Repository navigation
CI proposal: container-based validation lane for the packaging shell scripts (uci-defaults) #521
Description
Problem
make go-battery (now unified across all 16 Go modules, #455) gates the Go side — but the shell that configures routers (packaging/files/etc/uci-defaults/99-tollgate-setup, hotplug scripts, maintainer scripts) has no automated lane. Two recent incidents landed exactly in that gap:
- apk: 99-tollgate-setup version gate always resolves to "unsubstituted" — full setup never re-runs after first boot #459 — the version gate's case-pattern sentinel was rewritten by the packaging's global placeholder substitution; full setup silently never re-ran on apk. Found by a field report on real hardware, not by any CI check.
- fix: assign radios by band, not section index (radio0 is not always 2.4 GHz) #452 — the radio band-binding logic (7 hardware topologies) could only be validated off-router with ad-hoc scaffolding assembled by hand.
Proposal
A CI lane (and locally runnable script) that exercises the setup script inside real OpenWrt userspace — the openwrt/rootfs Docker images — against fixture /etc/config/wireless topologies with authored ground truth:
- One
--rmcontainer per topology: normal, swapped-band, single-band, tri-band, legacy-hwmode, misbound-upgrade, STA-preserved. - Each container seeds minimal router defaults (the rootfs image ships without
/etc/config/networketc. — this gap itself exercised the script's designed no-LAN guard), installs the fixture, runs the setup script (full path + same-version verify path), then runs a fixed assertion block over the resulting uci state. - Run the matrix on both
x86-64-openwrt-24.10(opkg) andx86-64-25.12-SNAPSHOT(apk) — real BusyBox ash and realucisemantics, which is where GNU-vs-BusyBox and stub-uciharnesses diverge from reality.
What it catches
The #459 bug class (script-shape regressions invisible to bash -n), band-binding regressions, STA-preservation and credential-preservation breaks, verify-path drift, and BusyBox incompatibilities — before merge, with no hardware.
Evidence this works
This exact kit ran during #452 validation: 66/66 assertions green on each image, plus it surfaced two real issues in my own scaffolding that a weaker harness missed. The full kit (fixtures, driver, assertion block, runner, logs) is here: https://gist.github.com/Amperstrand/db914f7d6b1fb6e749bc3c6b7ca97980 (NOTES.md documents the operational gotchas, including the rootfs missing-defaults trap).
Cost
~2 minutes of CI, two public Docker images, ~300 lines of fixtures+driver. Docker-in-CI prerequisite; ngit runners would need container support (the GitHub-side twin is being archived per #457, so this may belong in the ngit pipeline's future container lane).
Relationship to existing work
Complements #470's static guard (check-version-sync.sh §5b) — that one catches placeholder duplication textually; this catches behavioral regressions. The assertion block is the executable form of #452's router runbook.
Filed by request of the account holder; implementation offered separately.
Activity
test(packaging): rootfs-container tier for uci-defaults validation
test(packaging): rootfs-container tier for uci-defaults validation
test(packaging): rootfs-container tier for uci-defaults validation
test(packaging): rootfs-container tier for uci-defaults validation — …
Amperstrand commentedon Oct 6, 2026
Delivered: the rootfs-container validation tier for the uci-defaults scripts landed via #530's rebase (#671) and runs as part of the packaging gate in
make release-check. Closing as shipped.