ci: publish docker image on push to main#435
Conversation
Greptile SummaryThis PR adds an automatic push trigger on
Confidence Score: 3/5Safe to merge for the trigger and tag logic itself, but the missing concurrency group means two rapid pushes to main can produce a The .github/workflows/docker_publish.yaml — needs a concurrency group before the jobs block.
|
| Filename | Overview |
|---|---|
| .github/workflows/docker_publish.yaml | Adds push-to-main trigger and TAGS_INPUT env var to keep latest in sync; missing concurrency group creates a race condition that can produce mixed-arch manifest lists under consecutive pushes. |
Sequence Diagram
sequenceDiagram
participant G as GitHub (push to main)
participant W as Workflow Trigger
participant BA as build-image (amd64)
participant BAR as build-image (arm64)
participant M as publish-manifest
participant R as GHCR Registry
G->>W: push event on main
W->>BA: "start (TAGS_INPUT=latest)"
W->>BAR: "start (TAGS_INPUT=latest)"
BA->>R: push latest-amd64
BAR->>R: push latest-arm64
BA-->>M: done
BAR-->>M: done
M->>R: imagetools create latest
M->>R: imagetools create sha-short
Note over W,R: Without concurrency group two runs can interleave producing a latest manifest that mixes arch layers from different commits
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
.github/workflows/docker_publish.yaml:1-22
**Missing concurrency group risks mixed-arch `latest` manifests**
The new push trigger means two workflow runs can be in flight simultaneously for consecutive commits to `main`. Because the arch-specific tags (`latest-amd64`, `latest-arm64`) are shared across runs, run A could push `latest-amd64` from commit 1 while run B has already pushed `latest-arm64` from commit 2. The `publish-manifest` job of either run then assembles a manifest list pointing to images from *different* commits — a silently corrupted `latest` image.
Adding a `concurrency` block before `jobs:` serialises (or cancels-and-restarts) builds so the arch-specific layers and manifest always come from the same commit.
Reviews (1): Last reviewed commit: "ci: publish docker image on push to main" | Re-trigger Greptile
| @@ -15,6 +17,9 @@ permissions: | |||
| env: | |||
| REGISTRY: ghcr.io | |||
| IMAGE_NAME: ${{ github.repository }} | |||
| # On push to main, inputs.tags is empty, so fall back to "latest" so the | |||
| # latest tag tracks main. Manual dispatch still honors custom tags. | |||
| TAGS_INPUT: ${{ inputs.tags || 'latest' }} | |||
There was a problem hiding this comment.
Missing concurrency group risks mixed-arch
latest manifests
The new push trigger means two workflow runs can be in flight simultaneously for consecutive commits to main. Because the arch-specific tags (latest-amd64, latest-arm64) are shared across runs, run A could push latest-amd64 from commit 1 while run B has already pushed latest-arm64 from commit 2. The publish-manifest job of either run then assembles a manifest list pointing to images from different commits — a silently corrupted latest image.
Adding a concurrency block before jobs: serialises (or cancels-and-restarts) builds so the arch-specific layers and manifest always come from the same commit.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/docker_publish.yaml
Line: 1-22
Comment:
**Missing concurrency group risks mixed-arch `latest` manifests**
The new push trigger means two workflow runs can be in flight simultaneously for consecutive commits to `main`. Because the arch-specific tags (`latest-amd64`, `latest-arm64`) are shared across runs, run A could push `latest-amd64` from commit 1 while run B has already pushed `latest-arm64` from commit 2. The `publish-manifest` job of either run then assembles a manifest list pointing to images from *different* commits — a silently corrupted `latest` image.
Adding a `concurrency` block before `jobs:` serialises (or cancels-and-restarts) builds so the arch-specific layers and manifest always come from the same commit.
How can I resolve this? If you propose a fix, please make it concise.
🗒️ Description / Motivation
The
docker_publishworkflow wasworkflow_dispatch-only, so the publishedlatestGHCR image only refreshed when someone manually dispatched the workflow and otherwise drifted behindmain. The issue asks that every commit tomainupdate thelatestDocker tag automatically, which is what this change does.What Changed
The single file touched is
.github/workflows/docker_publish.yaml. Apushtrigger onmainnow runs alongside the existingworkflow_dispatch. Becauseinputs.tagsis empty on a push event, a workflow-levelTAGS_INPUT: ${{ inputs.tags || 'latest' }}env now provides the effective tag list, and the two${{ inputs.tags }}reads (thePrepare tagsstep and theCreate multi-arch manifestsstep) consume$TAGS_INPUTinstead.Correctness / Behavior Guarantees
Manual dispatch behaves exactly as before, since
TAGS_INPUTfalls through to whatever the user passed ininputs.tags, so custom comma-separated tags still expand unchanged. On a push tomainthe list resolves tolatest, producing the samelatest+sha-<short>manifest that a dispatch withtags=latestalready produced. The one behavior change worth flagging for reviewers is thatlatestnow moves on everymaincommit; nothing inside the repo consumes the image tag, so this only affects external consumers who pinlatest.Tests Added / Run
No automated tests apply to a workflow trigger change. I confirmed the file still parses with
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/docker_publish.yaml'))"and hand-traced the tag derivation: a dispatch withtags=latest,v0.1.0still expands both tags, while a push with emptyinputs.tagsresolves tolatest.Related Issues / PRs
Closes #94
✅ Verification Checklist
make fmt— N/A, this PR changes only workflow YAML and no Rust sourcemake lint(clippy with-D warnings) — N/A, no Rust source changedcargo test --workspace --release— N/A, no Rust source changed; YAML validated viayaml.safe_loadinstead