mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-25 19:54:15 +00:00
On 2026-09-09 the labeler's config was replaced with the rendered template, which has empty identity fields (owner DID, DID, rotation key). The running process kept its in-memory config, so nothing failed until the next restart on 2026-09-12, when the labeler crash-looped on "labeler.owner_did is required" and nobody was told: the deploy tool never probed the labeler at all. The sync's missing-file branch is the only code that writes a whole template, so an update now refuses when the file is gone and says to restore it from the predeploy backup; provision keeps the first-install behaviour. The health check was a single curl two seconds after restart. The hold takes longer than that to open its listener, so tonight's deploy printed HEALTH_FAIL for a hold that answered seconds later. Worse, the verdict was a substring match on HEALTH_OK, which the scanner's SCANNER_HEALTH_OK line also satisfies, so a failed hold next to a healthy scanner was reported healthy. Each restarted service (hold, scanner, appview, labeler) is now polled every two seconds for up to thirty, and reports on its own whole-label line. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvFJr4Dwz8p2NDAeXmgmBt
33 lines
1.1 KiB
Go
33 lines
1.1 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRenderHealthProbe(t *testing.T) {
|
|
s := renderHealthProbe("hold", "http://localhost:8080/xrpc/_health", 15)
|
|
for _, want := range []string{"seq 1 15", `curl -sf "http://localhost:8080/xrpc/_health"`, `echo "PROBE hold OK`, `echo "PROBE hold FAIL`, "sleep 2"} {
|
|
if !strings.Contains(s, want) {
|
|
t.Errorf("probe script missing %q:\n%s", want, s)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseProbesDoesNotConfuseServices(t *testing.T) {
|
|
out := "systemctl output\nPROBE hold FAIL 30\nPROBE scanner OK 4\nnoise PROBE labeler OK 2\n"
|
|
got := parseProbes(out)
|
|
if got["hold"].Status != "FAIL" || got["hold"].Seconds != 30 {
|
|
t.Errorf("hold = %+v, want FAIL after 30s", got["hold"])
|
|
}
|
|
if got["scanner"].Status != "OK" || got["scanner"].Seconds != 4 {
|
|
t.Errorf("scanner = %+v, want OK after 4s", got["scanner"])
|
|
}
|
|
if _, ok := got["labeler"]; ok {
|
|
t.Errorf("a PROBE token that is not at the start of a line must not count: %+v", got["labeler"])
|
|
}
|
|
if !probeMarkersPresent(out) {
|
|
t.Error("expected probe markers to be detected")
|
|
}
|
|
}
|