Skip to content

perf(ci): add caching, path filtering, and nextest to speed up CI#723

Open
wpfleger96 wants to merge 6 commits into
mainfrom
wpfleger/ci-perf-optimization
Open

perf(ci): add caching, path filtering, and nextest to speed up CI#723
wpfleger96 wants to merge 6 commits into
mainfrom
wpfleger/ci-perf-optimization

Conversation

@wpfleger96
Copy link
Copy Markdown
Collaborator

@wpfleger96 wpfleger96 commented May 22, 2026

Several CI jobs were compiling Rust from scratch on every push with no caching, and all jobs ran regardless of what changed — a frontend-only PR would still wait for two full musl cross-compile runs.

server-cross-compile (~7-8 min x 2 targets) and desktop-build-macos (~7-10 min) had zero cargo caching, making them the biggest uncached time sinks. Meanwhile, all 9 heavy jobs ran on every PR even when the relevant code hadn't changed.

  • Add dorny/paths-filter gating so jobs only run when their source trees change; all jobs still run on push to main/release. Filters include rust-toolchain.toml, deny.toml, .github/workflows/ci.yml, and pnpm-lock.yaml to avoid false negatives. Add missing desktop-rust trigger to desktop-e2e-integration.
  • Add Swatinem/rust-cache to server-cross-compile (with per-target key) and desktop-build-macos; add save-if: ${{ github.event_name != 'pull_request' }} to all 6 rust-cache instances to prevent cache writes on PR events (PRs still restore from cache for build speed)
  • Move docker compose up -d earlier in desktop-e2e-integration so containers boot during pnpm/Playwright install; scope to postgres redis typesense minio minio-init (the services CI actually needs); remove Docker image tar caching (direct pulls from GitHub's proxy are faster than restoring 600MB+ tarballs)
  • Switch pnpm caches from hardcoded store/v3 path (stale for pnpm 11 which uses store/v11) to dynamic pnpm store path --silent, and split into actions/cache/restore + actions/cache/save with push-only writes
  • Switch unit-tests to just test-unit (which auto-detects cargo-nextest with fallback); pin nextest to 0.9.136
  • Fix version comment mismatches flagged by zizmor: dorny/paths-filter (v3 -> v3.0.2), taiki-e/install-action (v2 -> v2.79.3), Justfile -> justfile case
  • Add .github/zizmor.yml to suppress cache-poisoning false positives on Swatinem/rust-cache — zizmor only recognizes lookup-only as a mitigation, not save-if (upstream bug filed)

@wpfleger96 wpfleger96 force-pushed the wpfleger/ci-perf-optimization branch from 935bd05 to 854f9cb Compare May 22, 2026 15:46
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Dismissed
Comment thread .github/workflows/ci.yml Dismissed
Comment thread .github/workflows/ci.yml Fixed
wpfleger96 added a commit that referenced this pull request May 22, 2026
Path filter gaps (missing desktop-rust, wrong Justfile case, missing
rust-toolchain.toml/deny.toml/ci.yml triggers), hardcoded pnpm store
path that missed the v11 directory, cache-poisoning from writing caches
on PR events, Docker tar caching that's slower than direct pulls, and
a diverged unit-test command between CI and Justfile.

Split pnpm caches into restore/save with push-only writes, add save-if
to new rust-cache instances, pin nextest to 0.9.136, and scope docker
compose to the 3 services CI actually needs.
Comment thread .github/workflows/ci.yml Fixed
Comment thread .github/workflows/ci.yml Dismissed
Comment thread .github/workflows/ci.yml Dismissed
Comment thread .github/workflows/ci.yml Dismissed
CI wall-clock time is bottlenecked by uncached Rust builds and jobs
running unnecessarily on unrelated changes. Server cross-compile
(~7-8 min × 2 targets) and Desktop Build macOS (~7-10 min) had zero
cargo caching; all jobs ran on every PR regardless of what changed.

- Add dorny/paths-filter gating so jobs only run when relevant files
  change (rust, desktop, web, mobile groups); push to main still runs
  everything
- Add Swatinem/rust-cache to server-cross-compile and
  desktop-build-macos (the two most expensive uncached jobs)
- Move docker compose up earlier in desktop-e2e-integration so
  containers boot during pnpm/Playwright install instead of after
- Add Docker image caching for postgres/redis/typesense in E2E job
- Add pnpm store cache to web, desktop, and desktop-e2e-integration
- Switch unit tests to cargo-nextest for parallel test execution
- Update Justfile test-unit to auto-detect nextest with script fallback
Path filter gaps (missing desktop-rust, wrong Justfile case, missing
rust-toolchain.toml/deny.toml/ci.yml triggers), hardcoded pnpm store
path that missed the v11 directory, cache-poisoning from writing caches
on PR events, Docker tar caching that's slower than direct pulls, and
a diverged unit-test command between CI and Justfile.

Split pnpm caches into restore/save with push-only writes, add save-if
to new rust-cache instances, pin nextest to 0.9.136, and scope docker
compose to the 3 services CI actually needs.
Add save-if to the 4 pre-existing Swatinem/rust-cache steps (rust-lint,
unit-tests, desktop, desktop-e2e-integration) so cache writes are
restricted to push events across the board, not just the 2 new instances.

Fix dorny/paths-filter version comment: the pinned SHA is v3.0.2,
not the floating v3 tag.
…tags

zizmor's cache-poisoning rule only recognizes lookup-only as a
mitigation for Swatinem/rust-cache, not save-if. All 6 instances
already have save-if set to prevent cache writes on PRs, but zizmor
can't introspect this parameter. Add inline ignore comments as a
stopgap until upstream fixes this (to be filed as a zizmor bug).

Fix taiki-e/install-action version comments: the pinned SHA is
v2.79.3, not the floating v2 tag.
The inline zizmor: ignore[cache-poisoning] comments appended to the
version comment didn't suppress the findings — zizmor may require the
directive as the first token after #. Switch to a .github/zizmor.yml
config file which suppresses cache-poisoning for ci.yml at the file
level, with a reference to the upstream bug (zizmorcore/zizmor#2051).

Add minio and minio-init to the selective docker compose up command
in desktop-e2e-integration — the relay now requires S3/MinIO for
the git object-store conformance probe added in #726.
@wpfleger96 wpfleger96 force-pushed the wpfleger/ci-perf-optimization branch from 5884832 to 89e9dcd Compare May 22, 2026 19:35
The zizmor scanner runs as an org-level GHAS integration, not from a
repo checkout — it never reads .github/zizmor.yml. Dismissed the
cache-poisoning alerts (#10-13, #32, #33) as false positives via the
code-scanning API instead, with references to the upstream bug
(zizmorcore/zizmor#2051).
@wpfleger96 wpfleger96 marked this pull request as ready for review May 22, 2026 20:45
@wpfleger96 wpfleger96 requested a review from a team as a code owner May 22, 2026 20:45
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.

2 participants