From bb8634312d602c5cbcfa6b3801c721b7dd4d8ed2 Mon Sep 17 00:00:00 2001 From: efiten Date: Thu, 3 Sep 2026 23:05:16 +0200 Subject: [PATCH] ci: publish images on a tag ref, not only on a push event (#1951) **v3.10.0 produced no container image.** The build job reported `success` and pushed nothing. ## What happened `release-fast-path.yml` re-tags `:edge` to `:vX.Y.Z` when the `:edge` revision label matches the tagged commit, and dispatches `deploy.yml` when it does not. For v3.10.0 the tagged commit was documentation-only. The `paths-ignore` added in #1949 means documentation-only commits skip `deploy.yml`, so no `:edge` image was ever built for that commit, the labels did not match, and the fallback ran. **That part worked exactly as designed** and correctly refused to re-tag an image built from a different commit. Then `deploy.yml` skipped all five GHCR steps, because each was gated on `github.event_name == 'push'` and a `workflow_dispatch` is not a push: ``` 4. Build Go Docker image (local staging): success 5. Set up Docker Buildx: skipped 7. Log in to GHCR: skipped 9. Build and push to GHCR: skipped ``` **So the fallback has never been able to publish an image.** It dispatches a pipeline that cannot push. That stayed invisible for as long as the fast path kept succeeding, which it did until a release note happened to be the last commit before the tag. ## Fix Gate those five steps on a push **or** a tag ref: ```yaml if: ${{ github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') }} ``` A dispatch aimed at a tag now publishes. A dispatch aimed at a branch still does not, so this does not turn every manual run into a release. ## The version stamp needed no change Verified rather than assumed. `Compute build metadata` keys on `GITHUB_REF`, not on the event: ```bash if [[ "$GITHUB_REF" == refs/tags/v* ]]; then APP_VERSION="${GITHUB_REF#refs/tags/}"; else APP_VERSION="edge"; fi ``` The failed v3.10.0 run already logged `Build: version=v3.10.0 commit=5bad23b`. Only the publishing was missing. ## Not covered here `Release Artifacts` failed on the same run for an unrelated reason: the GitHub release had been created by hand before the workflow reached it, and `action-gh-release` cannot update an immutable release. That one is process, not code. Push the tag and let the workflow create the release. Once this merges, re-dispatching `deploy.yml` against `v3.10.0` publishes the images for the existing tag. No re-tagging needed. Co-authored-by: Claude Opus 5 (1M context) --- .github/workflows/deploy.yml | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cc1e74cb..4b0f09d3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -621,6 +621,18 @@ jobs: # ─────────────────────────────────────────────────────────────── # 3. Build & Publish Docker Image # ─────────────────────────────────────────────────────────────── + # The five GHCR steps below publish on a push to master (the :edge image) and + # on a tag ref. The tag half is not decoration: release-fast-path.yml re-tags + # :edge to :vX.Y.Z when the :edge revision label matches the tagged commit, + # and dispatches THIS workflow when it does not. That fallback previously + # produced no image at all, because a workflow_dispatch is not a push and + # every publishing step was gated on github.event_name == 'push'. It built + # locally, reported success, and pushed nothing. + # + # That went unnoticed until v3.10.0, where the tagged commit was + # documentation-only. Documentation-only commits skip this workflow (see the + # paths-ignore above), so no :edge image was ever built for it, the label + # comparison failed, and the fallback ran for the first time. build-and-publish: name: "🏗️ Build & Publish Docker Image" needs: [e2e-test] @@ -653,15 +665,15 @@ jobs: echo "Built Go staging image ✅" - name: Set up Docker Buildx - if: github.event_name == 'push' + if: ${{ github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') }} uses: docker/setup-buildx-action@v3 - name: Set up QEMU (arm64 runtime stage) - if: github.event_name == 'push' + if: ${{ github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') }} uses: docker/setup-qemu-action@v3 - name: Log in to GHCR - if: github.event_name == 'push' + if: ${{ github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') }} uses: docker/login-action@v3 with: registry: ghcr.io @@ -669,7 +681,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Extract Docker metadata - if: github.event_name == 'push' + if: ${{ github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') }} id: docker-meta uses: docker/metadata-action@v5 with: @@ -682,7 +694,7 @@ jobs: type=edge,branch=master - name: Build and push to GHCR - if: github.event_name == 'push' + if: ${{ github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') }} uses: docker/build-push-action@v6 with: context: .