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) <noreply@anthropic.com>
This commit is contained in:
efiten
2026-09-03 23:05:16 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent 5bad23b46a
commit bb8634312d
+17 -5
View File
@@ -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: .