feat(ci): substitute from the shared binary cache - #59
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6362449. Configure here.
Every workflow built everything from source, including the SDKs, while the
cache the rest of the company uses sat next to it unused.
Only `main` and the tags write. What a pull request builds is decided by its
branch, and so is what a merge queue builds — an entry that is dequeued was
never on `main` at all. A run there that could write would let any branch put a
store path in front of every other repository's builds. The ref decides this
rather than the event name, which gets two cases wrong: a run started by hand
is not a `push`, and a `push` is whatever branch a repository chose to run on.
Reading may fail without failing the workflow: a cache out of reach should cost
a run its time and not its result. Writing may not, so the step takes
`{ required }` for the run whose purpose is to fill it.
Signed-off-by: Niklas Zender <n.zender@famedly.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The cache the commit before this one wired up has no writer here. This repository's only workflow runs on pull requests and the merge queue, the queue is not enabled at all, and nothing runs on `main` — so every run would read from a cache that stays empty. A workflow on `main` now builds what every repository pinning these standards resolves against and hands it over: the devshell, both SDKs, the Rust toolchain, and vodozemac. Unlike every other workflow it fails loudly when it cannot, because the run that writes is the one every other repository waits on. vodozemac is what earns the run. It is a Rust build rather than a download, it is the same library for everyone, and it was only a package where a Dart project had already asked for it — so the repository that could most cheaply build it never did. It is unconditional now. `x86_64-linux` only, though the option reaches all three systems. Darwin bills ten times the minutes to move SDK archives Google already built, which shortens nobody's wait, and the one thing genuinely compiled there takes 24 seconds. GitHub's arm64 Linux runners reached private repositories in January against the same free minutes as the x64 ones, so the option can name one once an arm64 image build downstream turns out to compile something worth caching. Signed-off-by: Niklas Zender <n.zender@famedly.com> Co-authored-by: Cursor <cursoragent@cursor.com>
tlater-famedly
left a comment
There was a problem hiding this comment.
I don't think we need a separate workflow for uploads; the cachix action will implicitly fill the cache with any used artifacts, and the other workflows will be exercising those. Let's reduce the amount of workflow clutter.
#50 already covers enabling cachix, on the other hand, it's just blocked by the fact that our CI secrets don't currently work this way.
| - uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 | ||
| - uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 | ||
| with: | ||
| authToken: ${{ secrets.CACHIX_AUTH_TOKEN_FAMEDLY }} |
There was a problem hiding this comment.
This doesn't work in public repos

Every workflow builds the SDKs and the vodozemac bindings from source, while
the
famedlyCachix the rest of the company uses sits unused next to it.Reading. A step in
steps.setup, so every generated workflow gets it. Itmay fail without failing the workflow: a cache out of reach should cost a run
its time and not its result.
Writing. Only
mainand tags. A pull request and a merge queue entry bothbuild what a branch decided, and a run there that could write would let any
branch put a store path in front of every other repository's builds. The ref
decides this rather than the event name, which gets two cases wrong: a run
started by hand is not a
push, and apushis whatever branch a repositorychose to run on.
Filling. Nothing here runs on
maintoday, so the cache would have stayedempty no matter who read it.
populate-binary-cachebuilds what everyrepository pinning these standards resolves against — the devshell, both SDKs,
the Rust toolchain and vodozemac — and, unlike every other workflow, fails
loudly when it cannot hand them over. Other repositories need nothing: the
option is empty by default, and what a workflow on
mainbuilds anyway isalready pushed by the step in
setup.x86_64-linuxonly here, though the option reaches all three systems. Darwinbills ten times the minutes to move SDK archives Google already built, which
shortens nobody's wait; the one thing genuinely compiled there is vodozemac, at
24 seconds.
aarch64-linuxbecame a standard runner in private repositories inJanuary and costs no more than x64, so it is worth revisiting once we know
whether the arm64 image builds downstream compile anything the cache could hand
them.
vodozemac had to become an unconditional package to be built here at all: it was exposed only where a Dart project asked for it, and this repository has none.
Supersedes #50. Conflicts with #56, which moves the vodozemac module and adds an import next to this one's; whichever lands second wants a rebase.
Test plan
nix flake check --all-systems,prek --all-files --stage pre-pushcarries it without
continue-on-errorskipPushis false only forrefs/heads/mainandrefs/tags/*, so apull request, a merge queue entry and a dispatch from a branch all read
mainafter merge fills the cache, and a later pull requestsubstitutes vodozemac instead of building it