ci(docker): publish a sortable main-<commit UTC>-<sha7> relay tag (#8240)

## Summary

Each push to main adds one more tag to the relay image manifest that
`docker.yml` already publishes:

- `:main-<YYYYMMDDHHmmss>-<sha7>` (UTC commit time)
- `:debug-main-<YYYYMMDDHHmmss>-<sha7>` on the debug manifest

`:main`, `:sha-<7>`, and the release tags don't change.

**Why:** `:sha-<7>` has no ordering, so a deploy tool that wants "the
newest main build" has to fetch metadata for every tag before it can
sort. Our staging promotion warehouse (Kargo, `NewestBuild`) does that
on every discovery cycle, against about 1,700 `sha-*` tags (4,800 total)
in `ghcr.io/block/buzz`. That's slow, it hits registry rate limits, and
one failed fetch aborts the whole cycle. The timestamp prefix makes the
tag sort lexically in build order. A `Lexical` selector with
`^main-\d{14}-[0-9a-f]{7}$` can then pick the newest build from the tag
list alone and fetch only the tags it keeps.

Details, checked against the pinned `docker/metadata-action` v6.1.0
(`80c7e94d`):

- `{{sha}}` is the 7-char short sha (`defaultShortShaLength = 7`), the
same value as `:sha-<7>`.
- `{{commit_date}}` formats in UTC by default. On a push it uses the
event's `commits[].timestamp`, so rerunning a commit produces the same
tag.
- `type=raw` inherits the flavor prefix, so the merge job's debug leg
emits `debug-main-…`. That's the same mechanism that produces
`debug-main` today.
- `enable=` limits the tag to `push` on `refs/heads/main`. Release tags,
rescue dispatches, and PRs never get it.

On main's last 40 commits, author time and committer time are the same
instant, and both increase monotonically. A commit pushed with a
backdated timestamp would sort below newer builds and just wouldn't be
auto-picked; the next push supersedes it.

**What got simpler:** this adds one tag line in each of the two places
that already mirror the tag matrix, plus header docs. In return,
downstream tooling no longer needs per-tag metadata fetches to find the
newest build.

### Related issue

N/A (staging rollout tooling). The downstream warehouse and tag-guard
changes land separately and don't switch over until this tag has been
published.

### Testing

- `scripts/test-relay-image-eligibility-workflow.sh` and
`scripts/test-release-ref-contract.sh` pass at `9ba1d8b7f`.
- PR runs don't push images (`push: false`), so the first real tag
appears on the first main push after merge. I'll check the registry for
`main-<14 digits>-<sha7>` and `debug-main-…` on that manifest.

---------

Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
This commit is contained in:
Luke Tornquist
2026-10-13 15:47:53 -04:00
committed by GitHub
parent 40c1c474e7
commit d6dc813290
3 changed files with 20 additions and 4 deletions

View File

@@ -16,8 +16,8 @@ name: Docker image
# the relay image version tracks crates/buzz-relay/Cargo.toml, never desktop.
#
# Triggers:
# - push to main → :main + :sha-<7>
# + :debug-main + :debug-sha-<7>
# - push to main → :main + :sha-<7> + :main-<commit UTC>-<7>
# + the matching :debug-* tags
# - push tags relay-v*.*.* → :{version} + :{major}.{minor} + :{major}
# + matching :debug-* tags
# (+ :latest/:debug-latest for stable releases)
@@ -34,6 +34,12 @@ name: Docker image
# intact) and the bare version flows straight to the semver parser. On a
# real push event value= is empty and the match strips relay-v from the ref.
#
# :main-<YYYYMMDDHHmmss>-<7> names the same main build as :sha-<7>, prefixed
# with its UTC commit time so the tag sorts by build order. Kargo's Lexical
# strategy picks the newest from the tag list alone; :sha-<7> cannot be
# ordered without fetching every image's metadata. It uses the commit date,
# not the run date, so a rerun of the same commit re-pushes the same tag.
#
# The :latest tag tracks the latest STABLE relay release: metadata-action's
# `flavor.latest=auto` (its default) emits :latest only for non-prerelease
# semver, so relay-v0.3.0-rc.1 publishes :0.3.0-rc.1 without moving :latest,
@@ -162,6 +168,7 @@ jobs:
type=semver,pattern={{version}},match=^relay-v(.*)$,value=${{ inputs.version }}
type=semver,pattern={{major}}.{{minor}},match=^relay-v(.*)$,value=${{ inputs.version }}
type=semver,pattern={{major}},match=^relay-v(.*)$,value=${{ inputs.version }}
type=raw,value=main-{{commit_date 'YYYYMMDDHHmmss'}}-{{sha}},enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
labels: |
org.opencontainers.image.title=Buzz
org.opencontainers.image.description=WebSocket relay server for the Buzz communications platform
@@ -371,6 +378,7 @@ jobs:
type=semver,pattern={{version}},match=^relay-v(.*)$,value=${{ inputs.version }}
type=semver,pattern={{major}}.{{minor}},match=^relay-v(.*)$,value=${{ inputs.version }}
type=semver,pattern={{major}},match=^relay-v(.*)$,value=${{ inputs.version }}
type=raw,value=main-{{commit_date 'YYYYMMDDHHmmss'}}-{{sha}},enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- name: Create and push manifest list
id: manifest

View File

@@ -480,8 +480,8 @@ Every Pod the chart renders — relay, pairing relay, storage accounting, and th
deletion drain operator job — carries a chart-owned
`tags.datadoghq.com/version` label derived from the deployed image:
`image.tag` when set, otherwise `image.digest`, otherwise `Chart.AppVersion`.
The tag is preferred because it is the readable build name (`sha-<commit>`)
dashboards already use; promotion tooling writes it together with the digest
The tag is preferred because it is the readable build name (`sha-<sha7>`, or
`main-<UTC commit time>-<sha7>` for Kargo-promoted main builds) dashboards use; promotion tooling writes it together with the digest
that actually pins the image.
```yaml

View File

@@ -52,6 +52,14 @@ fi
grep -q 'verify-release-ref\.sh' "$repo_root/.github/workflows/release.yml"
grep -q 'verify-release-ref\.sh' "$repo_root/.github/workflows/docker.yml"
# Kargo's buzz-image warehouse selects Lexical over ^main-[0-9]{14}-[0-9a-f]{7}$;
# a drifted format stops Freight discovery silently, so pin both image legs.
sortable_main_tag=" type=raw,value=main-{{commit_date 'YYYYMMDDHHmmss'}}-{{sha}},enable=\${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}"
sortable_count="$(grep -Fxc "$sortable_main_tag" "$repo_root/.github/workflows/docker.yml" || true)"
if [ "$sortable_count" != 2 ]; then
echo "docker.yml must publish the sortable main-<UTC>-<sha7> tag on both image legs (found $sortable_count)" >&2
exit 1
fi
grep -q 'test-release-ref-contract\.sh' "$repo_root/.github/workflows/ci.yml"
"$repo_root/scripts/test-signed-canary-contract.sh"
"$repo_root/scripts/test-desktop-release-cache-key.sh"