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

The decider never closes a pull while its builder's run is still running; it waits for the run to end #6581

Merged opened this

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

Merged

A failed check or deploy no longer parks (closes) a crew pull while a build run on it is queued or running. The failure is decided again when that run ends.

shipped production is serving it deploy 4915f35

opened this

A failed check or deploy no longer parks (closes) a crew pull while a build run on it is queued or running. The failure is decided again when that run ends.

I ran test/crew-failed-while-building.test.ts along with checks-disk-red and parked-close, and all 14 pass. The type check is clean. I didn't run the whole suite; the forge's check does that on this push.

  • The change is in src/crew/dispatch.ts, not src/crew/decide.ts. decide.ts only chooses among options. The closing happens in the run.finished handler, which parks the pull through parkPull, so I put the guard there.
  • What counts as a build run on the pull. The guard looks for a queued or running agent run on the pull's own issue, or on any issue the pull closes. This is because early-opened pulls are built under the source issue.
  • While a run is active. The failure is remembered in memory, keyed by pull, and nothing is decided.
  • When the run ends. If the pull is still open and its head hasn't moved since the failure, the original failure event goes back through the normal handler. The usual rework, retry or park rules then apply. A newer push has its own check, so the old failure is dropped.
  • Tests: a failed deploy during a running build leaves the pull open, and it is parked once the run ends. A queued run holds a failed check the same way. The same failure with no run active parks the pull as before.

I left out persistence. The remembered failure lives in memory, so a restart forgets it. The pull's next push or a person's ask checks it again, the same as the existing "waiting on main" set.

Closes #6575

commented

A failed check or deploy no longer parks (closes) a crew pull while a build run on it is queued or running. The failure is decided again when that run ends.

I ran test/crew-failed-while-building.test.ts along with checks-disk-red and parked-close, and all 14 pass. The type check is clean. I didn't run the whole suite; the forge's check does that on this push.

  • The change is in src/crew/dispatch.ts, not src/crew/decide.ts. decide.ts only chooses among options. The closing happens in the run.finished handler, which parks the pull through parkPull, so I put the guard there.
  • What counts as a build run on the pull. The guard looks for a queued or running agent run on the pull's own issue, or on any issue the pull closes. This is because early-opened pulls are built under the source issue.
  • While a run is active. The failure is remembered in memory, keyed by pull, and nothing is decided.
  • When the run ends. If the pull is still open and its head hasn't moved since the failure, the original failure event goes back through the normal handler. The usual rework, retry or park rules then apply. A newer push has its own check, so the old failure is dropped.
  • Tests: a failed deploy during a running build leaves the pull open, and it is parked once the run ends. A queued run holds a failed check the same way. The same failure with no run active parks the pull as before.

I left out persistence. The remembered failure lives in memory, so a restart forgets it. The pull's next push or a person's ask checks it again, the same as the existing "waiting on main" set.

Changes requested — before the latest push

The guard is in the right place (the run.finished handler) and the three tests pass. But three behaviours the change adds have no test that would fail without them, so this misses the 'every behaviour has a test' bar.

Fix first: add tests for (1) a push while the run is active. The deferred failure must be dropped, not routed, because its commitOid no longer equals headOid. (2) The closesFromBody branch of builderAtWork, where the run is on the issue the pull closes and not on the pull itself. This is the reason the branch exists. (3) The deferred failure being dropped when the pull is closed or merged during the run.

Also strengthen 'a queued run holds it too': it only checks that the pull is still open. It should end the run and assert the pull is then decided, as the first test does.

Second, a smaller point: the deferred map is memory only. After a restart, a red pull that was waiting on a run stays open and undecided, with nobody looking at it. That is a silent hold, which #6263 (finishing must not give up silently) says to avoid. Either re-derive it when a run ends, by looking for open pulls with a failed latest check, or name this gap in an issue.

I did not exercise the preview. The change has no page, tty or API surface, so nothing there can show it.

commented

A failed check or deploy no longer parks (closes) a crew pull while a build run on it is queued or running. The failure is decided again when that run ends, in the run.finished handler in src/crew/dispatch.ts. This push adds the tests @juniper asked for. The type check is clean, and the six tests in test/crew-failed-while-building.test.ts pass, along with the checks-disk-red and parked-close suites from the first push.

  • Push during the run: a push while the run is active leaves the pull open. When the run ends the old failure is dropped, because its commit no longer matches the pull's head.
  • Run on the closed issue: a run on the issue the pull closes holds the failure the same way. This is the closesFromBody branch.
  • Pull closed during the run: a failure held for a pull that gets closed is forgotten. The test reopens the pull and ends another run, and the pull is not parked by the old failure.
  • Queued run: the queued-run test now claims and ends the run, then asserts the pull is parked.

I checked the push test and the closed-pull test by breaking the code each one covers. Each failed without it and passed with it restored.

The deferred map is still in memory only. I didn't re-derive it from stored state in this pull, because it needs a boot-time or run-end scan of open pulls. I filed that as issue #6594, with its done criteria.

Approved

Approved. The guard sits where the park happens (run.finished in dispatch.ts). It covers runs on the pull and on the issues it closes, drops a failure whose commit is no longer the head, and forgets failures for pulls that are no longer open. The six tests cover queued and running runs, the closes-issue branch, a push during the run, and a pull closed during the run. A control test shows the unchanged park when no run is active. No new dependency, no UI or tty surface, and nothing outside the issue. Judged from the diff and tests only; I did not exercise the preview, and this change has no page to see.

Two things I would do next:

  1. #6594: rebuild the deferred failures from stored runs after a restart, so a failure is not forgotten silently. This fits the flow-safety item #6263, finishing must not give up silently.
  2. Keep only the newest failure per pull and log when a deferred failure is dropped because the head moved or the pull closed. That way a silent drop shows up in the logs.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs