Run the infrastructure bench suites weekly, and fix what they found - #276
Open
danielrmerskine wants to merge 1 commit into
Open
Run the infrastructure bench suites weekly, and fix what they found#276danielrmerskine wants to merge 1 commit into
danielrmerskine wants to merge 1 commit into
Conversation
Of the 38 bash integration suites, CI executed exactly one; the rest were syntax-checked but never run. New "Bench: Extended" (bench-extended.yml), Saturday 14:17 UTC, runs the infrastructure suites -- box-level tests needing NO instruments, so the workflow carries none of integration-tests.yml's relay/firmware machinery and the bench stays dark throughout. Leaf workflow on the shared hardware-ci concurrency group; no pull_request trigger ever (public repo, self-hosted runner); failure notifies the shared bench-alert issue, and there is deliberately NO recovery job -- closing that alert is exclusively the nightly's signal. Five of the seven suites are wired. boxes_config.sh is not: its discovery section inventories every box reachable from the runner's network and prints the results, and a full network inventory does not belong in a CI log. It stays runnable by hand; wiring it needs a CI-safe output mode (counts, not names) first. python.sh is not wired either: 53 of its checks call `lager python -c` for inline execution and there is no `-c` option, so it fails 43 of 84. Three more pass `--image`, also gone. It needs the rewrite devenv.sh already had, against the current interface, and that is its own change. Baselining 43 would record "calls an option that does not exist" as the expected state. Each suite declares a baseline -- the number of its checks known to fail today -- and tools/bench_suite_gate.sh ratchets two-sided: more failures than the baseline is red, fewer prints a notice telling you to lower it. That is what lets this land green without softening a single assertion. Every non-zero baseline names the issue that owns it. The gate also fails when a suite produces no summary at all, which is what a crash or a step timeout looks like; that case is not a pass. Reading the gate matters, because the step ticks lie: a continue-on-error step shows green whether its suite passed, failed, or timed out. WHAT THE RUNS FOUND Test defects, fixed here: - `lager boxes add` now requires --user; 33 call sites predated that. - deployment.sh read the removed `lager duts` registry in three spots and called `lager duts --help`, which is gone -- and its `set -e` meant the first failure killed the run before its own summary printed, hiding every later result. Now `lager boxes`, `lager dut`, `set +e` to match every other suite in the directory. - python.sh had a hard DOCKER_IMAGE guard on line 15 that aborted the whole suite before a single check ran, for the sake of two optional checks. That is why none of its ~100 checks had ever run anywhere. - devenv.sh tested the removed named-environment CLI; rewritten against the current per-project model. 13/13. - generic.sh asserted that `boxes add --ip` rejects things like "999.999.999.999" and "not.an.ip.address". It does not, by design: --ip takes an IP *or* a DNS hostname, and those are valid hostname syntax. Those checks now cover what the validator genuinely refuses: URL, path, port, empty, invalid label. - Assertions pinned to strings the CLI no longer prints: `nets --help`, `boxes edit`, `defaults add`. - deployment.sh inspected containers named `controller` and `python`. There is one container, named `lager`, so both checks failed on every box -- a stale expectation reported as a box fault. - python.sh called `lager python --kill` with no process ID in eight places. --kill takes a PID; killing everything is --kill-all. Passing neither made click consume the following --signal as the PID and then reject the signal name as a script path, so every kill check in the suite was malformed. Product behaviour the suites exposed, filed separately: `lager hello` failing under sustained repetition (#273), and `box config` sysctl and cargo entries not applying or clearing (#275). python.sh additionally surfaced `--timeout` never firing and a detached launch that does not return (#274). Three of the five suites end up expecting zero failures. The two that do not each name the issue that owns them. HANGS AND THE BOX LOCK Two CLI paths stalled indefinitely on the bench. Bounding them one at a time cost a bench round each, so python.sh now wraps `lager` in a shell function that bounds every call. A hang is a failed check that names itself instead of a suite that stalls until its step timeout. That mattered more than it first appeared. The CLI releases its auto-lock three ways -- try/finally, atexit, and a SIGTERM/SIGINT/SIGHUP handler -- but a step timeout ends in SIGKILL, which cannot be caught, so the box-side TTL (1800s) is the only backstop. An expired lock is reaped without --force; an unexpired one blocks the next run outright, a real collision for back-to-back runs that cost two rounds here. This workflow force-releases before its connectivity check, matching the call update-regression.yml already makes for its own leak path. Forcing is safe because the hardware-ci concurrency group serialises bench workflows against this box. ALSO static-checks now shellchecks and syntax-checks tools/ as well as test/. Those scripts are CI's own machinery -- one files public issues, one gates these suites -- and they were never linted. They pass with no exclusions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Of the 38 bash integration suites, CI executes exactly one. This adds Bench: Extended (
bench-extended.yml), a weekly job on the self-hosted bench that runs five of the seventest/integration/infrastructure/suites -- the box-level ones needing no instruments, so the bench stays dark for the whole run.Saturday 14:17 UTC, clear of the nightly's worst case. Leaf workflow on the shared
hardware-ciconcurrency group. Nopull_requesttrigger, ever: public repo, self-hosted runner. Failure updates the sharedbench-alertissue; there is deliberately no recovery job, because closing that alert is the nightly's signal and a green weekly must never mask a nightly that is still failing.The gate
Each suite declares a baseline -- how many of its checks are known to fail today -- and
tools/bench_suite_gate.shratchets two-sided:That is what lets this land green without softening a single assertion. Every non-zero baseline names the issue that owns it. A suite that produces no summary at all -- a crash, a step timeout -- is red regardless of its baseline; that case is not a pass.
deployment.shdevenv.shnets.shbox_config.shgeneric.shhellounder sustained repetition -- #273Three of the five expect zero failures. The two that do not each name the issue that owns them, and the baseline comes down as those are fixed.
Reading the gate is the point: a
continue-on-errorstep shows a green tick whether its suite passed, failed, or timed out. The step ticks cannot be trusted and the annotations can.Two suites are deliberately not wired
boxes_config.sh-- its discovery section inventories every box reachable from the runner's network and prints the results. A network inventory does not belong in a CI log. It stays runnable by hand; wiring it needs a CI-safe output mode (counts, not names) first.python.sh-- it does not test the CLI we ship. 53 of its checks calllager python -c "<code>"for inline execution and there is no-coption; the runner reportsError: No such option '-c'and the suite fails 43 of 84. Three more pass--image, also gone. It needs the rewritedevenv.shalready had, against the current interface, and that is its own reviewable change. Baselining 43 would record "calls an option that does not exist" as the expected state and leave the ratchet watching for a 44th.What the runs found
Eight supervised bench rounds. Test defects, fixed here:
lager boxes addnow requires--user; 33 call sites predated that.deployment.shread the removedlager dutsregistry in three places and calledlager duts --help. Itsset -emeant the first failure killed the run before its own summary printed, hiding every later result.devenv.shtested the removed named-environment CLI; rewritten against the current per-project model. 13/13.generic.shasserted thatboxes add --iprejects999.999.999.999andnot.an.ip.address. It does not, by design ----iptakes an IP or a DNS hostname, and both are valid hostname syntax. Those checks now cover what the validator genuinely refuses.nets --help,boxes edit,defaults add.deployment.shinspected containers namedcontrollerandpython. There is one container, namedlager. Both checks failed on every box, reporting a stale expectation as a box fault.Product behaviour, filed separately:
lager hellofailing under sustained repetition (#273) andbox configsysctl and cargo entries not applying or clearing (#275).python.shadditionally surfaced--timeoutnever firing and a detached launch that does not return (#274).The box lock
The CLI releases its auto-lock three ways --
try/finally,atexit, and a SIGTERM/SIGINT/SIGHUP handler -- but a step timeout ends in SIGKILL, which cannot be caught. The client-side release never runs, and the box-side TTL (1800s by default) becomes the only backstop. An expired lock is reaped automatically and needs no--force; an unexpired one blocks the next run outright.That collides for back-to-back runs -- a re-run after a timeout, or dispatches during a debugging session, land well inside 30 minutes. It happened twice during this validation. It is not a threat to the schedule: the nightly and this weekly are hours apart, so any leaked lock has long expired by then.
This workflow force-releases before its connectivity check, matching the call
update-regression.ymlalready makes for its own leak path. Forcing is safe here because thehardware-ciconcurrency group serialises bench workflows against this box, so a lock still held when the job starts belongs to a run that is no longer running.Also
static-checksnow shellchecks and syntax-checkstools/as well astest/. Those scripts are CI's own machinery -- one files public issues, one gates these suites -- and were never linted. They pass with no exclusions at all.Verification
nets.shand half ofgeneric.sh's failures turned out to be caused bypython.shrunning ahead of them in the same job; with it unwired,nets.shpasses all 25 and
generic.shdrops from 10 failures to 5. Failures thatbelong to no suite are exactly what a baseline must not record.
shellcheck -S warningandbash -nclean acrosstest/andtools/.notify-failureguard are removed in the same commit; the finalon:block isschedule+workflow_dispatchonly.