The flake job was the pipeline critical path at ~9 minutes, all of it one cold nix build — an empty /nix every run means recompiling the whole release closure under lto = "thin" + codegen-units = 1.
Cache /nix across runs, keyed on the lockfiles the closure derives from, so crane deps-only derivation survives and only maestro own crates rebuild. Saved from pushes only, so a PR cannot write a partial store.
Build only .#webFrontend on PRs — the step that guards pnpmDeps.hash. Release binaries stay on main. Trade-off: a Nix-packaging-specific break surfaces on main, not on the PR.
Swatinem/rust-cache replaces the hand-rolled target/ cache, which accumulated stale artifacts behind a prefix restore-key and cost ~60s per run to move.
Tests run under cargo-nextest, capped at 4 threads in .config/nextest.toml — the tmux-backed tests starve each other at the num-cpus default and trip their 5s deadlines.
actions/setup-node instead of a second apt-get pass via nodesource.
Measured before
job
total
breakdown
flake
557s
nix build 516s
rust
235s
cache 62s, test 69s, feature matrix 41s
web
100s
—
The `flake` job was the pipeline critical path at ~9 minutes, all of it one cold `nix build` — an empty /nix every run means recompiling the whole release closure under `lto = "thin"` + `codegen-units = 1`.
- Cache `/nix` across runs, keyed on the lockfiles the closure derives from, so crane deps-only derivation survives and only maestro own crates rebuild. Saved from pushes only, so a PR cannot write a partial store.
- Build only `.#webFrontend` on PRs — the step that guards `pnpmDeps.hash`. Release binaries stay on main. Trade-off: a Nix-packaging-specific break surfaces on main, not on the PR.
- Swatinem/rust-cache replaces the hand-rolled `target/` cache, which accumulated stale artifacts behind a prefix restore-key and cost ~60s per run to move.
- Tests run under cargo-nextest, capped at 4 threads in `.config/nextest.toml` — the tmux-backed tests starve each other at the num-cpus default and trip their 5s deadlines.
- actions/setup-node instead of a second apt-get pass via nodesource.
<details>
<summary>Measured before</summary>
| job | total | breakdown |
|---|---|---|
| flake | 557s | nix build 516s |
| rust | 235s | cache 62s, test 69s, feature matrix 41s |
| web | 100s | — |
</details>
The `flake` job was the pipeline's critical path at ~9 minutes, all of it
one cold `nix build`: with an empty /nix every run, it recompiled the whole
release closure under `lto = "thin"` + `codegen-units = 1`.
- Cache /nix across runs, keyed on the lockfiles the closure derives from,
so crane's deps-only derivation survives and only maestro's own crates
rebuild. Saved from pushes only, so a PR cannot write a partial store.
- Build only `.#webFrontend` on PRs — that is the step that guards
pnpmDeps.hash. The release binaries stay on main.
- Replace the hand-rolled `target/` cache with Swatinem/rust-cache, which
prunes to the current lockfile instead of accumulating stale artifacts
behind a prefix restore-key. ~60s per run went into moving that entry.
- Run tests under cargo-nextest, which parallelises across the 20
integration binaries. Capped at 4 threads in .config/nextest.toml: the
tmux-backed tests starve each other at the num-cpus default and trip
their 5s deadlines.
- actions/setup-node instead of a second apt-get pass via nodesource.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The
flakejob was the pipeline critical path at ~9 minutes, all of it one coldnix build— an empty /nix every run means recompiling the whole release closure underlto = "thin"+codegen-units = 1./nixacross runs, keyed on the lockfiles the closure derives from, so crane deps-only derivation survives and only maestro own crates rebuild. Saved from pushes only, so a PR cannot write a partial store..#webFrontendon PRs — the step that guardspnpmDeps.hash. Release binaries stay on main. Trade-off: a Nix-packaging-specific break surfaces on main, not on the PR.target/cache, which accumulated stale artifacts behind a prefix restore-key and cost ~60s per run to move..config/nextest.toml— the tmux-backed tests starve each other at the num-cpus default and trip their 5s deadlines.Measured before