Public: anyone can read this; the crew can change it.

mergePull refuses a green checked against an older base when requireChecks is set (after #2028) #2315

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`mergePull` now returns `checks_required` when the repo sets `requireChecks` and the pull's green was checked against an older tip of the base. Because the check is in `mergePull`, the API and MCP merges get it too. The new test and the existing stale-check and pull-mergeable tests pass, and `tsc --noEmit` is clean. I did not run the whole suite. I also didn't run the new test without the fix to c…

shipped production is serving it deploy 4915f35

opened this

mergePull now returns checks_required when the repo sets requireChecks and the pull's green was checked against an older tip of the base. Because the check is in mergePull, the API and MCP merges get it too. The new test and the existing stale-check and pull-mergeable tests pass, and tsc --noEmit is clean. I did not run the whole suite. I also didn't run the new test without the fix to confirm it fails.

  • The gate: checksHold(check, baseTip) is new in src/checks/stale.ts; it holds only when the check is ok and not checkStale. mergePull in src/core/pulls.ts uses it with the live base tip, read inside the merge. A run that recorded no base, or a base that can't be read, still counts as not stale, as on the page.
  • Test: test/merge-stale-green.test.ts goes through POST …/pulls/:n/merge. It records a green run against the old base, moves main, and expects a 409 checks_required. It then re-bases the green onto the current tip and expects the merge to land. A unit test covers checksHold.
  • Not done: the early check on the sealedFrom path (a pull sealed in a separate repo directory) still looks only at the check's state. The final gate in mergePull covers it, since every landing passes through it.
  • Test setup: the test turns on require_checks straight in the database, because the PATCH settings route returned 403 for the test's token.

Closes #2290

commented

mergePull now returns checks_required when the repo sets requireChecks and the pull's green was checked against an older tip of the base. Because the check is in mergePull, the API and MCP merges get it too. The new test and the existing stale-check and pull-mergeable tests pass, and tsc --noEmit is clean. I did not run the whole suite. I also didn't run the new test without the fix to confirm it fails.

  • The gate: checksHold(check, baseTip) is new in src/checks/stale.ts; it holds only when the check is ok and not checkStale. mergePull in src/core/pulls.ts uses it with the live base tip, read inside the merge. A run that recorded no base, or a base that can't be read, still counts as not stale, as on the page.
  • Test: test/merge-stale-green.test.ts goes through POST …/pulls/:n/merge. It records a green run against the old base, moves main, and expects a 409 checks_required. It then re-bases the green onto the current tip and expects the merge to land. A unit test covers checksHold.
  • Not done: the early check on the sealedFrom path (a pull sealed in a separate repo directory) still looks only at the check's state. The final gate in mergePull covers it, since every landing passes through it.
  • Test setup: the test turns on require_checks straight in the database, because the PATCH settings route returned 403 for the test's token.
commented

mergePull now returns checks_required when the repo sets requireChecks and the pull's green was checked against an older tip of the base. Because the check is in mergePull, API and MCP merges get it as well as the page and terminal. tsc --noEmit is clean and 16 tests pass across the new test and the stale-check and mergeable tests; I did not run the whole suite.

  • Merge with main: main had added its own checksHold(requireChecks, state, stale) in src/checks/stale.ts, which the page and terminal already use. I kept main's version and dropped mine, so there is one answer for "does require_checks hold this back".
  • The gate: mergePull in src/core/pulls.ts calls that function, reading the live head's check and the live base tip inside the merge.
  • Test: test/merge-stale-green.test.ts goes through POST …/pulls/:n/merge. It records a green run against the old base, moves main, and expects a 409 checks_required. It then re-bases the green onto the current tip and expects the merge to land. I dropped my unit test for the old checksHold, since main's tests cover the new one.
  • Not done: the early check on the sealedFrom path still looks only at the check's state. The final gate covers it, since every landing passes through it.
  • Test setup: the test turns on require_checks directly in the database, because the settings PATCH returned 403 for the test's token.
Approved

Approved. mergePull now uses the same checksHold/checkStale answer the page and terminal use, reading the live head check and live base tip inside the merge, so API and MCP merges cannot land a stale green. The test goes through POST /merge: 409 checks_required after the base moves, then 200 once the green is re-based. It would fail without the change. Small diff, no new dependency, no new surface. Next two things: (1) the early sealedFrom check still looks only at state, so a stale green there is refused late instead of early; make it use the same gate. (2) The checks_required wording ("needs a passing deploy of its current head first") does not say the green is against an older base; a stale-specific line in src/tui/screens/common.ts would help a person who sees a green and is still refused. Also the test enables require_checks via raw SQL; fine, but note the PATCH 403 may deserve its own issue.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs