Skip to content

ci: split and shard the desktop lanes, and fix a dead path filter - #118

Merged
yjc801 merged 7 commits into
mainfrom
claude/desktop-core-timeout-41eaa2
Sep 2, 2026
Merged

yjc801 merged 7 commits into
mainfrom
claude/desktop-core-timeout-41eaa2

Conversation

@yjc801

@yjc801 yjc801 commented Sep 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

Desktop Core was the CI critical path at ~29 minutes across the last dozen runs, while the next-longest job finished in under 8. It ran the frontend checks and the Tauri Rust checks back to back in one lane, so every desktop PR waited on the sum.

This PR splits it into parallel lanes and then, by owner decision, drops the compiled-flag matrix from the PR path.

  • Desktop Core — lint/format, unit tests, frontend build. Pure TypeScript, no Tauri Linux deps, mold, or Rust cache. ~6 min.
  • Desktop Tauri — clippy, check, tests. ~11–14 min. This is the new desktop critical path.
  • Desktop Tauri Compiled Flags — sharded one job per BUZZ_BUILD_* state (list read from the Justfile's compiled_flag_states), then disabled with if: false in the final commit. The sharded recipe, the state list, and the matrix generation all stay so re-enabling is restoring one if: line.

Details:

  • Both Tauri lanes build the frontend first because tauri_build::try_build resolves frontendDist, and share one rust-cache entry via shared-key.
  • Only Desktop Core saves the pnpm store, so concurrent saves of one key cannot race.
  • The desktop aggregator requires Desktop Core and Desktop Tauri to succeed and tolerates skipped for the disabled compiled-flags lane; ci-complete lists all three.
  • scripts/test-path-filter-contract.sh guards the paths-filter groups against patterns that match nothing (the justfile vs Justfile case bug).
  • The dead Upload desktop e2e artifacts step is dropped; the lane never ran Playwright.

Coverage trade-off (deliberate)

With the compiled-flags lane off, nothing in CI or the pre-push hook compiles a build with a BUZZ_BUILD_* flag set. The three flag assertions are #[ignore]d, so just desktop-tauri-test never reaches them, and the flag-sensitive non-ignored tests only run in the default state. A flag regression surfaces in a release build with that flag set, or when someone runs just desktop-tauri-test-compiled-flags by hand (the lefthook comment now says to do that when touching a flag). Owner accepted this to keep the PR path short.

Test plan

  • ci.yml parses as YAML; desktop-tauri-compiled-flags.if is false, matching the smoke-E2E pattern
  • scripts/test-path-filter-contract.sh passes
  • Sharded matrix green before disable (run 33619719783): shards 9m48s / 10m37s / 10m41s in parallel
  • CI on the current head (run 33642572134): Desktop Core and Desktop Tauri green, Compiled Flags skipped, Desktop and CI Complete green

🤖 Generated with Claude Code

@yjc801 yjc801 changed the title ci: disable the Desktop Core lane ci: split the Desktop Core lane into three parallel lanes Sep 2, 2026
@yjc801 yjc801 changed the title ci: split the Desktop Core lane into three parallel lanes ci: split Desktop Core into three parallel lanes Sep 2, 2026
yjc801 added a commit that referenced this pull request Sep 2, 2026
On its own lane the compiled-flag matrix took 33m40s on PR #118, longer
than the old combined Desktop Core lane it was split out of, so it was
still the desktop critical path. Turn it off the same way the smoke E2E
shards are turned off (if: false, original condition kept in a comment)
and let the Desktop aggregator accept its skipped result.

Desktop Core (~6m) and Desktop Tauri (~11m) stay on. Nothing else runs
`just desktop-tauri-test-compiled-flags`, so the lefthook comment now
says to run it by hand when touching a compiled flag.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: Junchao Yan <[email protected]>
@yjc801 yjc801 changed the title ci: split Desktop Core into three parallel lanes ci: split and shard the desktop lanes, and fix a dead path filter Sep 2, 2026
yjc801 and others added 6 commits September 2, 2026 07:15
The lane routinely runs far too long. Turn it off the same way the smoke
E2E shards were turned off (if: false, original condition kept in a
comment for re-enabling), and let the Desktop aggregator accept its
skipped result so downstream contexts still resolve.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: Junchao Yan <[email protected]>
Desktop Core was the CI critical path at ~29 minutes across the last
dozen runs, while the next-longest job finished in 7m36s. It ran the
frontend checks and the Tauri Rust checks back to back in one lane, so
every desktop PR waited on the sum.

Disabling the lane outright would have removed the only CI run of
`just desktop-check` (biome + the zoom-safe px-text and pubkey-truncation
guards) and `just desktop-test`, and the only run anywhere of
`just desktop-tauri-test-compiled-flags`, which verifies the owner-only
agent-access capability and the auto-connect flag in both compiled
states. Pre-push hooks cover some of that but are bypassable, absent on
web edits, and never ran the compiled-flag matrix at all.

Split into three lanes that run in parallel instead, keeping every check:

- Desktop Core — lint/format, unit tests, frontend build. Pure
  TypeScript, so it no longer installs the Tauri Linux deps, mold, or the
  Rust cache. ~6 minutes.
- Desktop Tauri — clippy, check, tests. ~8 minutes.
- Desktop Tauri Compiled Flags — the compiled-flag matrix, which was
  15m11s of the old lane's 28m59s because each permutation forces a full
  rebuild through `build.rs`'s rerun-if-env-changed.

Both Tauri lanes need the frontend built first because
`tauri_build::try_build` resolves `frontendDist` (`../dist`), and they
share one `rust-cache` entry via `shared-key` rather than each keying on
their own job id. Only Desktop Core saves the pnpm store, so three
concurrent saves of one key cannot race.

The `desktop` aggregator now requires all three to succeed — no `skipped`
tolerance, since none of them is disabled — and `ci-complete` gains the
two new lanes. The dead `Upload desktop e2e artifacts` step is dropped:
this lane has never run Playwright, so it had nothing to upload.

Desktop critical path drops from ~29 minutes to ~17, with no loss of
coverage.

Signed-off-by: Junchao Yan <[email protected]>
On its own lane the compiled-flag matrix took 33m40s on PR #118, longer
than the old combined Desktop Core lane it was split out of, so it was
still the desktop critical path. Turn it off the same way the smoke E2E
shards are turned off (if: false, original condition kept in a comment)
and let the Desktop aggregator accept its skipped result.

Desktop Core (~6m) and Desktop Tauri (~11m) stay on. Nothing else runs
`just desktop-tauri-test-compiled-flags`, so the lefthook comment now
says to run it by hand when touching a compiled flag.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: Junchao Yan <[email protected]>
Round-1 post-approval review found that forcing
`desktop-tauri-compiled-flags` to `false` leaves nothing in CI or the
pre-push hook compiling a `BUZZ_BUILD_*`-set build. The three flag
assertions are `#[ignore]`d, so `just desktop-tauri-test`'s
`cargo test --workspace` never reaches them, and the flag-sensitive
non-ignored tests only ever run in the default state.

The lane was disabled because it was slow. Reading the step log of the
one run it completed (33604032432, 19m56s cold) shows where the time
actually went, and it is not recompilation:

- 3 × the full 3141-test desktop lib suite: 193.8s + 193.1s + 189.4s,
  about 9m36s of the 20.
- 4 recompiles of the Tauri crate at roughly 1 minute each.

So the fix is to stop running the states in sequence, and to stop running
one of them at all:

- `just desktop-tauri-test-compiled-flags-state <state>` verifies one
  compile state. `probes` (both flag assertions in the clean state plus
  auto-connect set), `owner-only`, and `demo-slug`. The state list lives
  once, in the `compiled_flag_states` Justfile variable; the aggregate
  `desktop-tauri-test-compiled-flags` iterates it, so the local and manual
  entry point still runs everything.
- CI runs one job per state as a `fail-fast: false` matrix. The states
  compile and test concurrently rather than serially, so the lane's wall
  clock becomes its slowest single state, not their sum.
- The clean-state `cargo test --lib` is dropped. `just desktop-tauri-test`
  already runs that suite as `cargo test --workspace` with no flag set,
  and the flag-sensitive non-ignored tests resolve an absent expectation
  to exactly the value an explicit `false` gives them — see
  `expected_owner_only` in managed_agents/runtime/test_fixtures.rs and
  `current_build_deploy_payload_forwards_compiled_policy` in
  commands/agents_tests.rs. It was ~3m15s of duplicated test runtime.

The `desktop` aggregator goes back to requiring strict `success` from this
lane; a matrix job's result is `success` only when every shard passed.
Coverage is identical to the pre-disable recipe minus the duplicated run.

Signed-off-by: Junchao Yan <[email protected]>
The Justfile advertised `compiled_flag_states` as the single source of
truth for the compiled build states, but `ci.yml` repeated the three
literals and nothing compared them. Adding a fourth state would have made
the aggregate recipe run it locally while CI kept spawning only the
original three, with `Desktop` and `CI Complete` still green — a silent
coverage loss on a security-sensitive check.

The `changes` job now reads the list with
`just --evaluate compiled_flag_states`, converts it to JSON, and exposes
it as an output; `desktop-tauri-compiled-flags` builds its matrix from
that output. The workflow no longer names any state, so the Justfile
variable is genuinely the only place the set is written.

Fail-closed in both directions: an empty list is an explicit error rather
than a matrix with no shards, and a state name the recipe does not
recognise still hits the recipe's `*)` branch and fails its shard.

`changes` gets `timeout-minutes: 5` instead of 2. It now invokes `just`,
which Hermit downloads on first use in that job, and every other lane
depends on this one — a marginal timeout here would fail the whole run.

Signed-off-by: Junchao Yan <[email protected]>
The `rust` paths-filter group named lowercase `justfile`; the repository
file is `Justfile`. The pinned dorny/paths-filter builds its matcher with
`{dot: true}` and nothing else, and picomatch defaults `nocase` to false,
so the pattern matched nothing. Verified against the pinned versions:
`src/filter.ts` at ceb8a2b sets `MatchOptions = {dot: true}`, its
package.json pins picomatch ^2.3.1, and picomatch 2.3.1 with those options
returns false for `justfile` against `Justfile`.

The consequence is specific to the guarantee the previous commit added: a
pull request whose only change is `Justfile` — adding a state to
`compiled_flag_states`, exactly the maintenance path that list exists for
— set no filter output at all. The compiled-flags matrix was skipped by
its job condition, `Desktop` was skipped with it, and `CI Complete`
accepts skipped, so the new state could merge without its shard ever
running.

`scripts/test-path-filter-contract.sh` stops this recurring. It asserts
that every non-negated pattern in every filter group corresponds to
something in the repository: a pattern with no glob metacharacters must
name a tracked path exactly, and a glob must match at least one tracked
file. Globs are matched permissively, so only a pattern that corresponds
to nothing at all can fail. A case mismatch is reported as one, naming the
path the repository actually has.

The script self-tests before it checks anything, because a contract that
cannot fail is not a contract: it asserts that an absent literal path is
rejected, and that the lowercased form of a real mixed-case tracked file
is both rejected and reported as a case mismatch. Run against the filter
before this commit's one-line fix it reports:

    rust: 'justfile' - case mismatch: the repository has 'Justfile'

It runs in `changes` alongside the other contract steps, which is also
where the mis-cased pattern was read.

Note that Justfile-only pull requests now correctly trigger the rust
lanes, which they have not been doing. That is the entry's original
intent, not an expansion of it.

Signed-off-by: Junchao Yan <[email protected]>
@yjc801
yjc801 force-pushed the claude/desktop-core-timeout-41eaa2 branch from 6d1d836 to 1d86b6f Compare September 2, 2026 14:15
Owner decision on PR #118: the compiled-flag lane does not run on PRs.
Even sharded one job per state, each shard is a ~10 minute full rebuild
of the Tauri crate plus the desktop lib suite, and the owner chose to
drop it from the PR path entirely.

Turn it off the same way the smoke E2E shards are turned off (if: false,
original condition kept in a comment) and let the Desktop aggregator
accept its skipped result. The sharded recipe, the Justfile state list,
and the matrix generation in the changes job all stay so re-enabling is
a one-line change.

Nothing else compiles a BUZZ_BUILD_*-set build, so the lefthook comment
says to run `just desktop-tauri-test-compiled-flags` by hand when
touching a compiled flag.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: Junchao Yan <[email protected]>
@yjc801
yjc801 merged commit b468288 into main Sep 2, 2026
27 checks passed
@yjc801
yjc801 deleted the claude/desktop-core-timeout-41eaa2 branch September 2, 2026 15:08
yjc801 added a commit that referenced this pull request Oct 8, 2026
Resolve upstream block#8156 desktop CI split: take upstream's lanes, keep the
compiled-flags lane and smoke e2e disabled per PR #118 (gate expects smoke
skipped via SMOKE_SELECTED), drop the fork's now-unused compiled_flag_states
sharding, and take upstream's compiled-flags recipe.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Junchao Yan <[email protected]>
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.

1 participant