Not in fact any relation to the famous large Greek meal of the same name.

Sunday, 27 April 2025

System-testing embedded code in Rust, part four: Github contributions

Previously on #rust:

Giuseppe Pellizza da Volpedo's painting 'The Fourth Estate' (Il Quarto Stato), representing the solidarity of workers      
Something really nice happened the other day!

Cotton, the collection of low-level Rust crates I started mostly for my own use, had previously seen a couple of small patches supplied by other contributors – but for the first time, I got a pull request for an actual fairly major feature that I knew had to be done, that was on my to-do list, but that I hadn’t yet started.

This is of course very cool, not just because it saves me the effort, but also because it proves that these crates are actually useful to someone, that it’s worth it to them putting in actual work to improve them.

The feature in question was updating the smoltcp dependency from 0.11 to 0.12, which doesn’t sound like a big job, but sort-of is, because the fundamental types used for IPv4 and IPv6 addresses have changed. (Those types are now in the “core”, usable-on-embedded, part of the standard library, whereas previously smoltcp had needed to invent their own ones.) All of this is a Good Thing, because it means that the crate APIs are exactly the same in embedded and host builds, and it cuts out a needless dependency (no-std-net), but it meant a certain amount of churn (and an MSRV update).

The interesting question was, how do I test this pull request before merging it? “Because Rust”, it’s actually pretty likely that if it compiles, it’s going to work. And it certainly compiles. But this is, in part, a blog about taking software testing seriously, so I want to run these changes past the system-test hardware rig – actual Raspberry Pi Picos and STM32s running actual firmware with the code in – because that’s the quality bar for “ready to merge to main”.

Because the system-tests use real embedded hardware, real devboards for RP2040 and STM32, they can’t run in Github’s cloud. (Nor do I really want them run automatically – a malicious PR could overclock the boards or permanently damage them in other ways.) So I need to run them locally. But my local CI runs on my local repo, and Github works by the contributor forking my repository, doing the work, and then asking me to merge their repository’s main back into my repository’s main. But I rather need their work to be in a branch in my repository, not on main in a different one. And I certainly don’t want main in my own repository changed to match theirs, at least until the tests have run.

But fortunately, Github is slightly fictionalising the actual situation here. “My” repository and “their” repository are, in some sense, still actually the same one behind the scenes at Github: it’s just that Github’s UI shows my branches to me when I log in, and their branches to them when they log in. I can still do a one-off git fetch of “their” repository and git (not -hub) just does the Right Thing.

Concretely, my generous contributor’s Github name is tshakah. To fetch the changes on their main to a new branch in my repository, I can just do a one-off fetch (which doesn’t even set the default upstream for that branch):

git fetch git@github.com:tshakah/cotton.git main:tshakah-smoltcp-0.12
and then I can push the new, local, tshakah-smoltcp-0.12 branch to my local CI and run it through all the tests.

And the tests passed! So I can just merge the branch to main locally in the usual way (i.e., rebased and with a no-fast-forward merge), and when I push main to github

git push github main
then the pull request is automatically closed completed. (Or at least, it is if I haven’t needed to rebase – which I’d need to do, for instance if Github main was behind local main. If I rebase the contribution branch, Github doesn’t always recognise it when I push the merge, so in that case I have to close the PR manually, while making it clear to the contributor that I’ve taken their changes and appreciate their efforts.)

And once everything’s done and dusted, I can delete my local tshakah-smoltcp-0.12 branch from my local git server in the usual way:

git push origin --delete tshakah-smoltcp-0.12
because “origin” is still my local git server and not my Github account (nor tshakah’s).

About Me

Cambridge, United Kingdom
Waits for audience applause ... not a sossinge.
CC0 To the extent possible under law, the author of this work has waived all copyright and related or neighboring rights to this work.