Skip to content

Bound nix cache size in FFI CI workflows - #1814

Merged
benalleng merged 1 commit into
payjoin:masterfrom
emmanuelist:ci-bounded-nix-cache
Aug 19, 2026
Merged

Bound nix cache size in FFI CI workflows#1814
benalleng merged 1 commit into
payjoin:masterfrom
emmanuelist:ci-bounded-nix-cache

Conversation

@emmanuelist

Copy link
Copy Markdown
Contributor

Follow-up to #1131, with the measurements in
#1131 (comment).

magic-nix-cache-action writes one GitHub cache entry per nix store path. Upstream
currently holds 1031 entries totalling 10.46 GiB against a 10 GB quota, of which only 15
are the Swatinem/rust-cache entries the jobs actually reuse. GitHub then evicts
least-recently-used entries, so identical keys hit or miss depending on which PR ran last.

This swaps the four FFI workflows to
nix-community/cache-nix-action,
which stores the nix store as one bounded entry per workflow per runner OS, with
purge on so only the newest survives per key.

I tested it on my fork before opening this. All three testable FFI workflows passed
(csharp is excluded from the fork test only because its unrelated build-nuget-native
cross-compile matrix would have run too):

entries size
fork before 298 11.29 GiB
fork after 14 9.09 GiB

The 6 entries this action created, one per workflow per OS:

1.16 GiB  nix-Linux-dart-3a4d0953...
0.26 GiB  nix-Linux-javascript-3a4d0953...
0.26 GiB  nix-Linux-python-3a4d0953...
0.41 GiB  nix-macOS-dart-3a4d0953...
0.26 GiB  nix-macOS-javascript-3a4d0953...
0.26 GiB  nix-macOS-python-3a4d0953...
                                   total 2.61 GiB

With csharp included that is 8 entries rather than the thousands magic-nix-cache
produces, and CI runs were green so gc-max-store-size: 1G is not too tight for these
devshells. The number is easy to tune if you'd rather trade quota for fewer GC passes.

Fork runs: https://github.com/emmanuelist/rust-payjoin/actions?query=branch%3Aci-bounded-nix-cache

I left rust.yml, format.yml and crates-release.yml on magic-nix-cache-action so
this can be judged on the FFI workflows first. Happy to convert those too, or to close
this if you'd rather go a different way (dropping nix caching from the FFI jobs entirely,
or moving it off the GitHub quota to FlakeHub or Cachix were the other options I listed
in #1131).

Disclosure: co-authored by Claude Code.

@benalleng
benalleng self-requested a review August 17, 2026 23:16
@benalleng

Copy link
Copy Markdown
Collaborator

Its beautiful 🥲

image

@benalleng benalleng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CACK, looks functional.

Looking through the cache-nix-action options everything looks mostly covered. I am intrigued by the ability to use lookup-only for specific "release" type runs but maybe that is overkill.

@benalleng

benalleng commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Feel free to add this to other workflows in new commits. I would like to merge them all together in this PR.

@coveralls

coveralls commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 32272924268

Coverage remained the same at 86.718%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 16458
Covered Lines: 14272
Line Coverage: 86.72%
Coverage Strength: 343.46 hits per line

💛 - Coveralls

@emmanuelist

Copy link
Copy Markdown
Contributor Author

Added the rest of the workflows in three commits, so magic-nix-cache-action is out of
the repo now. The rust.yml keys are scoped per job since Test and Coverage build
.#nginx-with-stream while Lint just uses the default shell, so one shared key would
have them clobbering each other.

Couple of things you should know before merging though.

I got the attribution wrong in #1131. I had measured entry counts and then wrote as
if I had measured bytes. The real split upstream is magic-nix-cache at 1593 entries
but only 1.11 GiB, against Swatinem/rust-cache at 15 entries and 9.52 GiB. So this PR
takes the entry count down a lot and stops the churn, but it won't stop the eviction
#1131 is actually about. I've posted the full numbers and a save-if idea over
there. Still think this is worth merging, just not the fix I made it sound like.

On lookup-only, I had a look and I don't think it does what we'd want. When true it
skips restoring on a primary-key hit, and per the action it "doesn't change the
behavior of cache saving in any case". save: false is the one that stops a job
writing a cache. I've left saving on everywhere so the pattern stays uniform, but the
four crates-release.yml jobs are the obvious spot if you'd rather the release path
only read. Happy to add it.

One gap worth flagging: crates-release.yml doesn't actually get exercised by this PR.
Its pull_request trigger is filtered to the three Cargo.toml paths and the push
trigger is tags only, so those four conversions are going in untested. Same thing as
the dart workflow in #1810. Everything else ran green on my fork and here.

Disclosure: co-authored by Claude Code.

@benalleng

Copy link
Copy Markdown
Collaborator

We actually are modifying the nix cache workflow jobs unrelated to caching in #1819. Since that will greatly dedupe the caching steps you might want to rebase onto that once I merge it in.

On lookup-only, I had a look and I don't think it does what we'd want.

Yeah once I read the config again I realized that it isn't what I thought

crates-release.yml doesn't actually get exercised by this PR.

That's fine. We can always YOLO test at a later date. Likely worst case the cache fails for those.

@emmanuelist

emmanuelist commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto #1819. That collapsed most of this, since the nix setup now lives in
.github/actions/setup-nix and I only had to change it in the one place. Down from 7
files to 2, and rust.yml only because #1819 didn't touch it.

Keys are scoped by github.job now instead of a name I picked per workflow. I checked
and every job id that pulls in setup-nix is unique across the workflows, so nothing
collides and the composite action doesn't need an input for it. That also picks up
verify-tag-hygiene.yml for free.

Thanks for the steer on #1819, it's a much smaller change this way.

@benalleng benalleng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there is a valid reason I am missing the rust jobs should also use this new setup-nix/action

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to not simply use the setup-nix/action job for these workflows as well instead of copying them?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed I guess I missed those in my refactor, they should use the shared nix setup action too.

magic-nix-cache-action writes one GitHub cache entry per nix store path,
which churns through the Actions cache API and leaves over a thousand
entries behind. Swap it for nix-community/cache-nix-action, which keeps
the store as a single bounded entry per job, purging all but the newest.

Point the rust jobs at the shared setup-nix action too, rather than
repeating the install and cache steps inline, so there is one place to
change this.

Keys are scoped by `github.job` because jobs realise different store
closures, and job ids are unique across the workflows that set nix up.

Note this reduces entry count and churn but does not by itself free the
cache quota: Swatinem/rust-cache accounts for 9.32 GiB of the 10 GB
against cache-nix-action's 0.59 GiB. See payjoin#1131 for the numbers.
@emmanuelist
emmanuelist force-pushed the ci-bounded-nix-cache branch from 7e4b495 to 29b8e88 Compare August 19, 2026 15:55

@benalleng benalleng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 29b8e88

Hopefully this will at least make it easier to make sense of the cache churn when looking in the cache logs

@benalleng
benalleng merged commit 04e7c2d into payjoin:master Aug 19, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants