Skip to content

fix(release): mirror verified gate into the PR status rollup - #5457

Merged
clubanderson merged 1 commit into
kubestellar:v4from
Danathar:fix/5356-gate-status
Sep 1, 2026
Merged

fix(release): mirror verified gate into the PR status rollup#5457
clubanderson merged 1 commit into
kubestellar:v4from
Danathar:fix/5356-gate-status

Conversation

@Danathar

@Danathar Danathar commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Problem

Automated tagged releases reach the protected merge into v4 and are rejected for the full retry window:

Required status check "gate" is expected. (HTTP 405)

The release workflow has already observed a successful gate check-run on the exact release commit at that point. Nevertheless, release PRs such as #5402 remained blocked and v4.0.1 could not be cut.

Root cause

The release commit earns gate by dispatching docker.yml on a throwaway release-gate/v<version> branch. That proves the exact SHA, but a workflow_dispatch check-run has no pull-request association: its pull_requests list is empty, including when the workflow is dispatched after the release PR exists.

Branch protection evaluates the release PR's required-context rollup. That rollup contained the SHA-scoped dco and tide commit statuses but never the successful workflow-dispatch gate check-run, so the protected merge correctly reported gate as missing.

The post-PR re-dispatch added by #5363 cannot repair that representation mismatch. #5402 had a second green gate suite newer than every empty PR-open suite by 35 seconds and still received the same 405 for the entire merge window. Recency is not the discriminator; PR association is.

Implementation

  • .github/workflows/tagged-release.yml
    • grants statuses: write only to the release job, while explicitly preserving that job's existing permissions;
    • after the preceding step verifies docker.yml's gate check-run on the exact release SHA, posts gate: success through the commit Statuses API;
    • posts that status before opening the release PR, so its required-context rollup can consume the SHA-scoped result;
    • fails closed if the status POST fails: no PR, merge, tag, or GitHub Release is attempted;
    • removes the ineffective 30-second settle plus post-PR docker re-dispatch/wait race;
    • preserves the actual gh pr create response on failure instead of masking the diagnostic;
    • keeps the existing SHA-keyed merge API and its server-side branch-protection enforcement unchanged.
  • src/scripts/test-release-push-retry.sh
    • stubs and records the new Statuses API call;
    • proves the required order is status publication, PR creation, then merge;
    • proves a status failure stops before PR creation and tagging;
    • proves a PR-creation failure preserves the API response and stops before merge/tagging;
    • replaces the obsolete re-dispatch pin with structural assertions for the exact status endpoint, gate: success payload, job permission, and ordering.
  • src/docs/releases.md documents the actual scratch-check, status-mirror, protected-PR merge, and cleanup flow.
  • .github/workflows/docker.yml corrects the release-gate archaeology while preserving the ordinary PR gate job unchanged.

Design and safety invariants

The commit status is a transport for an already-earned verdict, not a second gate implementation. A missing, red, or timed-out docker check-run stops the preceding step, so it is impossible for this path to post success without first accepting docker.yml's result on the same commit_sha. The status POST itself is fail-closed.

The existing check-run remains the source of truth and remains what the workflow waits on. A commit status is used only because it is SHA-scoped and therefore visible to the release PR without a check-suite/PR association. GitHub's protected merge endpoint still makes the final decision, and the sha= argument still prevents merging a moved head.

statuses: write is job-scoped rather than workflow-wide. No PAT, GitHub App, repository secret, branch-protection bypass, force push, or protection configuration change is introduced.

Rejected alternatives:

  • Re-dispatching docker.yml after PR creation was measured and still produced pull_requests: []; it cannot enter the PR rollup and only adds a race and up to 10 minutes of waiting.
  • Opening the PR with a PAT/App token could allow PR workflows to run, but adds credential provisioning and ownership while reintroducing scheduling/race dependencies that the SHA-scoped status does not have.
  • Removing gate from branch protection would weaken protection for every other v4 update and is unnecessary.

Verification

  • bash src/scripts/test-release-push-retry.sh — PASS: 10 execution scenarios plus workflow-wiring assertions.
  • bash src/scripts/check-release-lines.sh — PASS.
  • bash src/scripts/check-no-image-attestations.sh — PASS.
  • bash src/scripts/check-action-pins.sh .github/workflows — PASS with upstream action repositories reachable.
  • bash -n src/scripts/test-release-push-retry.sh — PASS.
  • git diff --check — PASS.

The protected release merge itself cannot be exercised from a fork; the next release attempt is the end-to-end confirmation. This PR deliberately does not change ordinary contributor PR gate behavior, image publication, version derivation, release deferral, tag retries, or GitHub Release creation.

Fixes #5356

— hive: backend=codex

The release workflow verifies gate through a workflow_dispatch check-run on its scratch branch, but those check-runs have no pull-request association. The protected release PR therefore omits gate from its required-context rollup and rejects every merge with HTTP 405, even when a newer gate check-run is green.

After the exact-SHA gate wait succeeds, publish gate:success as a SHA-scoped commit status before opening the PR. Fail closed if that POST fails, remove the ineffective post-PR re-dispatch race, preserve gh pr create diagnostics, and document the corrected protection flow.

Extend the release harness to prove status/PR/merge ordering and both new failure paths.

Fixes kubestellar#5356

Signed-off-by: Danathar <doug.baggett@gmail.com>
@kubestellar-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign danathar for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added dco-signoff: yes Indicates the PR's author has signed the DCO. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Sep 1, 2026
@clubanderson
clubanderson merged commit ccb1885 into kubestellar:v4 Sep 1, 2026
44 of 45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Release merge rejected: gate is a check-run on a scratch branch, protection wants a status on v4

2 participants