Skip to content

Commit f70fc02

Browse files
ausimianclaude
andcommitted
docs: attribute the polling, and state what confirmation trusts
Two corrections to what the notes claim. The release note described bin/castle install polling running/1, which is Forecastle's behaviour and not Castle's integrated state: mix.lock pins Forecastle at 7eb5acc, whose bin/castle installs with a single rpc and never calls running/1. Castle supplies the answer; the asking belongs to Forecastle, from its own 1.0.0. Said that way round in both RELEASE.md and AGENTS.md, without claiming the pair's behaviour is already in effect here. The boot-completion check trusts the selected boot script to emit {progress, started} where it means what it says, and that is worth saying out loud. A RELEASE_BOOT_SCRIPT naming a hand-written script that never reaches the marker is never confirmed - install waits, then fails, and the refusal names the progress the node did reach, so it is diagnosable and never a false success - and one that emits the marker before its applications start defeats the check. Neither is validated: Mix generates these scripts and offers no rel/ template for them, so reaching either state takes deliberate work. That also corrects something I wrote in the previous commit. systools_make:add_apply_upgrade/2's hard match on the trailing marker does not rule this out: it builds the hybrid script for an emulator upgrade and says nothing about a script an operator supplies. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C4oaMvbR1cbxrZBj8qwkqN
1 parent 44a804c commit f70fc02

3 files changed

Lines changed: 43 additions & 4 deletions

File tree

AGENTS.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ Castle's job is configuration and release management on a running node.
2525
the system is running. `install_release/1`'s reply says only that the upgrade
2626
was accepted: a transition that restarts the emulator is replied to and then
2727
rebooted, and an emulator upgrade finishes on the way back up, where it can
28-
still roll back. `bin/castle install` therefore polls this rather than
29-
trusting the reply. Two conditions. The version is the running release: the
28+
still roll back. So Castle answers the question and leaves the asking to
29+
Forecastle: `bin/castle install` repeats it rather than trusting the reply,
30+
from Forecastle 1.0.0 — the revision pinned in this project's `mix.lock`
31+
installs with a single rpc and never calls this, so do not describe the
32+
polling as something Castle's own integrated state does. Two conditions. The
33+
version is the running release: the
3034
`current` one, or the `permanent` one when none is current — `install` leaves
3135
its target `current` and `commit` promotes it, so both count; `unpacked` (a
3236
rolled-back continuation) and `tmp_current` (written before the reboot) do
@@ -41,6 +45,18 @@ Castle's job is configuration and release management on a running node.
4145
that commits straight after installing would make a version that cannot boot
4246
the permanent one.
4347

48+
The marker is the whole of the evidence, so it inherits whatever the selected
49+
boot script does with it. `RELEASE_BOOT_SCRIPT` naming a hand-written script
50+
that never reaches `{progress, started}` will never be confirmed — `install`
51+
waits and then fails, and the refusal names the progress the node did reach,
52+
so it is diagnosable and never a false success — and one that emits the marker
53+
before its applications start defeats the check. Both are documented rather
54+
than validated: Mix generates the boot scripts and offers no `rel/` template
55+
for them, so reaching either state takes deliberate work. (An earlier note
56+
here claimed `systools_make:add_apply_upgrade/2`'s hard match on the trailing
57+
marker ruled this out. It does not: that builds the hybrid script for an
58+
emulator upgrade and says nothing about a script an operator supplies.)
59+
4460
Every one of them is a command entry point, so `Castle` is the command
4561
boundary: an operation that fails raises `Castle.Error` there, which is what
4662
leaves a non-zero exit status behind for the shell that asked for it. Raising,

RELEASE.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88
accepted: a transition that restarts the emulator is replied to and *then*
99
rebooted, and for an emulator upgrade the instructions run on the way back
1010
up, where they can still fail and roll back. Completion therefore has to be
11-
observed, and `bin/castle install` polls this to observe it. Confirmation
12-
needs two things: the version is the release the system is running - the one
11+
observed rather than inferred, and this is what makes it observable: a caller
12+
that repeats the question until it is answered - which is what Forecastle's
13+
`bin/castle install` does, from its own 1.0.0 - can tell an upgrade that took
14+
effect from one that did not. Castle supplies the answer; it does not do the
15+
asking, and the Forecastle this release is built against does not yet ask.
16+
17+
Confirmation needs two things: the version is the release the system is
18+
running - the one
1319
whose status is `current`, or the `permanent` one if none is current, so a
1420
version is confirmed both before and after `commit` - *and* its boot has
1521
finished. The second is not redundant. A node that restarted into the new
@@ -18,6 +24,16 @@
1824
from `kernel` onwards, so an application started after `sasl` can still fail
1925
and take the system back to the version that was permanent. Confirming
2026
earlier than that would let automation `commit` a release that cannot boot.
27+
28+
"Finished booting" means the boot script reached its `{progress, started}`
29+
instruction, which is the last thing every boot script Mix generates does.
30+
A release booted with a `RELEASE_BOOT_SCRIPT` that names a hand-written
31+
script without that marker will therefore never be confirmed: `install` waits
32+
and then fails, and the refusal names the progress the node did reach, so it
33+
says what is wrong rather than failing silently - but it will not succeed. A
34+
script that emits the marker before its applications are started defeats the
35+
check instead, since the marker is all there is to go on.
36+
2137
Nothing can build a relup that restarts the emulator until
2238
[forecastle#4](https://github.com/ausimian/forecastle/issues/4), so the
2339
restart transitions this addresses cannot be exercised end to end yet. The

lib/castle/commands.ex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ defmodule Castle.Commands do
199199
# before that same marker (systools_make.erl:336). So a provided status of
200200
# `:started` means the script ran to the end: applications up, and any
201201
# continuation of the upgrade finished.
202+
#
203+
# The marker is the whole of the evidence, so this trusts whichever boot
204+
# script was selected to emit it where it means what it says. One that never
205+
# reaches it is never confirmed - `install` waits, then fails, and the message
206+
# below names the progress the node did reach - and one that emits it early
207+
# defeats the check. Mix generates these scripts; both states take an operator
208+
# writing their own and pointing RELEASE_BOOT_SCRIPT at it.
202209
defp booted(vsn, init) do
203210
case init.get_status() do
204211
{_internal, :started} ->

0 commit comments

Comments
 (0)