DEV Community

Anguo
Anguo

Posted on

rk-deploy v0.2: a real board caught the bug my test suite couldn't

rk-deploy v0.2: a real board caught the bug my test suite couldn't

Two weeks ago I shipped rk-deploy v0.1 — manifest-driven packaging, fleet push, atomic rollback and status reports for RKNN apps on Rockchip boards. v0.2 is out today, and the most interesting thing in it is not a feature. It's a bug that only existed on real hardware.

The uninstall bug that unit tests structurally missed

An external contributor (the project's first — he arrived within two hours of the v0.1 announcement) implemented rkdeploy uninstall: inventory the whole fleet first, refuse to delete the fleet's last installed copy unless you say so explicitly, keep shared/ data unless --purge is passed.

His test suite was thorough: 34 tests, fake systemctl, symlink refusal, stop failures, idempotency. Everything green on CI for Python 3.9 and 3.12.

Then I ran it on a real RK3588 board (systemd 249), following the documented flow: normal uninstall, then a later --purge to clean up the preserved shared/ data. The purge aborted with cannot-query-service-enable-state.

The cause: on systemd 249, systemctl is-enabled <unit> for a unit file that has already been deleted prints its error to stderr and leaves stdout empty. The board script treated "empty output" as "cannot determine" and aborted — fail-safe, nothing was deleted, but the documented two-step flow was broken. My fake systemctl in the test suite always printed something, so no test could see it.

The fix is one line of semantics (empty output in the unit-absent branch means not-found), plus a regression test that models the real missing-unit behaviour (empty stdout, exit 4). Then I re-ran the whole sequence on the board — deploy, refused last-copy delete, allowed delete, purge — before merging. Lesson I keep re-learning: for board tooling, the fake is a hypothesis; the board is the referee.

What else is in v0.2

Board diagnostics in status reports. The read-only probe now also reports the numeric systemd version, the shared-library SONAMEs from ldconfig -p (names only — no filesystem paths leak into reports), and every readable thermal zone's ID, type and temperature. On my RK3588 lab board that's 7 zones (soc-thermal 48 °C, bigcore0/1 49 °C, gpu 44 °C, npu 45 °C, …) and 1,617 library names. Diagnostics are emitted even when the app isn't installed, so a bare board can hand you a complete environment report — exactly what I need when someone says "it doesn't work on my RK3576".

Offline HTML fleet report. rkdeploy status --html report.html renders the same schema-1 data as a single self-contained file: inline CSS, no JavaScript, nothing fetched. One card per board, library count only (nobody needs 1,617 names in an HTML page). This is the artifact you attach to a delivery email.

Deploy dry-run. rkdeploy deploy --dry-run prints the per-board target root and the fully rendered systemd unit with zero SSH contact.

Four of the five v0.2 items came from that same external contributor's PRs, including a full Simplified Chinese translation of the spec. The repo still has 0 stars, which I mention because it's true — but it has something better: a second pair of eyes that found real work to do.

Still deliberately not doing

No resident agent, no central server, no Web UI. No automatic apt install — dependencies are reported as a preflight checklist, never silently changed on a customer's offline board. Rollback never migrates your data; if your app changed its on-disk format incompatibly, that's the app's job, and the docs say so.

Board reports for RK3576 / RK3566 / RK3568 are still the most valuable feedback I can get — issues #1 and #2 in the repo describe exactly what to run. If you deploy to Rockchip boards for a living, I'd like to hear what your ritual looks like.

Top comments (0)

⌂ 换网址