CI Changed-Files Selective Pipelines
Problem
Every PR currently runs the full build/test/typecheck suite across all ~15 packages. Most PRs touch 1-3 packages. This wastes CI minutes, slows feedback loops, and creates noise when unrelated packages fail.
Goals
- PR CI runs only affected packages plus their downstream dependents.
- Nightly CI runs the full suite as a safety net.
- Dependency closure is computed from the workspace graph, not hardcoded.
Non-goals
- Caching build artifacts across runs (separate optimization).
- Parallelizing individual package test suites.
Proposed approach
Dependency graph script (scripts/ci-affected.ts): Parse each
packages/*/package.json for dependencies and devDependencies
referencing workspace packages. Build an adjacency list. Given a set
of changed paths, resolve to package names, then walk forward edges
to collect the full closure. Output a JSON array of affected package
directories.
Changed-file detection: Use git diff --name-only origin/main...HEAD
in CI. Map each changed path to its owning package via directory prefix
(packages/<name>/). Root-level changes (package.json, bunfig.toml,
tsconfig) trigger full suite as a safeguard.
GitHub Actions matrix: The PR workflow calls the affected script, then feeds the output into a dynamic matrix for build, test, and typecheck jobs. Empty matrix (no affected packages) skips those jobs.
Nightly full run: A separate scheduled workflow runs all packages unconditionally on a cron schedule.
Phases
Phase 1 — Affected-packages script and PR workflow
- Implement
scripts/ci-affected.tswith workspace graph resolution. - Add unit tests for graph closure (diamond dependencies, root changes).
- Update
.github/workflows/pr.ymlto use dynamic matrix from script output. - Keep existing full-suite workflow as nightly cron.
Phase 2 — Validation and tuning
- Run both selective and full suite in parallel for 2 weeks to verify the selective pipeline never misses a real failure.
- Add a CI step that logs skipped packages for auditability.
- Remove parallel full-suite run once confidence is established.
Validation criteria
- PR touching only
packages/cli/does not run daemon or core tests. - PR touching
packages/core/runs core + all downstream packages. - Root-level changes trigger full suite.
- Nightly cron runs all packages regardless of recent changes.
Open decisions
- Should
docs/orweb/changes skip all package CI entirely, or run a minimal lint-only pass? - Should the affected script live in
scripts/or be an inline composite action in.github/?