Build here, install on the board
Last updated
The loop between changing a line and watching the robot run it, with no push, no CI run and no tag. About a minute on an incremental build, against several for a push plus a CI run.
scripts/dev-push.sh is that command.
Once, before the first push
The board has to be a dev board. The artifact is signed with the team dev key, so a customer robot refuses it exactly as it refuses --ref. See Setting up a dev board.
The dev signing key goes at ~/.duck-keys/team.dev.key. Set DUCK_DEV_SECRET_KEY if yours lives elsewhere.
A toolchain that can build for the board. Either install the cross-compiler:
cargo install cargo-zigbuild --locked
brew install zig
Or install nothing and pass --docker, which needs only a running Docker daemon — slower to start, and the path to reach for before you have a board at all.
The loop
scripts/dev-push.sh --name duck-c51b
# or once per shell
export DUCK_ROBOT=duck-c51b
scripts/dev-push.sh
The name is the one duckctl scan lists. Its address is asked for over Bluetooth and then cached, so only a push that cannot reach the cached address goes back to the radio. That is what makes a new DHCP lease, a reflash or a different network cost nothing to follow.
The ssh user is radxa; export DUCK_BOARD_USER=pierre if yours is not. An address works too and skips the radio entirely.
What it does
Cross-compiles the workspace, packages the same artifact a release does, signs it with the dev key, copies it to ~/duck-sideload on the board, and applies it there through robotctl update apply --from. Then it waits for the daemons to report the new release:
==> building 0.5.1-dev.local.1763400000.g7fc1444 for the board (zigbuild)
==> signing with /Users/you/.duck-keys/team.dev.key
==> applying on radxa@192.168.1.42
==> checking every daemon is running it
[ok] robotd
[ok] configd
...
Which “problems” in that output are not problems
This saves a lot of misreading.
updaterd and btd restart five seconds after the apply replies, so those two lines take a moment. Not a hang.
[--] padd published nothing is not a failure. It is also what a stopped or deliberately disabled daemon looks like, and what mediad looks like on a board with no camera.
[--] tofd published nothing means a release from before tofd published an identity at all — one more push fixes it — rather than a sensor that is missing. tofd runs whether or not one is fitted.
It is an ordinary update
The signature, the artifact hash, compatibility, the health gate and auto-rollback all run. A build that does not come up is reverted and the board is back on what it was running. Going back on purpose is the ordinary command too:
sudo robotctl update rollback daemon
Two pushes of the same dirty tree never collide — the version carries the push’s timestamp, not just the commit. The tree is expected to be dirty here.
Watching what you pushed
From a second terminal, before the push, so the restart shows up in it:
ssh radxa@192.168.1.42 'journalctl -f -u robotd -u configd -u btd -u padd'
-u updaterd on its own is the update itself — each phase, the health gate, and the restarts it triggers.