本机构建,一分钟装上板子
最后更新
改一行代码到看着机器人跑起来之间的循环:不用 push、不用等 CI、不用打 tag。
一条命令从仓库克隆为板子构建、签名、经 ssh 安装。增量构建约一分钟,而 push 加一次 CI 要好几分钟。
这条命令是 scripts/dev-push.sh,下面全都是它的参数。
第一次之前,三件事
做完就不用再管了。
1. 板子必须是开发板。 产物用团队 dev 密钥签名,零售机器人拒绝它,和拒绝 --ref 是同一个机制。见配置一块开发板。
2. dev 签名私钥放在 ~/.duck-keys/team.dev.key——就是 CI 给分支构建签名用的那把密钥的私有半边,团队成员手上有。放在别处就设 DUCK_DEV_SECRET_KEY。
3. 能为板子构建的工具链。 装交叉编译器:
cargo install cargo-zigbuild --locked
brew install zig
或者什么都不装,给每条 dev-push.sh 加 --docker,只需要一个运行中的 Docker 守护进程。这条路启动更慢,但在你还没有板子的时候它是唯一可行的那条。
循环本身
指定机器人名字,让推送自己去找它:
scripts/dev-push.sh --name duck-c51b
或者每个 shell 设一次:
export DUCK_ROBOT=duck-c51b
scripts/dev-push.sh
这个名字就是 duckctl scan 列出的、robotctl system set-name 设置的那个,也是 duckctl 读的同一个 DUCK_ROBOT。
地址是通过蓝牙问出来的(机器人自己的 net.status 应答),然后被缓存。只有当推送连不上缓存地址时才会回头去问无线电。这就是为什么换了 DHCP 租约、重新刷机、或者换个网络,都不需要你做任何事。
ssh 用户默认是 radxa,不是的话:
export DUCK_BOARD_USER=pierre
直接给地址也行,这样完全跳过无线电:
scripts/dev-push.sh radxa@192.168.1.42
export DUCK_BOARD=radxa@192.168.1.42
它做了什么
交叉编译整个 workspace → 打包成和正式发布完全相同的产物 → 用 dev 密钥签名 → 复制到板子的 ~/duck-sideload → 在那里通过 robotctl update apply --from 应用。然后等所有守护进程报告新版本:
==> building 0.5.1-dev.local.1763400000.g7fc1444 for the board (zigbuild)
==> packaging
==> signing with /Users/you/.duck-keys/team.dev.key
==> copying to radxa@192.168.1.42:/home/radxa/duck-sideload
==> applying on radxa@192.168.1.42
==> 0.5.1-dev.local.1763400000.g7fc1444 is live on radxa@192.168.1.42
==> checking every daemon is running it
current -> 0.5.1-dev.local.1763400000.g7fc1444
[ok] robotd
[ok] configd
[ok] padd
[ok] updaterd
[ok] btd
[ok] mediad
[ok] tofd
输出里哪些“异常”其实是正常的
这一节能省掉很多误判。
updaterd 和 btd 在 apply 应答之后五秒才重启,所以这两行会晚一点才出现。不是卡住了。
[--] padd published nothing 不是失败。它同时也是“守护进程被停掉了”或“被刻意禁用了”的样子,还是没装摄像头的板子上 mediad 的样子。
[--] tofd published nothing 意思是这个发布版早于”tofd 会公布自己身份“这个特性——再推一次就好了,而不是传感器没装:tofd 不管有没有装传感器都会运行。
它是一次普通的更新
这一点很重要:签名、产物哈希、兼容性检查、健康门禁、自动回滚,全都照常运行。 一个起不来的构建会被撤销,板子回到它之前跑的版本。
主动退回也是普通命令:
sudo robotctl update rollback daemon
板子上确认版本:
robotctl version
同一棵脏工作树推两次不会撞车——版本号里带的是这次推送的时间戳,不只是 commit。这里的工作树本来就该是脏的。
一边推一边看
在推送之前开第二个终端,这样重启过程能出现在里面:
ssh radxa@192.168.1.42 'journalctl -f -u robotd -u configd -u btd -u padd'
单独看 -u updaterd 则是更新本身——每个阶段、健康门禁,以及它触发的重启。