fix(ci): run the selection's Python suites when a file is unmapped - #6115
Conversation
An unmapped changed file sent test-bash to the full shell corpus and ran no Python suite, so every test_*.py the selector picked in that pull request went unrun, and the whole-tree runs (schedule, dispatch, a push with no base) never ran pytest at all. #6059 widened the unmapped set by dropping the Python import rule, so this now hits more pull requests than before. - The UNMAPPED branch keeps the full shell corpus and also runs this leg's slice of the selector's --unmapped-corpus listing that is not a shell suite: the selection's Python and Node suites, plus every Python suite when the unmapped file is a .py and every Node suite when it is Node. - The whole tree runs every Python suite, each leg every legs-th one. - Python suites run one pytest process each: suites in different directories import same-named helpers (from conftest import ...), so one process broke collection once suites from two such directories ran together. - Eval fixtures (*/evals/fixtures/*) are data the skill evals read and are not run; two of them error under pytest by design. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A whole-tree dispatch run (37141114979) ran the Python corpus on every leg for the first time: legs 0-2 passed in 7 to 7.5 minutes, and leg 3, which also runs the outside-Node packages and the Node sub-projects, was cancelled at the 11-minute limit in its Node steps after its Python share (the planning surface server suite alone took 202 s) had passed. 16 minutes is the ceiling for a job here. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
xargs -t prints every pytest command before it runs, so a leg's log names each Python suite it ran, not only pytest's count line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @kyle-sexton's task in 5m 57s —— View job Code review complete
SummaryReviewed the diff to I traced all three branches that now call the shared
No correctness bugs found in the diff; the control flow for all three branches is internally consistent and matches the PR description's claims about what each path now runs. No inline comments needed. Note on verification claims: the PR body's replay-script numbers, the linked CI run outcomes, and the local WSL verification steps are author-claimed; I did not independently re-run them and am not asserting them as verified here. |
|
Claude finished @kyle-sexton's task in 1m 14s —— View job Security review
Scope: only file changed is No security issues found. Reasoning:
|
|
claude-security-review has reviewed this pull request through c9fb3e2; a later push is reviewed from there. |
|
claude-review has reviewed this pull request through c9fb3e2; a later push is reviewed from there. |
No related issue: follow-up to #6059 (wave 3 PR 2 of the CI performance program); a verifier found its selected Python suites unrun on some pull requests. Refs #3932.
Summary
When a pull request changes a file the test selector cannot map,
test-bashfalls back to the full shell corpus, and that branch runs no Python suite. Everytest_*.pythe selector picked in such a pull request went unrun, and the whole-tree runs (schedule, dispatch, a push with no diff base) never ran pytest at all. #6059 dropped the Python import rule, which makes more.pyfiles unmapped, so its replay of 895 merged pull requests leaves 111 selected (PR, Python suite) pairs unrun over 19 PRs, against 85 over 14 with main's selector before it. This change makes both branches run them: 0 unrun.Fix
.github/workflows/ci.yml, step "Run plugin contract tests" oftest-bash:UNMAPPED:). Keeps the full shell corpus and the two outside-Node packages, then lists this leg's slice ofscripts/affected-tests.sh --unmapped-corpusand runs every suite in it that is not a shell suite, the way the exit-3 branch does:test_*.pyunder pytest, the rest throughscripts/run-outside-node-suites.sh --paths. The listing holds the selection's own Python and Node suites, plus every Python suite when the unmapped file is a.pyand every Node suite when it is Node, so an unmapped.pynow runs the Python corpus as perf(ci): select only the suites a change runs or reads #6059's body said the S9 fallback would. A listing that fails (any exit but 0 or 4) fails the step. A failing shell corpus no longer stops the step before the Python suites run; the step still fails.from conftest import ...), so one shared process fails collection once suites from two such directories run together (measured: running the corpus in one process per shard errors oncannot import name 'parsed_output' from 'conftest'). The exit-3 branch had the same latent fault.*/evals/fixtures/*holds data the skill evals read; two of itstest_*.pyfiles error under pytest by design. The Node side already excludes that directory throughscripts/outside-node-exclusions.txt.The
--unmapped-corpuswiring that replaces the whole-shell-corpus fallback with each language's own corpus stays with PR 3; this change keeps the shell corpus and adds what it misses.test-bashtimeout 11 -> 16 minutes. The first whole-tree run of this change (37141114979) passed on legs 0-2 in 7 to 7.5 minutes; leg 3, which also runs the outside-Node packages and the Node sub-projects, was cancelled at 11 minutes in its Node steps after its Python share had passed (plugins/planning/surface/test_server.pyalone took 202 s). 16 is the ceiling for a job here.xargs -tlogs each pytest command, so a leg's log names every Python suite it ran.Verification
Replay check: selected suites each CI branch leaves unrun
The verifier's replay of the 895 pull requests merged in the 7 days to 9671ece (main's selector at 9671ece, #6059's at 71ed6fc, and #6059's
--unmapped-corpuslisting on each PR with an unmapped file). For every PR, thetest-bashbranch its exit code takes, and each selected suite that branch runs nowhere. Node counts as run when it sits in a registered package, in a sub-project whose steps run, beside a wrapper that runs, or under the exclusion list.ci.ymlbeforeci.ymlbeforeci.ymlOf the 8 PRs where main's CI ran Python suites and #6059's ran none because a file was unmapped (#5907 dfd7938, #5925 cb30935, b3bb5f3, 0b48d8f, a501f14, 28ed10f, 030bb3d, c94a299), 7 run Python suites again; c94a299's one suite (
test_save_point.py) was selected on main through a mention #6059's rules reject, so nothing selects it to run. The whole tree now runs all 139 Python suites, and every Node suite in the tree is owned (6 in packages, 98 in sub-projects, 16 with a wrapper, 6 excluded).CI
test-bashlegs 8:03, 6:03, 6:57, 9:23. Thexargs -tlines show each of the 139 Python suites (everytest_*.pyoutside*/evals/fixtures/*) ran exactly once across the four legs..py, probe test(ci): probe an unmapped Python file through the fallback #6116 (closed unmerged): one comment added toplugins/harness-ops/lib/plugin_cache_versions.py, which the selector reports UNMAPPED. Run 37141969828 at 0f244c3 (c9fb3e2 plus the probe commit): all fourtest-bashlegs green (6:57 to 9:49), each warning the fallback, running its shell-corpus share and then its slice of the Python corpus; the 139 Python suites ran exactly once between them.check-pluginsfailed there as expected (an unbumped plugin edit to a shared copy).test-bashlegs 5:28 to 10:55, the longest 5 s under the former 11-minute limit.Local (WSL Ubuntu 26.04, Python 3.14.7 with both CI requirement files)
run:block extracted from thisci.ymland run in a scratch clone, withrun-plugin-tests.shandrun-outside-node-suites.shstubbed to record their arguments:plugins/code-metrics/scripts/report.pychanged): exit 0, the 7 selected Python suites each in its own pytest;.markdownlint-cli2.jsonc: exit 0, shell corpus and the Node packages, no Python suite (none selected);plugin_cache_versions.py: exit 0, 147 listed, 139 run, the 8 eval fixtures skipped;cannot import name 'parsed_output' from 'conftest'.plugins/testing/skills/audit/evals/fixtures/{negative,positive}/test_*.pyerror at collection.actionlint,scripts/check-docs-only-gate.sh --check,scripts/check-lane-coverage.sh --check,zizmor --offline: clean.scripts/selection-audit.sh'sfallback_corpusstill findsrun-plugin-tests.shin the UNMAPPED block.Related
--unmapped-corpusin place of the whole-shell-corpus fallback, pins routed to their lanes,--with-alwaysdropped. With that,scripts/selection-audit.sh'sfallback_corpusshould model the per-language fallback: today it counts only the shell corpus, so it reports a Python suite reading an unmapped.pyas a gap although this branch now runs it.🤖 Generated with Claude Code