Files
werkator/docs/prs/2026-10-03-PR#95-cancel-instead-of-delete-of-active-builds.md
miandmhoennig 95bd17fb2a
werkator build succeeded after 01:45
werkator/deploy build succeeded after 00:06
The × of a queued or running build cancels it, deleting it is refused (v1.30.1) (#95)
The × on a running row deleted the stored result while the build ran on, holding its branch (a deploy waited behind it for hours) and unreachable for cancel.

- `DELETE` answers 409 for a queued or running build.
- `cancel` asks the executor (`BuildExecutor.isActive`) instead of the stored results, so an orphaned build can still be stopped.
- Pending and running rows render the × as \"Cancel build\".

PR-doc: `docs/prs/2026-10-03-PR#95-cancel-instead-of-delete-of-active-builds.md`

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #95
2026-10-03 15:59:44 +02:00

3.4 KiB
Raw Permalink Blame History

WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.

The Problem

Every row of the build tables carries a ×, and on a running row it read as "cancel". It meant "Delete stored build": the result was removed, and the build ran on. Nothing showed it any more, but it still held its branch, so a deploy queued behind a mutation build waited for hours. The cancel endpoint looked the build up in the stored results, so with the row gone it could not be stopped either. When the build finished, the executor found no result to update and recorded a new one, so the deleted build turned up again. This happened twice on werkator.javagil.de.

The Scenarios

Feature: A queued or running build is cancelled, never deleted

Scenario#95.01: Deleting a queued or running build is refused

So that no build runs on without a row to show and stop it.

  • Given a build that is queued or running
  • When its result is deleted through the API
  • Then the answer is 409, naming the build and saying to cancel it first
  • And the result and its artifacts stay
Verified by

Scenario#95.02: A build whose result is gone can still be cancelled

So that a build orphaned by an earlier version can be stopped without a restart.

  • Given a running build whose stored result was deleted
  • When it is cancelled through the route of its repository
  • Then the executor cancels it
  • And the route of another repository still does not reach it
Verified by

Scenario#95.03: A queued or running row offers Cancel

So that the × does what it looks like it does.

  • Given a history with a pending, a running and a finished build
  • When the page is rendered
  • Then the pending and the running row carry a cancel button, the finished row the delete button
Verified by

The Solution

  • BuildExecutor.isActive(repo, artifactKey) says whether a build is queued or executing in that repository. It asks the executor, not the stored results, because a result can be gone while its build runs.
  • cancel uses it in place of the lookup in the history; that also keeps a route from reaching another repository's build.
  • DELETE /api/builds/<key> answers 409 for an active build.
  • builds.html and werkator.js render the × of a pending or running row as "Cancel build", like the card on the current-builds page.

Additional Changes

  • Scenario#65.04 waits for the draining flag: it is set after the result is stored, and a slow CI read it too early.
  • Version 1.30.1 with its release note.

Follow-up PRs

  • A queued build that is cancelled stays PENDING until its branch's worker reaches it, which can be hours behind a long build. It could be recorded as CANCELLED at once.