diff --git a/.gitea/workflows/harbor-build-deploy.yml b/.gitea/workflows/harbor-build-deploy.yml index c86018c..3598a5b 100644 --- a/.gitea/workflows/harbor-build-deploy.yml +++ b/.gitea/workflows/harbor-build-deploy.yml @@ -1,6 +1,6 @@ name: Harbor Build Once → Deploy Many (Compose) -on: +"on": workflow_call: inputs: harbor_registry: @@ -10,6 +10,7 @@ on: type: string default: ci image_repo: + description: "Image repository name under harbor_project (example: myapp)" type: string required: true @@ -23,9 +24,8 @@ on: type: string default: linux/amd64,linux/arm64 - # IMPORTANT CHANGE deploy_runners_json: - description: 'JSON array of runner labels' + description: "JSON array of runner labels (example: [\"prod-1\",\"prod-2\"])" type: string required: true @@ -33,6 +33,7 @@ on: type: string default: . compose_args: + description: "Arguments after `docker compose`" type: string default: up -d --pull always --remove-orphans @@ -42,13 +43,20 @@ on: HARBOR_PULL_USERNAME: { required: true } HARBOR_PULL_PASSWORD: { required: true } -jobs: + outputs: + image_repo: + description: "Image repository (no tag/digest), e.g. harbor.hcmc.online/ci/myapp" + value: ${{ jobs.build_and_push.outputs.image_repo }} + image_digest: + description: "Content digest, e.g. sha256:..." + value: ${{ jobs.build_and_push.outputs.image_digest }} + image_ref: + description: "Immutable image ref, e.g. harbor.hcmc.online/ci/myapp@sha256:..." + value: ${{ jobs.build_and_push.outputs.image_ref }} -# ========================================================== -# BUILD ONCE (single powerful runner) -# ========================================================== +jobs: build_and_push: - name: Build & Push Image + name: Build & Push Image runs-on: devsg-atlantic outputs: @@ -58,6 +66,8 @@ jobs: steps: - uses: actions/checkout@v4 + + - uses: docker/setup-qemu-action@v3 - uses: docker/setup-buildx-action@v3 - name: Compute image metadata @@ -66,12 +76,17 @@ jobs: run: | set -euo pipefail IMAGE="${{ inputs.harbor_registry }}/${{ inputs.harbor_project }}/${{ inputs.image_repo }}" - SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-12) - BRANCH="${{ github.ref_name }}" + SHORT_SHA="$(echo "${{ github.sha }}" | cut -c1-12)" + RAW_BRANCH="${{ github.ref_name }}" + # Docker tags cannot contain slashes, spaces, etc. + BRANCH="$(echo "${RAW_BRANCH}" | tr "/\\" "-" | tr -c "A-Za-z0-9_.-" "-" | sed -E "s/^-+|-+$//g" | cut -c1-120)" + if [[ -z "${BRANCH}" ]]; then BRANCH="branch"; fi - echo "image_repo=$IMAGE" >> $GITHUB_OUTPUT - echo "sha_tag=sha-$SHORT_SHA" >> $GITHUB_OUTPUT - echo "branch_tag=$BRANCH" >> $GITHUB_OUTPUT + { + echo "image_repo=$IMAGE" + echo "sha_tag=sha-$SHORT_SHA" + echo "branch_tag=$BRANCH" + } >> "$GITHUB_OUTPUT" - name: Login Harbor (push) uses: docker/login-action@v3 @@ -80,7 +95,6 @@ jobs: username: ${{ secrets.HARBOR_PUSH_USERNAME }} password: ${{ secrets.HARBOR_PUSH_PASSWORD }} - # Cached multi-platform build - name: Build & Push Image id: build uses: docker/build-push-action@v6 @@ -89,21 +103,15 @@ jobs: file: ${{ inputs.dockerfile }} platforms: ${{ inputs.platforms }} push: true - tags: | ${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.sha_tag }} ${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.branch_tag }} ${{ steps.meta.outputs.image_repo }}:latest - cache-from: type=registry,ref=${{ steps.meta.outputs.image_repo }}:buildcache cache-to: type=registry,ref=${{ steps.meta.outputs.image_repo }}:buildcache,mode=max - -# ========================================================== -# DEPLOY MANY (fan-out runners) -# ========================================================== deploy: - name: Deploy to Fleet + name: Deploy to Fleet needs: build_and_push strategy: @@ -126,7 +134,6 @@ jobs: - name: Show image run: echo "Deploying ${{ needs.build_and_push.outputs.image_ref }}" - # Linux/macOS - name: Compose Up (Unix) if: runner.os != 'Windows' shell: bash @@ -137,7 +144,6 @@ jobs: set -euo pipefail docker compose ${{ inputs.compose_args }} - # Windows runners support - name: Compose Up (Windows) if: runner.os == 'Windows' shell: pwsh