fix: create tag and release atomically via gh release create - #14
Merged
Conversation
Previously the workflow did `git push origin TAG` (irreversible) and THEN `gh release create` as a separate step. If the second step failed (GitHub API hiccup, network blip, transient permissions issue), we'd be left with a tag on the remote but no corresponding Release — broken state requiring manual cleanup, and architect's upload-release-assets would retry uselessly against a Release that doesn't exist. GitHub's release-create endpoint accepts a `tag_name` + `target_commitish` and creates the tag as part of the same API call when it doesn't already exist. One operation, one failure point. Either both materialize or neither does. Side benefit: closes a small race window with architect's upload step. Previously there was ~1s between tag push and release creation; if CircleCI dispatched fast enough, upload-release-assets would start polling for a release that didn't exist yet (architect's built-in ~60s retry loop covered this, but better to not race at all). Trade-off named in the YAML comment: the tag becomes lightweight (a plain ref) instead of annotated. For our use — git describe, architect's tag filter, gitsemver, gh release view — both behave identically. The `github.actor` attribution that the previous annotated tag carried is also dropped; the release itself still shows up as created by github-actions[bot] either way, so the practical attribution doesn't really change. Drop the now-redundant `--verify-tag` flag (it was guarding against the failed-tag-push case that this change eliminates).
fiunchinho
force-pushed
the
atomic-tag-and-release-v2
branch
from
June 3, 2026 13:45
27900a3 to
30b63eb
Compare
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.
Summary
Today's flow is:
git push origin TAG← irreversiblegh release create TAG ...← can fail independentlyIf step 2 fails (GitHub API blip, transient permissions issue, network), we're left with a tag on the remote but no corresponding Release — a "stuck" state requiring manual cleanup, and architect's
upload-release-assetsjob retries uselessly against a Release that doesn't exist.GitHub's release-create endpoint accepts a
tag_name+target_commitishand creates the tag as part of the same API call when it doesn't already exist. One operation, one failure point. Either both materialize or neither does.Diff (~15 lines saved)
--verify-tag(was guarding against the failed-push case that no longer exists)git config user.name/email(was only needed for the annotated tag's metadata)Bonus: closes a race with architect
Previously there was a ~1s window between tag push and release creation. CircleCI dispatches on the tag push, so
architect/upload-release-assetscould start polling for a release that didn't yet exist. Architect's built-in ~60s retry loop covered this race, but better to not race at all — with the atomic approach, the release exists the moment the tag does.Trade-offs (explicit in the YAML comment)
git tag -awith message)github.actor(PR merger)github-actions[bot]For the giantswarm stack —
git describe,architect/*tag filters,gitsemver,gh release view— both tag types behave identically. The tagger-attribution change is small: the release itself is created bygithub-actions[bot]in both cases; only the tag's annotation differed. Nobody routinely inspects tag annotations.Test plan
v1.X.Yrelease exists with tag + notes, no separate "push tag" step in the workflow run output.release-2.xbranch and merging a conventional commit produces a Release on that branch's history (already exercised via--target $GITHUB_SHA).