You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The mc Release workflow can be triggered both by a RELEASE.* tag push and by workflow_dispatch. Without per-tag serialization and explicit retry semantics, concurrent runs created duplicate same-tag Draft releases and split assets across failed jobs.
Incident evidence:
Published RELEASE.2026-08-26T00-00-00Z plus orphan Draft release ID 377272417 with 7 duplicate assets.
Published RELEASE.2026-08-26T17-15-27Z plus orphan Draft release ID 377309241 with 7 duplicate assets.
Tag-push Release run 32995378797 failed after a same-tag manual run had already created assets.
Selected semantics
Serialize release jobs by resolved tag with cancel-in-progress: false.
Validate the RELEASE.YYYY-MM-DDTHH-MM-SSZ tag, require it to resolve to the checkout, and pass it explicitly as GORELEASER_CURRENT_TAG.
Fail fast if exactly one published release exists for the tag.
Replace exactly one existing Draft from scratch through GoReleaser's replace_existing_draft.
Fail fast when more than one matching release exists; duplicate Draft cleanup is deliberate and manual.
Keep per-asset replacement disabled. Retry replaces the whole Draft; package upload has no --clobber.
Reconfirm that exactly one Draft exists immediately before package upload.
Leave a failed run's Draft available for inspection; the next retry replaces it.
Remove orphan Drafts 377272417 and 377309241 without touching the corresponding published releases.
Local implementation
Commit: f08111c6 ci: make release retries tag-idempotent
Release-state decisions live in buildscripts/check-release-state.sh with fixture coverage in _test.sh.
test-release.yml watches, syntax-checks, executable-checks, and runs both scripts.
The commit is local and unpushed; the hash will resolve on GitHub only after the follow-up PR is published.
Live read-only checks reject the current published tag, accept an absent tag before build, reject absent/published state when a Draft is required, and fail closed on an inaccessible repository.
make verifiers, go test ./..., bash syntax, and git diff --check pass locally.
Push a focused PR and require hosted CI green.
Exercise one controlled Draft build only after all source blockers are closed.
Verify a retry leaves exactly one Draft with one copy of every archive and package asset.
Verify a published-release rerun fails before any build or upload.
Do not create a new production tag until the remaining remote and controlled-Draft checks are complete. The existing published releases remain unchanged.
Problem
The mc Release workflow can be triggered both by a
RELEASE.*tag push and byworkflow_dispatch. Without per-tag serialization and explicit retry semantics, concurrent runs created duplicate same-tag Draft releases and split assets across failed jobs.Incident evidence:
RELEASE.2026-08-26T00-00-00Zplus orphan Draft release ID377272417with 7 duplicate assets.RELEASE.2026-08-26T17-15-27Zplus orphan Draft release ID377309241with 7 duplicate assets.32995378797failed after a same-tag manual run had already created assets.Selected semantics
cancel-in-progress: false.RELEASE.YYYY-MM-DDTHH-MM-SSZtag, require it to resolve to the checkout, and pass it explicitly asGORELEASER_CURRENT_TAG.replace_existing_draft.--clobber.377272417and377309241without touching the corresponding published releases.Local implementation
f08111c6 ci: make release retries tag-idempotentbuildscripts/check-release-state.shwith fixture coverage in_test.sh.test-release.ymlwatches, syntax-checks, executable-checks, and runs both scripts.Verification and close criteria
.github/goreleaser.yml.make verifiers,go test ./..., bash syntax, andgit diff --checkpass locally.Do not create a new production tag until the remaining remote and controlled-Draft checks are complete. The existing published releases remain unchanged.