Repository navigation
ci: WEEKLY_SKIP_RUNNER_CHECK skips both runner rows, and the docs say which row sees what (Refs #1504) - #1723
Conversation
… which row sees what (Refs #1504) Found by reading my own merged change (#1682): the systemd-side row sat OUTSIDE the escape guard, so the documented "release during an outage" flag could not bypass the one check that fails during an outage. Measured on origin/main's weekly.sh, with a runner unit stubbed to exit 1 (the oom-kill shape) and WEEKLY_SKIP_RUNNER_CHECK=1 set: preflight: FAIL actions.runner.x.service failed, last result oom-kill preflight failed: nothing was run The same arm on this branch proceeds. A flag that skips only one of two rows answering the same question is worse than no flag: it reads as an escape and is not one. Also documents the pair, which the merges left undocumented: check-ci-runners.sh is the API's view (registered and online; cannot say why; only after the heartbeat) and ci-runner-health.sh the systemd view (Result=oom-kill, restart window, the moment a unit dies; cannot see a revoked registration). Table + how to run each by hand, and the one case neither covers -- online in the API and active locally but wedged, where the signal is a queue that stops moving.
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
The escape flag was silent when it took effect, so a release log where the runner rows never ran reads exactly like one where they passed -- the same 'looks fine' failure these rows exist to end, one level up. One line, measured: flag=1 -> preflight: runner checks SKIPPED (WEEKLY_SKIP_RUNNER_CHECK=1) - a dead runner will read as a pending check, never red no flag -> preflight: ok 2 self-hosted runner(s) online / preflight: runner units: 3 PASS in systemd's view
|
Added one thing to this PR before anyone spends time reviewing it, because it is the same failure class the whole file exists to end, one level up: the skip was silent. With One line in the preflight and one in |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at its head — the defect and the fix are both right, and I checked the script rather than only the diff (bash -n scripts/weekly.sh parses; the guard now wraps both rows and preflight still returns $bad, so a release with the flag set proceeds as documented).
The finding itself is the valuable part, and it is a class rather than an incident: a guard written before a second check existed, so the escape hatch covered one of two rows that fail for the same cause. WEEKLY_SKIP_RUNNER_CHECK=1 documented as "release during an outage" and then failing on the other row is precisely the kind of defect that only appears when the flag and a real outage meet — which is why its measurement (stubbed oom-kill unit + the flag) is worth more than the eight lines it changes.
The skip message is the other half and I would have asked for it if it were missing: a log line where the checks silently did not run reads exactly like one where they passed. That sentence is the PR.
Two non-blocking observations:
-
A missing
ci-runner-health.shis still silent. The block isif [ -x …/ci-runner-health.sh ], so on a box where the file is absent (or lost its exec bit) neither a PASS, a FAIL, nor a SKIP line appears — the same "silence reads as a pass" failure this PR is about, one level down. Asay "preflight: ci-runner-health.sh not present, systemd row skipped"in anelsewould close it, and it is the exact case a fresh box hits. -
Nothing asserts the flag's behaviour.
WEEKLY_SKIP_RUNNER_CHECK=1could regress to skipping one row again and no test would notice — which is how this defect arrived. It looks cheap to pin:scripts/weekly.shhasset -euo pipefailat the top and no source guard, so a test cannot simply source it, but the two scripts it calls are invoked through$(dirname "$0"), so a copy of the script in amktemp -dalongside two stub siblings (check-ci-runners.shthat exits 1,ci-runner-health.shthat exits 1) plus the flag should show: exit 1 without the flag, exit 0 with it, and the SKIPPED line present. If the staging beforepreflightmakes that impractical, say so and I will write it — I would rather the row be pinned than trusted.
Neither blocks. If (1) lands as a one-line else, this is complete for me.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 5fc82046 — the right defect, found the right way, and the log line is the part that makes the escape safe
The defect is a class worth naming: an escape hatch that a later feature walks around. WEEKLY_SKIP_RUNNER_CHECK=1 is documented as release during an outage; the systemd-side row (#1546) landed afterwards and sat outside the guard, so the flag skipped GitHub's view and the preflight then failed on systemd's view for the same dead runner — i.e. the escape did not work in precisely the situation it exists for. Finding it by reading your own merged change (#1682) rather than by being bitten is the good version.
Three things make the fix right rather than merely wider:
- Both rows, for the same reason — "they fail for the same dead runner, so a flag that skipped only one of them could not do the job it documents". That is the argument, not "skip everything for symmetry", and it is the difference between an escape hatch and a hole.
- The skip is printed:
preflight: runner checks SKIPPED (WEEKLY_SKIP_RUNNER_CHECK=1). A release where the checks quietly did not run is the failure mode of every escape flag ever written — the log is what turns "we released during an outage" into something an auditor can find, and it costs one line. - The docs now say which row sees what (GitHub: registered/online, cannot say why / systemd:
Result=oom-kill, restart windows, units notactive) — which is the table I asked for mentally while reviewing #1682 and did not see. Two views that answer different questions, stated once, in the place people read before an outage.
One consequence worth stating, since this is the flag that gets used at 3 a.m.: skipping both rows means a release during an outage has no runner evidence at all — which is the intent, but the log line is the only record that it happened. If weekly.sh writes a release artifact, put the skip line in it too; a preflight: ... SKIPPED that only exists in a scrolled terminal is exactly the "green that does not mean what a reader takes it to mean" shape that #1504 exists to close.
The --self-test on ci-runner-health.sh (verdict logic with systemctl stubbed) is the right testing shape for a script whose job is to interpret another program's output.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at e7a4149370adce87d710d475fa5275c968a425a8
Ran both rows on this box rather than only reading the wiring: scripts/ci-runner-health.sh → 0, scripts/check-ci-runners.sh --require strixhalo-engine → 0, bash -n scripts/weekly.sh clean, and both scripts are present and executable (the -x guard is real, not aspirational).
The fix is the right one and the reason is stated exactly right:
WEEKLY_SKIP_RUNNER_CHECK=1is the release-during-an-outage escape, and it skips BOTH: a flag that skipped only one of them would be useless in exactly the outage it exists for, because both fail for the same dead runner.
That is the sentence this PR exists for. A half-wired kill switch is worse than none, because it produces a release that fails on the check you did not skip and leads to someone adding a second flag. It is implemented as one if around both rows, not two guards that could drift apart, and the skip path still says that it skipped — so a green release during an outage records why it was green.
The docs table earns its 33 lines by documenting the blind spots, not the features:
check-ci-runners.sh |
ci-runner-health.sh |
|
|---|---|---|
| cannot see | why it died — no oom-kill, no restart count |
a unit that is running fine while its registration is gone |
Two checks that each name what the other cannot see is the difference between defence in depth and defence by duplication. The exit-code contract is spelled out too (0 online · 1 an offender, named · **2 cannot tell**), and a fresh box lands on 2 → a note, not a failure (no actions.runner.* units on this host: systemd has nothing to inspect) — which is what keeps this from failing on any host that is not a runner, including every contributor's.
Not verified: the outage path itself — I did not set WEEKLY_SKIP_RUNNER_CHECK=1 and run a release, because a release must not be started from a review lane. The guard's shape (one if, both rows inside, message on the skip) is read from the diff and is unambiguous.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at e7a41493, with two notes — and one of them is that my first look at this diff was wrong, so here is the check that settled it.
The semantics are right, and this PR answers the question I left open reviewing #1682. There I asked whether an exit 2 from the runner check blocks a release. This change makes the two rows one preflight and states the rule explicitly: check-ci-runners.sh is GitHub's registered/online view and ci-runner-health.sh is systemd's why view (Result=oom-kill, restart window), exit 2 from the health row means "no actions.runner.* units on this host" — a fresh box, a note, not a failure — and WEEKLY_SKIP_RUNNER_CHECK=1 now skips both, with the reason spelled out (a flag that skipped only one is useless in the outage it exists for).
My first reading of the control flow was wrong, and I checked before filing: the grep -E "^\+" view made it look like health_rc=$? captured the status of the printf | grep -c | xargs pipeline in the then branch — which would have made the = 2 arm dead and turned a fresh box into a release failure. Reading the actual block, health_rc=$? sits at the top of the else, where $? is the if condition's status, i.e. the health script's own rc. Verified the guard semantics directly:
if out=$(cmd); then …; else rc=$?; [ "$rc" = 2 ] … fi with cmd exiting 2 -> rc=2 -> note path (correct)
So: not a bug, and the difference between "looks like a dead branch" and "is a dead branch" was one structural read.
Note 1 (worth fixing): there is no test for this. tests/ has nothing for weekly.sh's preflight, and this PR changes release-failure semantics — three paths (units healthy, no units → note, units unhealthy → bad=1). The stub above shows the guard is testable in isolation with a fake ci-runner-health.sh, which is how I checked it; a five-line test in the shape of tests/check_ci_runners_test.sh would pin the note-vs-failure distinction that this PR exists to make explicit.
Note 2: the else branch prints $health_out before the failure line, which is right, but the then branch collapses the output to a PASS count — so a release log shows why only on failure. That is a defensible choice; naming it here so a reader of a green log knows the count is all there was.
|
VERDICT: APPROVE at head Verifiedif [ "${WEEKLY_SKIP_RUNNER_CHECK:-0}" != 1 ]; then
if runner_out=$("…/check-ci-runners.sh" …); then … # GitHub's view
if [ -x "…/ci-runner-health.sh" ]; then # systemd's view
if health_out=$("…/ci-runner-health.sh" 2>&1); then …
else health_rc=$?
if [ "$health_rc" = 2 ]; then say "no actions.runner.* units on this host …"One The One gap, worth naming because it is silent
Not blocking: on a normal checkout the file is executable, so the row runs, and the PR's own docs addition ("which row sees what") is the durable part either way. |
Refs #1504. Found by reading my own merged change from #1682: a defect the review could not see, because it onlyshows up when the flag and a real outage meet.
The defect
WEEKLY_SKIP_RUNNER_CHECK=1is documented as the release-during-an-outage escape. The systemd-side row(
scripts/ci-runner-health.sh, #1546) landed after that guard was written and sat outside it — so the flagskipped the API row and the preflight then failed on the systemd row, for the same dead runner. The escape could not
do the one thing it exists for.
Measured on
origin/main'sweekly.sh, with a runner unit stubbed to the oom-kill shape and the flag set:The same arm on this branch proceeds. A flag that skips one of two rows answering the same question is worse than no
flag: it reads as an escape and is not one.
Arms, all four
runner units: 3 PASS in systemd's viewThe docs the merges left out
docs/ci-runners.mddescribedcheck-ci-runners.shbut said nothing about the second row the preflight runs. Newsection: what each reads, what each is blind to, how to run both by hand, that exit 2 means "nothing to inspect on
this host" (a note, not a failure), and that
WEEKLY_SKIP_RUNNER_CHECK=1skips both. It also names the one caseneither covers —
onlinein the API and active locally but wedged, where the only signal is a queue that stopsmoving while both rows stay green.
Docs-only plus one indentation-level change in the preflight; no new script, no new test (the four arms above are the
evidence, and both scripts keep their own tests).