decision: should release.sh check CI before it tags a commit? #519

Open
opened 2026-09-15 23:52:41 +00:00 by hexajon · 2 comments
Owner

What happens

scripts/release.sh never checks CI. Its preflight covers the working tree, the branch, the remote, GoReleaser, the token, the signing key, and the satellite repos. So a release can be cut from a red main, and nothing in the release path runs the gate: no tests, no govulncheck, no license inventory check.

v0.19.0 was released on 2026-09-15 while the push CI run for that commit was failing.

Open question

Should the preflight resolve the CI result for the commit being tagged, and if so, what does it do?

  1. Refuse when the run failed, and refuse when no run exists.
  2. Refuse on a failed run, but allow with a warning when no run exists.
  3. Warn only, never refuse.
  4. Nothing here, and rely on branch protection requiring CI instead (#499).

Acceptance

  • The decision is recorded, the chosen behaviour is implemented, and a release attempt behaves as decided.
## What happens `scripts/release.sh` never checks CI. Its preflight covers the working tree, the branch, the remote, GoReleaser, the token, the signing key, and the satellite repos. So a release can be cut from a red `main`, and nothing in the release path runs the gate: no tests, no govulncheck, no license inventory check. v0.19.0 was released on 2026-09-15 while the push CI run for that commit was failing. ## Open question Should the preflight resolve the CI result for the commit being tagged, and if so, what does it do? 1. Refuse when the run failed, and refuse when no run exists. 2. Refuse on a failed run, but allow with a warning when no run exists. 3. Warn only, never refuse. 4. Nothing here, and rely on branch protection requiring CI instead (#499). ## Acceptance - The decision is recorded, the chosen behaviour is implemented, and a release attempt behaves as decided.
hexajon changed title from release: refuse to tag a commit whose CI is not green to decision: should release.sh check CI before it tags a commit? 2026-09-15 23:54:17 +00:00
Author
Owner

There is a tension between blocking the release on failed CI and then failing to have a signed release. Not sure how to resolve yet.

There is a tension between blocking the release on failed CI and then failing to have a signed release. Not sure how to resolve yet.
Author
Owner

Decided: option 1. The preflight resolves the CI result for the commit being tagged. It refuses on a failed run, and it refuses when no run exists.

My earlier comment named a tension that is not real. I checked the signing path:

  • scripts/release.sh:211-218 needs the local GPG secret key in the keyring, and aborts when it is absent.
  • .goreleaser.yaml:82-96 signs checksums.txt by calling local gpg with GPG_FINGERPRINT.
  • scripts/release.sh:367 tags locally, and :394 verifies the signature before publish.

Every signature is made on the release machine. The forge signs nothing, and it must not. So a refusal cannot produce an unsigned release. It only delays the release until CI is green, which is the behaviour I want.

Refusing on a missing run is deliberate. A missing run is an unknown state, not a safe one. The fix is to make CI run for that commit, not to tag past the gap.

Build outline:

  • Add a CI step to the preflight, beside the existing working-tree, branch, remote, GoReleaser, token, and signing-key checks.
  • Resolve the run for the exact commit that gets tagged, not for the branch tip.
  • Refuse on a failed or cancelled run. Refuse when no run exists. Name the commit and the run URL in the error.
  • Treat a still-running run as not yet green, and say so.
  • Document the gate in docs/contributing/releasing.md, in the preflight list.

Acceptance stays as written: a release attempt against a red commit stops, and a release attempt against a commit with no run stops.

This is independent of #499. That issue makes main require the checks it already claims to require. This gate is in the release path, where the tag is cut.

Decided: option 1. The preflight resolves the CI result for the commit being tagged. It refuses on a failed run, and it refuses when no run exists. My earlier comment named a tension that is not real. I checked the signing path: - `scripts/release.sh:211-218` needs the local GPG secret key in the keyring, and aborts when it is absent. - `.goreleaser.yaml:82-96` signs `checksums.txt` by calling local `gpg` with `GPG_FINGERPRINT`. - `scripts/release.sh:367` tags locally, and `:394` verifies the signature before publish. Every signature is made on the release machine. The forge signs nothing, and it must not. So a refusal cannot produce an unsigned release. It only delays the release until CI is green, which is the behaviour I want. Refusing on a missing run is deliberate. A missing run is an unknown state, not a safe one. The fix is to make CI run for that commit, not to tag past the gap. Build outline: - Add a CI step to the preflight, beside the existing working-tree, branch, remote, GoReleaser, token, and signing-key checks. - Resolve the run for the exact commit that gets tagged, not for the branch tip. - Refuse on a failed or cancelled run. Refuse when no run exists. Name the commit and the run URL in the error. - Treat a still-running run as not yet green, and say so. - Document the gate in `docs/contributing/releasing.md`, in the preflight list. Acceptance stays as written: a release attempt against a red commit stops, and a release attempt against a commit with no run stops. This is independent of #499. That issue makes `main` require the checks it already claims to require. This gate is in the release path, where the tag is cut.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#519
No description provided.