fix(ci): make a mistyped release tag visible, and buildable - #239
Open
bnsoni wants to merge 3 commits into
Open
Conversation
A manually pushed tag that does not match the Docker Build trigger produced NOTHING — no run, no annotation, nothing in the Actions tab. On 2026-09-03 `os 0.139.0-patch-1` and `lms 0.76.1-patch-1` were pushed without the `v` prefix; `trigger-docker-build.yml` only fires on `v*`, so GitHub never created a run and it presented as "the build workflow didn't pick up" with nowhere to look. The version bumps themselves were correct — package.json at both tags already carried the `-patch-1` suffix, so the images would have published as new tags without clobbering anything. Only the prefix was missing. Two changes: - tag-guard.yml (new) fires on EVERY tag. A version-shaped tag that cannot build now fails loudly with the exact re-tag command in the annotation, instead of failing silently. Builds nothing, needs no secrets. - workflow_dispatch on trigger-docker-build.yml. The tag filter was the only trigger, so a mistyped tag left no way to build at all. Dispatch can build any existing ref, including the mistyped tag, via the ref dropdown. Deliberately NOT broadening the tag filter to accept bare semver: that would fragment the convention and allow a double build when both `X` and `vX` are pushed. One convention, enforced visibly, is the safer shape. Verified: YAML parses, actionlint reports no new findings, the guard script passes `bash -n`, and it was executed for real — exit 0 on `v0.139.0`, exit 1 with the re-tag command on `0.139.0-patch-1`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adding workflow_dispatch introduced a hazard that the tag-only trigger did not
have. reusable-spa-docker-build.yml names the image from package.json AND also
pushes `latest`:
FULL_URI="$REGISTRY/$IMAGE_NAME:$VERSION"
docker tag "$FULL_URI" "$REGISTRY/$IMAGE_NAME:latest"
So dispatching against `main` would rebuild an already-released image tag and
repoint `latest` at it. Before workflow_dispatch existed the only way in was a
`v*` tag push, a deliberate release act.
The guard keeps that property: dispatch is a RECOVERY path for a ref that is
already tagged, not a way to build a branch.
push refs/tags/v0.139.0 -> allowed
workflow_dispatch refs/tags/0.139.0-patch-1 -> allowed (the recovery case)
workflow_dispatch refs/heads/main -> REFUSED
workflow_dispatch refs/heads/feature/x -> REFUSED
Verified by executing the step's script body: exit 1 with the error annotation
on a branch ref. actionlint back to main's single pre-existing finding.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A manually pushed tag that does not match the Docker Build trigger produces nothing — no run, no annotation, nothing in the Actions tab.
On 2026-09-03,
os 0.139.0-patch-1andlms 0.76.1-patch-1were pushed manually.trigger-docker-build.ymlfires only onv*, so GitHub never created a run. It presented as "the build workflow didn't pick up", with an empty Actions tab and nowhere to look.Root cause
Missing
vprefix. That is the whole of it —v0.36.9-patch-1already exists in lms, so the-patch-Nconvention was right.The version bumps were correct too:
package.jsonat both tags already carried the-patch-1suffix, and since the image is named frompackage.jsonrather than the tag, they would have published as new ECR tags without overwriting0.139.0or0.76.1.The deeper defect is that there was no recovery path. The tag filter was the only trigger on this workflow, so a mistyped tag could not be built at all — the only fix was to push another tag — and the mistake generated zero signal.
Changes
tag-guard.yml(new) — fires ontags: ['**']. A version-shaped tag that cannot build now fails loudly:It builds nothing and needs no secrets. Non-version tags are ignored.
workflow_dispatchontrigger-docker-build.yml— lets you build any existing ref, including a mistyped tag, by picking it in the ref dropdown.What I deliberately did not do
Broaden the tag filter to accept bare semver. That fragments the convention and permits a double build if both
XandvXget pushed. One convention, enforced visibly, is the safer shape.Verification
actionlintbash -non the guard scriptTAG=v0.139.0TAG=0.139.0-patch-1v*,skills-v*,app-v*, bare semver, non-version)🤖 Generated with Claude Code