Repository navigation
CI: on pull requests run the overlay's and related tests, whole suite for upstream code; balance shards (DEV-6649) - #25
Merged
Conversation
The runbook test only checked that the runbook and LAZURIO.md contain certain words, and two CI assertions only pinned that the workflow says `pnpm typecheck` and `vitest run --shard=`. None of them proves a release behaviour, and the CI pin would block running the suite differently. The read-only permissions, the upstream pin agreeing with the archive version, the upstream-workflow gate and the allowlist checks stay. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… shards Every pull request ran upstream's whole vitest suite (about 900 files, 45 minutes serially, four shards, about 16 minutes to green) although the overlay's own tests take seconds. A pull request now runs the overlay's own tests and what `vitest related` relates to its diff, still in four shards. Pushes to main, manual runs (the check of a rebuild) and pull requests that change CI or the upstream pin, the test runner, dependencies or shared test helpers run the whole suite; so does a pull request whose base is off the pinned upstream or whose diff cannot be read. The shards now split by measured duration (lazurio/vitest.config.mjs on top of the unchanged upstream config) instead of vitest's path hash, which put three of the slowest files into one 14-minute shard. fileParallelism stays off. The overlay job, the required check, chooses the files and runs the new selection tests next to the release contract. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
No test imports server/index.ts: about a hundred upstream end-to-end tests start it as a child process, and the UI tests load the app, index.html included, through a Vite dev server. vitest related therefore selected no upstream test for a change to server/index.ts, and only unit tests for a change to a component. A pull request that changes an upstream file other than Markdown and tests now runs the whole suite. Pull requests that change only Lazurio files, documentation or tests keep the overlay's tests plus vitest related. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The first durations came from one older run of main, in which several files ran slower than they do now (direct-coordination 186 s, now 142 s), so one shard finished about three minutes before the others in both runs of this pull request. The list now holds the mean of those two runs, and an unlisted file weighs their 0.7 s average; on the same measurements the shards come out at 697 to 734 s instead of 587 to 765 s. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
immakermatty
marked this pull request as ready for review
October 6, 2026 14:59
agentrozjedemeai
approved these changes
Oct 6, 2026
agentrozjedemeai
left a comment
Collaborator
There was a problem hiding this comment.
Exact-head QA at 1901846 (DEV-6649): APPROVED. I reviewed the PR diff, scope fallback and duration sequencer, and replayed scope selection on this base/head (full suite as CI changed). The isolated checkout passed all 14 Node contract/selection tests; diff check was clean. The six required checks on this head are green; the comment-only PR #26 exercised the related path successfully. Known limit remains: import-graph selection may miss external file reads/child-process loads of overlay code; overlay e2e runs on PRs and main runs the full suite.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Every pull request ran upstream's whole vitest suite: about 900 test files, 45 minutes of serial tests (
fileParallelism: false), four shards. The last pull request run before this change (PR #22, run 37213822983) took 18.6 min to green and 58 billed minutes; its slowest shard took 17.5 min, because vitest's path-hash split putdelta-context.e2e(242 s),direct-coordination.e2e(185 s) andgroup-local-vm.e2e(113 s) into one shard. The overlay's own tests take about 20 s.Target (plan DEV-6649, M6): a typical pull request is green in about 3 minutes;
mainstill runs the whole suite after every merge.What changes
Pull requests that change only Lazurio files, documentation or tests run what the change can affect. The overlay job (the required check
Overlay, typecheck and lint, name unchanged) runsscripts/lazurio-ci-scope.mjs. It hands the four vitest shards the overlay's own tests (every test file the overlay adds or changes againstUPSTREAM_SHA) plus the files the pull request changes (merge-base diff, renames off), and the shards runvitest relatedon them: vitest's own import graph picks the changed test files and every test that imports a changed file.The whole suite runs on pushes to
main, on manual runs (the dispatched check of a rebuild on a new upstream tag), and on a pull request that changes:UPSTREAM_SHAother than Markdown and test files. Measured reason: no test importsserver/index.ts(vitest related server/index.tsselects 0 files) because about a hundred upstream end-to-end tests start it as a child process, and the UI end-to-end tests load the app,index.htmlincluded, through a Vite dev server. Import-graph selection would silently skip them;.github/(CI, the upstream pinUPSTREAM_TAG/UPSTREAM_SHA, the allowlist), the selection script or the shard config, anypackage.json, the lockfile or workspace file, any vite/vitest config, atsconfig, or shared test helpers and fixtures (testing/,test/,__mocks__/,*fixtures/, which includes the vitest setup file).It also runs when the pull request's merge base does not stand on the pinned upstream commit, and whenever the selection fails (missing base, invalid SHAs, unreadable diff, odd path). It fails closed, with a warning in the log. In a shard, a
relatedscope with an empty or unreadable list fails the job instead of running nothing.Shards balanced by measured duration.
lazurio/vitest.config.mjstakes upstream'svite.config.tsunchanged and adds a vitest sequencer (sequence.sequencer, vitest's standard extension point). Itsshard()places files longest-first onto the least-loaded shard, deterministically. Durations:lazurio/vitest-durations.json, the 95 files that took 5 s or more on average in runs 37476583884 and 37478790478; every other file weighs 0.7 s. A listed file that no longer exists fails the run (rename or drop the entry; the overlay job's node test checks it too).fileParallelism: falsestays.Broker and Electron unit tests still run in shard 1 in both modes (about 30 s).
Runbook (
docs/operations/lazurio-fork-release.md, "Testing before a release") describes the selection, its limit and how to see what a pull request runs (UPSTREAM_SHA=<pin> node scripts/lazurio-ci-scope.mjs <base> <head>).What does not change
Release contract,
UPSTREAM_TAG/UPSTREAM_SHA, tags,mainhistory, the overlay guard and its allowlist,lazurio-release.yml,lazurio-archive.yml, the required check name and the vitest job names,fileParallelism. No upstream file changes, so there is no new allowlist entry.mainruns exactly what it ran before (the whole suite, broker and Electron tests, archive), only split differently across the four shards.Deleted tests
All in the Lazurio-owned
scripts/lazurio-release-contract.node-test.mjs. Upstream tests are not touched; the overlay may not change them.scripts/lazurio-release-contract.node-test.mjsthe runbook and fork contract name the operative factsLAZURIO.mdcontain certain words (documentation wording).scripts/lazurio-release-contract.node-test.mjsCI is read-only and pins the exact upstream base: thepnpm typecheckandvitest run --shard=assertionsKept on purpose: the upstream-workflow gate assertion (it guards a publishing boundary), the allowlist checks, and the shell-slot checks (the only rebuild guard of the slot).
Verification
CI on this pull request (it changes CI, so every run is the whole suite):
On the first two runs one shard finished about three minutes early: the first durations came from an older run in which several files were slower (
direct-coordination.e2e186 s, now 142 s). Re-measuring on those two runs narrowed the vitest time per shard from 587–765 s to 717–813 s. The whole run on this head was about 6 % slower (3 028 s of tests against 2 850 s), which is runner variance. A whole-suite run costs as many minutes as before and is about 3–4 minutes faster.The related path in CI: throwaway PR #26, stacked on this branch, changed only a comment in the Lazurio module
server/github-intake.ts. Run 37479124169 was green in 2.3 min, 8 billed minutes (overlay 1.2 min, archive 1.4 min, shards 0.7–1.0 min). It selected the 12 overlay test files (3/1/4/4 per shard), and shard 1 also ran broker + Electron. PR #26 is closed and its branch deleted.Replay of real history (
UPSTREAM_SHA=<pin of that head> node scripts/lazurio-ci-scope.mjs <base> <head>; the selected files come from vitest's graph on the current tree):main: 16 related (2–12 test files, 3–21 s), 9 whole suite for workflow changes and 3 for upstream code (scripts/control-omb.tstwice,server/browser-engine.ts). Under purevitest related, those 3 would have selected 46–49 % of the suite while still missing the server's child-process tests.Locally (macOS, Node 26, pnpm 10.33.0):
node --test scripts/lazurio-release-contract.node-test.mjs scripts/lazurio-ci-scope.node-test.mjs14/14 pass;pnpm lintandpnpm typecheckclean;pnpm broker:testandpnpm test:electronpass;vitest related --run --config lazurio/vitest.config.mjs --shard=N/4on a docs-only diff ran the 12 overlay tests, 4–12 s per shard. The duration split over the real 922 test files puts each file in exactly one shard (checked through the vitest Node API). I did not run the whole vitest suite on macOS; the three CI runs above ran it on Linux.Risks and follow-ups
mainruns everything after each merge; repair forward (plan risk note).allowed_upstream_changesruns the whole suite, because the allowlist lives in the workflow file. Moving it into its own file would let such pull requests run selectively, but that touches the release contract, so I left it as a possible follow-up.lazurio/vitest-durations.jsondrifts as the suite changes. Drift only unbalances shards; a rebuild that renames a listed file fails until the entry is updated (described in the runbook and the config).Refs #24
🤖 Generated with Claude Code
Note
Run scope-aware Vitest on pull requests and balance shards by test duration
scripts/lazurio-ci-scope.mjs, which resolves pull-request scope from the Git diff against the pinned upstream commit and publishes afullorrelatedVitest scope plus a related-file list to GitHub Actions outputs. Local runs can print the same decision from explicit base and head commits.lazurio/vitest.config.mjsusing measured weights fromlazurio/vitest-durations.json, replacing Vitest's default path-based shard assignment.readDurationsnow throws when a duration inlazurio/vitest-durations.jsonis invalid or a listed test file no longer exists; the runbook requires updating the duration list when a listed test is renamed or removed.Macroscope summarized 1901846.