Skip to content

workflows/release: tag after artifact checks#21073

Merged
yperbasis merged 13 commits into
erigontech:mainfrom
LarryArnault45:release-tag-after-artifact-checks
May 12, 2026
Merged

workflows/release: tag after artifact checks#21073
yperbasis merged 13 commits into
erigontech:mainfrom
LarryArnault45:release-tag-after-artifact-checks

Conversation

@LarryArnault45

@LarryArnault45 LarryArnault45 commented May 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #20648.

Move release tag creation out of build-release and into publish-release, after all artifacts are downloaded and verified. The tag is pinned to the exact commit that built the artifacts (needs.build-release.outputs.commit-id), not to branch HEAD. build-release keeps an early "tag must not exist" pre-flight so an operator-error re-dispatch fails fast.

Other changes

  • gh release create gets --verify-tag; the now-dead --target is removed (GitHub ignores target_commitish for existing tags).
  • gh release create failure exits non-zero so the In-case-of-failure rollback removes the just-pushed tag.
  • gh release view after success is best-effort (|| true) so a transient view failure can't trigger a rollback against an already-published release.
  • Manual-fallback instructions are printed when gh release create fails; the snippet recreates the tag at the verified build commit via --target and uploads the same asset set as the automated path, including the checksums file.
  • The rollback fires only when publish-release actually ran and didn't succeed (failure or cancelled), not when it was skipped due to an upstream failure — so a build-release pre-flight rejecting a pre-existing tag does not cause the rollback to delete that tag.

lupin012 and others added 3 commits May 10, 2026 16:03
- publish-release checkout uses fetch-depth: 1 (only the build commit is
  needed to create and push the tag).
- Drop the App-token generation from build-release. With the tag push
  moved out of this job, the implicit GITHUB_TOKEN (contents: read) is
  enough for the read-only checkout and ls-remote check.
- Fail the publish-release step when gh release create exits non-zero
  so In-case-of-failure removes the just-pushed tag rather than leaving
  it orphaned. The manual-instructions output still prints.
- Tighten the new publish-time checkout condition to also gate on
  release_version != '', mirroring the tag step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the release GitHub Actions workflow to avoid creating/pushing the release git tag until after all build artifacts have been downloaded and verified in the publish job, preventing premature tags when sanity checks fail.

Changes:

  • Remove tag creation from build-release, keeping only a fast-fail “tag already exists” check.
  • After artifact verification in publish-release, checkout the resolved build commit and create/push the release tag there.
  • Add --verify-tag to gh release create, and ensure failures propagate so the rollback job can remove the pushed tag.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
…fort

- Comment the tag-existence recheck in publish-release: it guards
  against a concurrent release run pushing the same tag between
  build-release's check and the push here.
- Make `gh release view` after `gh release create` non-fatal. The
  release is already created at that point, so a transient view
  failure must not fail the job and trigger the In-case-of-failure
  rollback (which would delete the tag the freshly-created release
  points at).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
yperbasis and others added 2 commits May 11, 2026 20:25
- Drop --target from the live gh release create. With --verify-tag the
  tag is required to already exist, and the GitHub API ignores
  target_commitish when the tag exists, so --target was dead code.
  Remove the now-unused GITHUB_RELEASE_TARGET env var.
- Manual fallback: print a NOTE that the just-pushed tag will be
  removed by the rollback job, and change the printed gh release
  create snippet to --target the build commit-id. Previously it
  printed --target <checkout_ref> (a branch), which after rollback
  would recreate the tag at branch tip rather than the verified
  build commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tighten the publish-time tag handling so a concurrent release dispatch
of the same version cannot cause this run's rollback to delete the
other run's tag.

- Tag push is now idempotent against this run's build commit. If the
  tag is already on remote at the same commit-id, continue rather than
  fail; only a mismatching tag is an error.
- Rollback compares the remote tag's commit to the build commit-id and
  only deletes when they match. If the tag points elsewhere (e.g. a
  concurrent run pushed it) it is left alone. An unknown/empty build
  commit (e.g. build-release was cancelled before resolving it) is
  treated as "not ours" and skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
git ls-remote --tags <tag> returns two lines for an annotated tag:
the tag object SHA on the bare ref and the commit SHA on the peeled
${tag}^{} ref. awk '{print $1}' then yields a multi-line string,
which breaks the equality check against BUILD_COMMIT — both the
idempotent fast-path in the tag-push step and the "is this ours"
check in the rollback step would silently misfire.

Apply the same fix to both: query the peeled ^{} ref first for the
commit SHA, fall back to the bare ref for lightweight tags (which
we create) or for missing tags (returns empty).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yperbasis yperbasis requested a review from lystopad May 11, 2026 18:43
Close the narrow race where two concurrent release dispatches of the
same version both reach publish-release with the same build commit:
Run A pushes the tag and creates the release; Run B takes the
idempotent fast-path, then fails at gh release create ("release
already exists"). Without this gate, Run B's rollback would see the
tag at its BUILD_COMMIT and delete it, orphaning Run A's release.

- Tag-push step records tag_pushed=true to step output, but only on
  the path that actually pushed the tag — not the idempotent
  fast-path, which means a different run owns the tag.
- Expose as publish-release job output.
- Gate In-case-of-failure on tag_pushed == 'true' so the rollback
  runs only when this run pushed the tag. The step-level SHA-match
  check remains as a safety net.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
…pushed; include checksums in snippet

In the manual-recovery branch of publish-release, the printed NOTE
assumed the rollback would remove the just-pushed tag — but rollback
is gated on tag_pushed, so in the idempotent fast-path (another run
already owned the tag) the tag is left in place. Split the message
on steps.push_tag.outputs.tag_pushed so the operator sees accurate
guidance in both paths. Also add the checksums file to the example
gh release create command so a manual publish produces the same
asset set as the automated path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml Outdated
…s when release exists

Two follow-ups raised by Copilot on the previous revision:

push_tag: a concurrent run that pushes the same tag at the same
BUILD_COMMIT between our ls-remote check and our git push made the
push fail noisily even though the end state was correct. Factor the
SHA resolution into a small function and re-resolve on push failure:
if the remote tag now matches BUILD_COMMIT, treat it as the
idempotent fast-path (tag_pushed stays unset); any other state is a
real error.

In-case-of-failure rollback: SHA equality alone wasn't enough to
guarantee safe deletion. If a concurrent run took the idempotent
push path and successfully created the GitHub Release while ours
failed, deleting the tag would orphan its Release. Before deleting,
gh release view the tag and skip when a release already exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yperbasis yperbasis requested a review from Copilot May 12, 2026 12:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/release.yml Outdated
…p core fix

Revert the concurrent-dispatch protections added across the last few
commits. They defend against a scenario (two simultaneous manual
dispatches of the same release version) that is operationally rare for
this workflow_dispatch-only workflow, while adding non-trivial shell
complexity. The pre-flight "tag must not exist" check in build-release
already catches the realistic operator-error case (re-dispatch after a
typo).

What remains is the minimal fix for erigontech#20648 plus two defensible
nice-to-haves:
- Tag creation moved out of build-release into publish-release, after
  artifacts are downloaded and verified.
- Tag pinned to needs.build-release.outputs.commit-id (not branch HEAD).
- gh release create --verify-tag (drops the now-dead --target).
- Manual-fallback instructions stay, with the checksums file in the
  printed snippet so a manual publish produces the same asset set.
- gh release view after success is best-effort (|| true) so a transient
  view failure does not trigger rollback against an already-published
  release.

Rollback returns to the original simple model: if publish-release did
not succeed, delete the tag if present on the remote. tag_pushed
output, SHA re-verification, peeled ^{} resolution, and the
gh release view race-guard are all gone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yperbasis yperbasis enabled auto-merge May 12, 2026 13:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/release.yml Outdated
…fast-failed

The rollback's gate was `publish-release.result != 'success'`, which also
fires when publish-release is `skipped` because an upstream job failed —
including the tag-already-exists pre-flight in build-release. In that
case publish-release never reached the tag-push step, so any tag named
${RELEASE_VERSION} on the remote is pre-existing. Deleting it undoes the
protection the pre-flight was offering.

Exclude `skipped` from the rollback gate so it fires only when
publish-release actually ran (failure or cancellation), the cases where
this run may have pushed the tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yperbasis yperbasis added this pull request to the merge queue May 12, 2026
Merged via the queue into erigontech:main with commit 428c559 May 12, 2026
55 of 56 checks passed

@lystopad lystopad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Looks good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

release.yml: git tag created before sanity checks

5 participants