Skip to content

Commit 4c0e275

Browse files
kriscendobotclaude
andcommitted
fix(triager): make self-provision opt-in (default skip), reconcile case I
My prior commit defaulted self-provision ON, which fought a peer's just-landed case I (a regression guard locking the clone-less-host SKIP behavior and its log line) and left origin/main2 red. The fleet deliberately chose the skip-model (clone-holder triages; others skip), so make provisioning OPT-IN: GARDEN_TRIAGE_SELF_PROVISION defaults to 0 → a missing clone is a clean skip with the peer's "a host that holds the clone triages this repo" log (case I passes unmodified). Set it to 1 to have this host self-provision a watched repo whose clone lives on no host (ocapn, agoric-3-proposals, cosgov) — the provisioning + bounded-atomic-clone + escalate-on-unreachable path is unchanged, just gated. Reconcile triager-test.sh case H: H1/H3/H4 set SELF_PROVISION=1 to exercise the opt-in provision / unreachable / underivable paths; H2 now asserts the DEFAULT (unset) clean skip — no auto-clone, no handler, no escalation. All hermetic. FOLLOW-UP for the maintainer: the three watched repos with no clone on any host (kriscendobot-{ocapn,agoric-3-proposals,cosgov}) are now un-wedged (no more crash-loop) but stay UN-TRIAGED under the default skip. To triage them, either create/hold their bare clones under worktrees/, or arm the opt-in (GARDEN_TRIAGE_SELF_PROVISION=1) on one host after confirming those forks exist. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2c76c8c commit 4c0e275

2 files changed

Lines changed: 37 additions & 19 deletions

File tree

scripts/jobs/test/triager-test.sh

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,18 @@ handler_new_sha="$(cut -f3 "$CALLS" | head -1)"
300300
[ "$(cursor_field "activity/$SLUG" last_sha)" = "$MSHA" ] && ok "activity cursor advanced to the clean sha" || bad "cursor = $(cursor_field "activity/$SLUG" last_sha) (want $MSHA)"
301301

302302
# ============================================================================
303-
hr; echo "H — missing bare clone on this host: SELF-PROVISION-or-skip, never a hard die"; hr
303+
hr; echo "H — missing bare clone: default clean skip; opt-in self-provision, never a hard die"; hr
304304
# The watch set is journal-shared across hosts, but bare clones are host-local, so a
305305
# host that arms this timer need not already hold the clone (the live crash-loop of
306306
# garden-triager@* on hosts whose worktrees/ held no clone for a watched slug). A
307307
# missing clone must be NON-FATAL — never the old hard die that drove an every-tick
308-
# systemd failure/restart. Some watched repos (ocapn, agoric-3-proposals, cosgov) have
309-
# no clone on ANY host, so a plain skip would leave them un-triaged forever; instead the
310-
# triager SELF-PROVISIONS the standing bare clone (clone-keeper's derive-URL +
311-
# bounded-atomic-clone logic) and then triages. An unreachable/underivable source skips
312-
# cleanly (exit 0, retry next tick) and escalates to the maintainer inbox — no crash loop.
308+
# systemd failure/restart. By DEFAULT a clone-less host cleanly SKIPS (the clone-holder
309+
# triages; case I guards the default resolving under worktrees/). Some watched repos
310+
# (ocapn, agoric-3-proposals, cosgov) have no clone on ANY host, so a plain skip leaves
311+
# them un-triaged forever; a host may OPT IN (GARDEN_TRIAGE_SELF_PROVISION=1) to
312+
# SELF-PROVISION the standing bare clone (clone-keeper's derive-URL + bounded-atomic-clone
313+
# logic) and then triage. An unreachable/underivable source under opt-in skips cleanly
314+
# (exit 0, retry next tick) and escalates to the maintainer inbox — no crash loop.
313315

314316
# A capture stub for alert_maintainer (GARDEN_ALERT_CMD): records "<key>|<msg>" so the
315317
# escalation paths are asserted OFFLINE instead of routing to the real inbox (mirrors
@@ -335,7 +337,7 @@ PSHA="$(git -C "$UPSEED" rev-parse HEAD)"
335337
git -C "$UPSEED" remote add origin "$UPBARE"; git -C "$UPSEED" push -q -u origin master
336338
rm -rf "$UPSEED"
337339

338-
# --- H1: self-provision SUCCEEDS from the derived (local) upstream, then triages ----
340+
# --- H1: opt-in self-provision SUCCEEDS from the derived (local) upstream, then triages
339341
rm -rf "$TR/state7"; STATE="$TR/state7"; rm -rf "$BARE"; seed_journal
340342
rm -rf "$REPOS/$NOSLUG.git"
341343
[ ! -d "$REPOS/$NOSLUG.git" ] && ok "fixture: no bare clone at \$GARDEN_REPOS/$NOSLUG.git (clone-less host shape)" || bad "fixture invalid: $NOSLUG.git unexpectedly present"
@@ -344,6 +346,7 @@ set +e
344346
env GARDEN=testhost GARDEN_STATE="$STATE" \
345347
JOURNAL_REMOTE="$BARE" JOURNAL_BRANCH="$BRANCH" \
346348
GARDEN_REPOS="$REPOS" GARDEN_WATCH_REF=master \
349+
GARDEN_TRIAGE_SELF_PROVISION=1 \
347350
GARDEN_CLONE_URL_BASE="$UPSTREAMS" GARDEN_ALERT_CMD="$ALERT_STUB" \
348351
GARDEN_TRIAGE_HANDLER="$HANDLER" HANDLER_RC=0 CALL_LOG="$CALLS" \
349352
GARDEN_TRIAGE_FAIL_THRESHOLD=5 \
@@ -358,23 +361,29 @@ grep -q "provisioned missing bare clone $NOSLUG" "$H1OUT" && ok "logs the provis
358361
[ "$(cut -f3 "$CALLS" | head -1)" = "$PSHA" ] && ok "new_sha is the provisioned upstream HEAD" || bad "new_sha = [$(cut -f3 "$CALLS" | head -1)] (want $PSHA)"
359362
[ ! -s "$ALERTS" ] && ok "no maintainer escalation on a successful provision" || bad "unexpected escalation: $(cat "$ALERTS")"
360363

361-
# --- H2: GARDEN_TRIAGE_SELF_PROVISION=0 → clean skip (the clone-holder triages) -----
364+
# --- H2: DEFAULT (self-provision OFF) → clean skip, the clone-holder triages --------
365+
# With GARDEN_TRIAGE_SELF_PROVISION unset (the fleet default), a clone-less host is a
366+
# benign no-op — it must NOT auto-clone (no surprise network / disk on every host) and
367+
# must NOT die. This is the skip-model case I guards, asserted here with the handler +
368+
# clone + escalation checks case I does not make.
362369
rm -rf "$TR/state8"; STATE="$TR/state8"; rm -rf "$BARE"; seed_journal
363370
rm -rf "$REPOS/$NOSLUG.git"
364371
: > "$CALLS"; : > "$ALERTS"; H2OUT="$TR/triager-h2.out"; : > "$H2OUT"
365372
set +e
366373
env GARDEN=testhost GARDEN_STATE="$STATE" \
367374
JOURNAL_REMOTE="$BARE" JOURNAL_BRANCH="$BRANCH" \
368375
GARDEN_REPOS="$REPOS" GARDEN_WATCH_REF=master \
369-
GARDEN_TRIAGE_SELF_PROVISION=0 GARDEN_ALERT_CMD="$ALERT_STUB" \
376+
GARDEN_CLONE_URL_BASE="$UPSTREAMS" GARDEN_ALERT_CMD="$ALERT_STUB" \
370377
GARDEN_TRIAGE_HANDLER="$HANDLER" HANDLER_RC=0 CALL_LOG="$CALLS" \
371378
GARDEN_TRIAGE_FAIL_THRESHOLD=5 \
372379
"$JOBS/triager.sh" "$NOSLUG" >>"$H2OUT" 2>&1
373380
rc=$?; set -e
374-
[ "$rc" -eq 0 ] && ok "provision-disabled tick exits 0 (benign skip, not a die)" || bad "tick exit = $rc (want 0)"
375-
grep -q "skipping triage (self-provision disabled)" "$H2OUT" && ok "skip log names the disabled self-provision" || bad "disabled-skip log missing"
376-
[ ! -d "$REPOS/$NOSLUG.git" ] && ok "no clone created when provisioning is disabled" || bad "clone unexpectedly created with provisioning disabled"
381+
[ "$rc" -eq 0 ] && ok "default clone-less tick exits 0 (benign skip, not a die)" || bad "tick exit = $rc (want 0)"
382+
grep -q "no bare clone at .*$NOSLUG.git on this host; skipping triage (a host that holds the clone triages this repo)" "$H2OUT" \
383+
&& ok "default skip log names the missing clone and the clone-holder reason" || bad "default-skip log missing"
384+
[ ! -d "$REPOS/$NOSLUG.git" ] && ok "no clone auto-created by default (self-provision is opt-in)" || bad "clone unexpectedly created without opt-in"
377385
[ ! -s "$CALLS" ] && ok "handler never invoked (nothing to diff without a clone)" || bad "handler ran ($(grep -c . "$CALLS") calls; want 0)"
386+
[ ! -s "$ALERTS" ] && ok "no maintainer escalation on the default clean skip" || bad "unexpected escalation: $(cat "$ALERTS")"
378387

379388
# --- H3: source UNREACHABLE → skip + retry, escalate (no crash loop) ----------------
380389
rm -rf "$TR/state9"; STATE="$TR/state9"; rm -rf "$BARE"; seed_journal
@@ -384,6 +393,7 @@ set +e
384393
env GARDEN=testhost GARDEN_STATE="$STATE" \
385394
JOURNAL_REMOTE="$BARE" JOURNAL_BRANCH="$BRANCH" \
386395
GARDEN_REPOS="$REPOS" GARDEN_WATCH_REF=master \
396+
GARDEN_TRIAGE_SELF_PROVISION=1 \
387397
GARDEN_CLONE_URL_BASE="$TR/no-such-upstreams" GARDEN_ALERT_CMD="$ALERT_STUB" \
388398
GARDEN_FETCH_RETRIES=1 GARDEN_FETCH_TIMEOUT=5 \
389399
GARDEN_TRIAGE_HANDLER="$HANDLER" HANDLER_RC=0 CALL_LOG="$CALLS" \
@@ -405,6 +415,7 @@ set +e
405415
env GARDEN=testhost GARDEN_STATE="$STATE" \
406416
JOURNAL_REMOTE="$BARE" JOURNAL_BRANCH="$BRANCH" \
407417
GARDEN_REPOS="$REPOS" GARDEN_WATCH_REF=master \
418+
GARDEN_TRIAGE_SELF_PROVISION=1 \
408419
GARDEN_CLONE_URL_BASE="$UPSTREAMS" GARDEN_ALERT_CMD="$ALERT_STUB" \
409420
GARDEN_TRIAGE_HANDLER="$HANDLER" HANDLER_RC=0 CALL_LOG="$CALLS" \
410421
GARDEN_TRIAGE_FAIL_THRESHOLD=5 \

scripts/jobs/triager.sh

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,24 @@ BARE="$GARDEN_REPOS/$slug.git"
4949
# host that arms this timer need not already hold the clone. The triager needs a local
5050
# clone to diff refs against its cursor (unlike comment-watcher.sh, which polls via
5151
# gh), so a missing clone must never be a hard die — that drove an every-tick systemd
52-
# failure/restart on any clone-less host. Some watched repos (ocapn, agoric-3-proposals,
53-
# cosgov) have no clone on ANY host, so a plain skip would leave them un-triaged
54-
# forever; instead SELF-PROVISION the standing bare clone, reusing the same derive-URL
55-
# + bounded-atomic-clone logic clone-keeper.sh uses to re-create a vanished tracked
56-
# clone (worktrees/<owner>-<name>.git → $GARDEN_CLONE_URL_BASE/<owner>/<name>.git),
52+
# failure/restart on any clone-less host.
53+
#
54+
# DEFAULT (self-provision OFF): a clone-less host is a benign no-op — the host that
55+
# holds the clone triages this repo. This is the just-landed skip-model (case I in the
56+
# test guards the default resolving under worktrees/), so a missing clone stays a clean
57+
# skip unless a host explicitly opts in.
58+
#
59+
# OPT-IN (GARDEN_TRIAGE_SELF_PROVISION=1): some watched repos have no clone on ANY host
60+
# (ocapn, agoric-3-proposals, cosgov), so a plain skip leaves them un-triaged forever.
61+
# When a host opts in, SELF-PROVISION the standing bare clone here, reusing the same
62+
# derive-URL + bounded-atomic-clone logic clone-keeper.sh uses to re-create a vanished
63+
# tracked clone (worktrees/<owner>-<name>.git → $GARDEN_CLONE_URL_BASE/<owner>/<name>.git),
5764
# then fall through to the normal fetch. If the upstream is unreachable, skip cleanly
5865
# (exit 0) so the next tick retries — no crash loop; a persistently unreachable or an
5966
# underivable source escalates to the maintainer inbox rather than dying forever.
6067
if [ ! -d "$BARE" ]; then
61-
if [ "${GARDEN_TRIAGE_SELF_PROVISION:-1}" != 1 ]; then
62-
log "no bare clone at $BARE on this host; skipping triage (self-provision disabled)"
68+
if [ "${GARDEN_TRIAGE_SELF_PROVISION:-0}" != 1 ]; then
69+
log "no bare clone at $BARE on this host; skipping triage (a host that holds the clone triages this repo)"
6370
exit 0
6471
fi
6572
if src="$(derive_clone_url "$BARE")"; then

0 commit comments

Comments
 (0)