Skip to content

fix(ci): never leave a stale signoff success when PR context fails - #422

Open
Kyleasmth wants to merge 6 commits into
mainfrom
YPE-5942/gate-stale-status
Open

Kyleasmth wants to merge 6 commits into
mainfrom
YPE-5942/gate-stale-status

Conversation

@Kyleasmth

@Kyleasmth Kyleasmth commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Closes YPE-5942.

Problem

context resolves the head SHA for the whole workflow. When it fails, every downstream job is skipped and whatever status was last written to that SHA stands, including a success whose signoff comment has since been edited or deleted. A major release could keep a green required check with its approval evidence gone.

Greptile flagged the same thing on the Expo port (#201) and agreed to defer it to this upstream fix.

Change

  1. Retry the PR lookup three times instead of dying on the first blip.
  2. Add context_unresolved, which posts a failing status when context fails. It runs on every event, not just pull_request: issue_comment payloads carry no head SHA, so it reads refs/pull/N/head over git. That is a different backend from the REST call that just failed, and needs no scope beyond contents: read.

The job is gated on failure, not != success, so a cancelled run superseded by a newer one does not paint the PR red.

Tests

.github/scripts/major-release-signoff.test.sh, 37 passing in ~2.5s.

Five new cases cover the retry (recovery and give-up, asserted by call count) and the status job (payload head, git-recovered head, unrecoverable head). Each was mutation-tested: breaking any one of the five production paths turns the suite red. A loop that never retries, a job re-gated to pull_request, a dropped SHA recovery, an ignored payload SHA, and a removed SHA validation are all caught.

The previous revision carried a RETRY_BACKOFF_SECONDS env override so the suite could skip the backoff. That was test-only surface in a production workflow; the suite now stubs sleep instead.

https://claude.ai/code/session_01Gnt93sVjs6ApXSzkDC2efU

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no new actionable failure was established.

Summary

The PR retries PR context lookup and adds a fallback job that posts a failing signoff status when context resolution fails. It also adds an empty changeset and regression tests.

  • The new job uses the pull-request payload SHA or, for comment events, the PR’s git head ref.
  • Greptile automatically discovered a related ticket that helped explain the purpose of this PR: prevent revoked signoff evidence from leaving an earlier successful status in place.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Event[PR or comment event] --> Context[Resolve PR context: up to 3 attempts]
  Context -->|success| Gate[Evaluate release and signoff]
  Context -->|failure| Head{Head SHA available?}
  Head -->|PR payload| Failure[Post failing signoff status]
  Head -->|Comment: git PR head ref| Failure
  Head -->|No recoverable SHA| NoStatus[Fail job without posting a status]
Loading

Reviews (5) · Last reviewed commit: "Merge branch 'main' into YPE-5942/gate-s..."

Kyleasmth and others added 2 commits September 21, 2026 16:33
When `context` failed the gate job was skipped entirely, so whatever status
was last written to that head SHA stood. A signoff edited or deleted without
a push therefore left an earlier `success` green on an unsigned major.

The PR lookup now retries, and a `pull_request` run whose context still fails
posts a failing status from the event payload. `issue_comment` payloads carry
no head SHA, so that path relies on the retry and on the next push.

Found by Greptile on the RN Expo port (#201); the condition is identical in
both workflows, so this lands here first.
@changeset-bot

changeset-bot Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6807b30

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Kyleasmth Kyleasmth self-assigned this Sep 23, 2026
Comment thread .github/workflows/major-release-signoff.yml

@jhampton jhampton left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Interestingly, this seems like it also forces a changeset to be present, and I think that's right...except for the "pure" DevOps cases. At a minimum, can you make it clear in the wording that PR's require a changeset where this logic is tripped?

Comment thread .github/workflows/major-release-signoff.yml
cameronapak
cameronapak previously approved these changes Sep 24, 2026

@cameronapak cameronapak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review

YPE-5942

Summary

Standards: 0 must-fix. Spec: 0 must-fix. Primary concern: none. One non-blocking suggestion would make the regression test prove that the fallback status is actually red.

Review evidence
  • Scope: reviewed revision, YPE-5942, the complete PR diff, surrounding workflow, tests, permissions, and existing review discussion.
  • Method: independently evaluated repository standards, ticket intent, correctness, cancellation, retries, event payloads, SHA recovery, and the combined result with current main.
Behavior or check Method / command Result Evidence source
CI script regressions pnpm test:ci-scripts 49 passed Coordinator
Combined PR and current main Synthetic merge plus pnpm test:ci-scripts 50 passed, including 38 signoff tests Coordinator
Formatting and patch integrity Prettier and git diff --check Passed Coordinator
Test detects a green fallback mutation Changed state=failure to state=success in a temporary copy It did not; all 37 tests still passed Coordinator
  • Limits: no live GitHub API outage was induced. GitHub event and status semantics were source-traced and exercised through the repository's mocks.
  • CI and bot review: CI is green at the reviewed revision. Greptile's missing-changeset finding is addressed by the empty changeset, though its thread remains open.
  • Event: APPROVE.

Written by Code Reviewer bot on behalf of Cam.

Comment thread .github/scripts/major-release-signoff.test.sh Outdated
"https://x-access-token:$GH_TOKEN@github.com/$REPOSITORY" \
"refs/pull/$EVENT_ISSUE_NUMBER/head" | cut -f1) || HEAD_SHA=""
fi
if ! [[ "$HEAD_SHA" =~ ^[0-9a-f]{40}$ ]]; then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

praise: Validating the recovered value as a full SHA before writing status keeps this fallback narrow and fail-closed.

For Agents: event-safe SHA recovery

This path prefers the immutable payload SHA for pull_request, uses the exact pull ref only when issue_comment lacks that field, and refuses to address a status when neither source yields a valid commit. The separate failure-only job also avoids turning superseded cancellations into misleading red statuses.

Written by Code Reviewer bot on behalf of Cam.

@cameronapak cameronapak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review

YPE-5942

Summary

Standards: 0 must-fix. Spec: 0 must-fix. Primary concern: none. The prior test-coverage suggestion is resolved.

Review evidence
  • Scope: reviewed revision, the complete current PR, changes since the prior review, both merges from main, YPE-5942, and existing review threads.
  • Method: traced the status fallback and strengthened test assertions, then reran the focused suite and mutations from the earlier finding.
Behavior or check Method / command Result Evidence source
CI script regressions pnpm test:ci-scripts 50 passed Coordinator
Green fallback mutation Changed state=failure to state=success in a temporary copy Detected: 2 tests failed Coordinator
Successful fallback-job mutation Changed the fallback's final exit to zero in a temporary copy Detected: 2 tests failed Coordinator
Formatting and patch integrity Prettier and git diff --check Passed Coordinator
  • Limits: no live GitHub API outage was induced. Event and status behavior remains covered through source tracing and repository mocks.
  • CI and bot review: all checks passed at the reviewed revision.
  • Event: APPROVE.

Written by Code Reviewer bot on behalf of Cam.

[[ "$call" == *"target_url=https://example.invalid/run"* ]] || problem="${problem:-no target_url}"
[[ "$call" == *"Could not resolve PR context"* ]] || problem="${problem:-no description}"
# The job exits nonzero so the check is red in the PR UI, not merely recorded.
[ "$result" -ne 0 ] || problem="${problem:-job exited 0}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

praise: Checking the posted failure payload and the job result closes the exact false-confidence gap from the earlier test.

For Agents: fail-closed regression coverage

The test now proves both observable outcomes: the commit receives the major-release-signoff failure status, and the workflow job remains red. Independent mutations to post success or exit zero each fail the focused cases.

Written by Code Reviewer bot on behalf of Cam.

This branch has not been deployed

No deployments
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.

3 participants