What
The run page offers Stop running run on a run a runner has picked up. Clicking it
records the request and leaves the lease where it is. The runner sees the request on the
heartbeat it already sends, stops the container, writes one line to the job log, and
reports the attempt it had so far. The run stays canceled, keeps its partial log and
step timings, and its page says who asked and that it was stopped rather than failed.
A queued run is still canceled outright, and its page now names the account too.
Why
Canceling a queued run was the only way to stop work, and the comment above CancelRun
said why: the queue does not own the process. So a build that was clearly wrong — an LLM
session on the wrong track, a retry loop, a test suite that will never finish — held its
runner until the step timeout, the job budget from #161, or somebody killing the
container by hand. None of those is a minutes-scale answer.
This is the second half of §3 of #138.
Shape
- Queue (
ci/runs):cancel_requestedandcancel_actorare additive columns onruns.CancelRunningsets them and touches nothing else;Heartbeatreturns the account ascancel.RecordAttemptandFinishkeep the canceled status when the marker is set, so the runner’s nonzero exit code does not turn the run into a failure. The expiry sweep cancels a marked run whose runner died instead of queueing it again, andRequeueclears the marker because a rerun is a new decision. - Runner (
ci/agent): the heartbeat reply gainscancel; a step or an image build that sees it kills the process group, stops the container, logs one line, and reports the partial attempt. A lost lease is still a lost lease: no report. - Web (
server/web): one action, with the outcome chosen from the run’s status. The button names what it will do, and the page names the account and distinguishes a run stopped while running from one canceled in the queue. Audit keeps its shape: the account, the repository, and the run. - Gate: no change needed — a canceled run already does not count as a check and is
not a wait, which
forge/landingalready tested.
Tests
ci/runs: a stop request keeps the lease and reaches the heartbeat; a record and a plain finish both keepcanceled; the expiry sweep cancels a request whose runner died; a rerun clears it; a queued cancel names the account.server/ssh: the request crosses a real SSH channel on the heartbeat reply, and the stopped attempt is stored.server: the browser action on a running run, the stopping state, and the page after the runner reports.
Checks
vole workflow run verifypasses, including the race test suite, vet, build, license and reachability scans, packaging, and link checks.vole workflow checkpasses.
Closes #162.