Skip to content

feat(ci): changed-based test selection gates every behavior lane - #14

Merged
pruge merged 1 commit into
mainfrom
fm/ci-changed-selection
Aug 25, 2026
Merged

feat(ci): changed-based test selection gates every behavior lane#14
pruge merged 1 commit into
mainfrom
fm/ci-changed-selection

Conversation

@pruge

@pruge pruge commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Summary

Every behavior lane now runs only what a PR actually changed. Each lane first intersects the PR's merge-base diff with its own composition through bin/fm-test-run.sh's conservative path->family map (single owner, extended in place - no mapping duplicated into the workflow). A lane whose diff maps to none of its tests prints skipped: no affected tests and reports success in seconds instead of silently cancelling, so the check still reports.

fm-test-run.sh

  • --changed now composes with --lane <name> / --family <name> as intersection filters (either flag order); standalone modes keep refusing combinations.
  • An empty final --changed selection prints skipped: no affected tests on stdout, emits the empty FM_TEST_SUMMARY, and exits 0.
  • Colocated contract tests cover watcher-change intersections (parallel lanes skip, serial keeps watcher families), family filters, flag-order equivalence, the skip marker, and the refusal contract.

ci.yml

  • Each behavior job gains a fast "Detect affected tests" step: on PRs it computes git merge-base of the PR base SHA and runs fm-test-run.sh --list --changed --base <merge-base> --lane/--family <lane>. On pushes to main it selects everything (approved merges run full lanes).
  • Gated jobs: portable-parallel-1/2, all six portable-serial shards (flake retry logic unchanged, both attempts use the changed intersection), real-Herdr lane (all Herdr setup skipped when nothing is affected; cleanup gated so it never runs without its session), macOS snapshot lane (snapshot-bearings family OR any changed bin/**/*.sh, since the stock-Bash parse sweep covers every tracked shell script).
  • Docs-only fast path, "Test coverage guard", "Repo invariants", timing artifacts, and shard-partition proof are unchanged.

Verification

  • bin/fm-lint.sh green (pinned ShellCheck 0.11.0 + actionlint 1.7.12).
  • bash tests/fm-test-run.test.sh 19/19 ok.
  • bin/fm-test-run.sh --check-coverage ok (total=165, partition proof intact).
  • Local dry run of this PR's own selection: parallel-1 runs only its 9 pure-contract-unit scripts, herdr lane selection resolves via the ci.yml mapping.

Each behavior lane now intersects the PR diff with its own composition
through bin/fm-test-run.sh's conservative path->family map instead of
always running its full inventory. A lane whose merge-base diff maps to
none of its tests prints 'skipped: no affected tests' and reports
success in seconds; docs-only PRs keep the existing fast path, pushes to
main still run complete lanes, and the flake retry plus shard-partition
proof contracts are unchanged.

fm-test-run.sh gains --changed combined with --lane/--family intersection
filters (either flag order), an explicit empty-selection stdout marker,
and colocated contract tests for both.
@pruge
pruge merged commit 2df4f28 into main Aug 25, 2026
16 of 17 checks passed
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