docs(prs): PR#23 got its number

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-09-04 18:02:58 +02:00
co-authored by Claude Fable 5.1
parent 0f57549b4f
commit e4b935c684
@@ -49,7 +49,7 @@ Three ways to add deployments were considered:
- *Green* is every run of the predecessor that ends with `SUCCESS`, whatever started it: the push watcher, an `atTimes` slot, a UI restart, `werkator retry`, or the startup recovery. - *Green* is every run of the predecessor that ends with `SUCCESS`, whatever started it: the push watcher, an `atTimes` slot, a UI restart, `werkator retry`, or the startup recovery.
- The key belongs to the `trigger` block: it says *when* the build runs, so it is never inherited from `builds.default`, and writing it flat is refused like every other trigger key. - The key belongs to the `trigger` block: it says *when* the build runs, so it is never inherited from `builds.default`, and writing it flat is refused like every other trigger key.
#### Scenario#000.01: A green predecessor triggers the follow-up on the same commit #### Scenario#23.01: A green predecessor triggers the follow-up on the same commit
So that a deployment ships exactly the commit that was just tested, with its own log, duration, and Gitea check. So that a deployment ships exactly the commit that was just tested, with its own log, duration, and Gitea check.
@@ -65,7 +65,7 @@ So that a deployment ships exactly the commit that was just tested, with its own
- [FollowUpTriggerTest — "a green predecessor enqueues the follow-up at the predecessor's commit"](../../src/test/kotlin/de/hoennig/werkator/watcher/FollowUpTriggerTest.kt) - [FollowUpTriggerTest — "a green predecessor enqueues the follow-up at the predecessor's commit"](../../src/test/kotlin/de/hoennig/werkator/watcher/FollowUpTriggerTest.kt)
#### Scenario#000.02: Every green run triggers again, including a repeated run of the same commit #### Scenario#23.02: Every green run triggers again, including a repeated run of the same commit
So that a deployment can be repeated by rerunning the build — and so that no run of a green build is silently *not* deployed, which would be more confusing than a redundant deployment. So that a deployment can be repeated by rerunning the build — and so that no run of a green build is silently *not* deployed, which would be more confusing than a redundant deployment.
@@ -77,7 +77,7 @@ So that a deployment can be repeated by rerunning the build — and so that no r
- [FollowUpTriggerTest — "every green run of the predecessor triggers the follow-up again"](../../src/test/kotlin/de/hoennig/werkator/watcher/FollowUpTriggerTest.kt) - [FollowUpTriggerTest — "every green run of the predecessor triggers the follow-up again"](../../src/test/kotlin/de/hoennig/werkator/watcher/FollowUpTriggerTest.kt)
#### Scenario#000.03: A run that is not green triggers nothing #### Scenario#23.03: A run that is not green triggers nothing
So that nothing is ever deployed from a failed, cancelled, or interrupted build. So that nothing is ever deployed from a failed, cancelled, or interrupted build.
@@ -90,7 +90,7 @@ So that nothing is ever deployed from a failed, cancelled, or interrupted build.
- [FollowUpTriggerTest — "only a SUCCESS of the named predecessor triggers"](../../src/test/kotlin/de/hoennig/werkator/watcher/FollowUpTriggerTest.kt) - [FollowUpTriggerTest — "only a SUCCESS of the named predecessor triggers"](../../src/test/kotlin/de/hoennig/werkator/watcher/FollowUpTriggerTest.kt)
#### Scenario#000.04: The trigger of a follow-up is host-pinned #### Scenario#23.04: The trigger of a follow-up is host-pinned
So that a branch can never deploy itself: a follow-up build is the host's way to hand real-world effects — targets, credentials — to a commit, and the host alone decides *when* and *for which branches* that happens. So that a branch can never deploy itself: a follow-up build is the host's way to hand real-world effects — targets, credentials — to a commit, and the host alone decides *when* and *for which branches* that happens.
@@ -104,7 +104,7 @@ So that a branch can never deploy itself: a follow-up build is the host's way to
- [ConfigLoaderTest — "a follow-up trigger is pinned to the host, a branch cannot add or widen one"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) - [ConfigLoaderTest — "a follow-up trigger is pinned to the host, a branch cannot add or widen one"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt)
#### Scenario#000.05: What the follow-up does comes with the repository #### Scenario#23.05: What the follow-up does comes with the repository
So that the deployment command is versioned with the code it deploys, like every other build command — while the host keeps the targets and credentials. So that the deployment command is versioned with the code it deploys, like every other build command — while the host keeps the targets and credentials.
@@ -118,7 +118,7 @@ So that the deployment command is versioned with the code it deploys, like every
- [BuildExecutorTest — "a follow-up build runs in its branch's worktree after its predecessor"](../../src/test/kotlin/de/hoennig/werkator/build/BuildExecutorTest.kt) - [BuildExecutorTest — "a follow-up build runs in its branch's worktree after its predecessor"](../../src/test/kotlin/de/hoennig/werkator/build/BuildExecutorTest.kt)
- [ConfigLoaderTest — "a branch supplies the command of a host-triggered follow-up"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) - [ConfigLoaderTest — "a branch supplies the command of a host-triggered follow-up"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt)
#### Scenario#000.06: A follow-up that could never fire is refused at start #### Scenario#23.06: A follow-up that could never fire is refused at start
So that a deployment that silently never runs cannot exist — the same reasoning that refuses a flat trigger key. So that a deployment that silently never runs cannot exist — the same reasoning that refuses a flat trigger key.
@@ -134,7 +134,7 @@ So that a deployment that silently never runs cannot exist — the same reasonin
- [ConfigLoaderTest — "afterSuccessOf must name an existing definition and must not form a cycle"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) - [ConfigLoaderTest — "afterSuccessOf must name an existing definition and must not form a cycle"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt)
- [ConfigLoaderTest — "afterSuccessOf written flat is refused like every trigger key"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt) - [ConfigLoaderTest — "afterSuccessOf written flat is refused like every trigger key"](../../src/test/kotlin/de/hoennig/werkator/config/ConfigLoaderTest.kt)
#### Scenario#000.07: Follow-ups fire in server mode only #### Scenario#23.07: Follow-ups fire in server mode only
So that the invariant "nothing is scheduled during CLI runs or tests" holds: a CLI `build` ends when its build ends, and a follow-up enqueued into a process that is about to exit would only ever be recorded as interrupted. So that the invariant "nothing is scheduled during CLI runs or tests" holds: a CLI `build` ends when its build ends, and a follow-up enqueued into a process that is about to exit would only ever be recorded as interrupted.
@@ -155,11 +155,11 @@ A definition may itself be followed; `ConfigLoader` refuses an unknown predecess
A new `FollowUpTrigger` in the `watcher` package listens to `BuildStatusChangedEvent`. A new `FollowUpTrigger` in the `watcher` package listens to `BuildStatusChangedEvent`.
On a `SUCCESS` it resolves the definitions of the result's branch at the result's commit — the same `definitionsFor` the watcher uses for the branch layer — and enqueues, through `BuildExecutor.startBuild(repo, branch, commit, name)`, every definition whose `afterSuccessOf` names the finished build and whose selector selects the branch. On a `SUCCESS` it resolves the definitions of the result's branch at the result's commit — the same `definitionsFor` the watcher uses for the branch layer — and enqueues, through `BuildExecutor.startBuild(repo, branch, commit, name)`, every definition whose `afterSuccessOf` names the finished build and whose selector selects the branch.
Passing the commit explicitly is what makes Scenario#000.01's last line true; the executor's duplicate guard folds a follow-up that is already queued for the same commit. Passing the commit explicitly is what makes Scenario#23.01's last line true; the executor's duplicate guard folds a follow-up that is already queued for the same commit.
The listener is armed by the watcher's `start()` and disarmed by `stop()`, which is how it stays silent in CLI runs and tests (Scenario#000.07). The listener is armed by the watcher's `start()` and disarmed by `stop()`, which is how it stays silent in CLI runs and tests (Scenario#23.07).
The pinning extends `stripPinned`: `afterSuccessOf` is removed from every trigger of the branch layer, and for every definition whose host trigger carries `afterSuccessOf` the branch layer's whole `trigger` block is dropped. The pinning extends `stripPinned`: `afterSuccessOf` is removed from every trigger of the branch layer, and for every definition whose host trigger carries `afterSuccessOf` the branch layer's whole `trigger` block is dropped.
That is the smallest rule that makes Scenario#000.04 hold: a branch keeps the right to describe what its deployment does, and loses only the right to decide that — or where — it happens. That is the smallest rule that makes Scenario#23.04 hold: a branch keeps the right to describe what its deployment does, and loses only the right to decide that — or where — it happens.
The pull-request gate is not consulted for a follow-up: the predecessor passed it already for the same commit, and the host's selector is the follow-up's own gate. The pull-request gate is not consulted for a follow-up: the predecessor passed it already for the same commit, and the host's selector is the follow-up's own gate.
The follow-up runs like any other build of its branch — same worktree, same sandbox, serialized behind its predecessor. The follow-up runs like any other build of its branch — same worktree, same sandbox, serialized behind its predecessor.