fix(ship): merge-train gates on CI — fetch check-runs in sync [ROA-274]#107
Merged
Conversation
The merge-train never gated on CI. upsertPR (sync) hardcoded
ci_status="" ("Phase 1 leaves it blank" TODO that never landed);
ci_status was only ever set by webhooks, which don't deliver on this
self-hosted fork. releaseEligibilityReason only blocks non-empty
non-"success", so empty → eligible → red PRs merged (e.g. PR #100
broke main lint for 12h).
Fix — make sync self-sufficient:
- github.GetCIStatus: combined rollup of the LEGACY commit-status API
+ the check-runs API (GitHub Actions reports as check-runs, which
the legacy /status endpoint is blind to). Failure-dominant: failure
> pending > success > "". CI-less repo → "" (stays mergeable by
design — RoastConsole/saf-roast-macos has zero workflows).
- upsertPR: resolve ci_status for OPEN PRs only (closed/merged skip —
bounds the rate-limit cost the original TODO worried about).
Best-effort: a fetch error logs + leaves "" and the next sync
corrects it; one PR's CI lookup never fails the whole sync.
- releaseEligibilityReason UNCHANGED: once ci_status is correctly
populated, the existing != "" && != "success" check already blocks
pending/failure and leaves CI-less repos mergeable. Fail-closed
behavior emerges from correct data; no logic change needed.
Reuses the existing gh.CheckRun type (webhook.go). Regression tests:
GetCIStatus rollup (5 cases), upsertPR persists/skips/error-tolerates
ci_status, releaseEligibilityReason CI gate (failure/success/empty).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes ROA-274. The Ship Hub merge-train never gated on CI — it merged PR #100 with red
frontendlint, breakingmainfor ~12h.Root cause:
upsertPR(sync) hardcodedci_status=""(a never-finished "Phase 1" TODO);ci_statuswas only ever set by webhooks, which don't deliver on this self-hosted fork.releaseEligibilityReasononly blocks non-empty, non-"success"— so empty → eligible → red PRs merge.Fix — make sync self-sufficient
github.GetCIStatus: one combined rollup of the legacy commit-status API + the check-runs API. GitHub Actions reports as check-runs, which the legacy/statusendpoint is blind to (whyci_statuswas always""here). Failure-dominant:failure > pending > success > "".upsertPR: resolvesci_statusfor open PRs only (closed/merged skip — bounds the rate-limit cost the original TODO worried about). Best-effort: a fetch error logs + leaves""; next sync corrects it; one PR's lookup never fails the whole sync.releaseEligibilityReasonunchanged: onceci_statusis correct, the existing!= "" && != "success"already blocks pending/failure. CI-less repos (no statuses, no check-runs →"") stay mergeable by design (RoastConsole / saf-roast-macos has zero workflows — must not false-block). Fail-closed behavior emerges from correct data; no logic change needed there.Test plan
go build ./...+go vetcleanship+githubsuites passTestGetCIStatus_*(5 rollup cases),TestUpsertPR_{OpenPR_Persists,MergedPR_Skips,CIFetchError_Tolerates},TestReleaseEligibilityReason_CIGate(failure/success/empty)Reuses the existing
gh.CheckRuntype.release.godeliberately untouched.🤖 Generated with Claude Code