DiffCI

Implementation guide

How to run only affected tests safely

Affected-test selection can shorten feedback and reduce compute, but only when missing dependency evidence causes a full run—not a smaller, unjustified selection.

Three common selection strategies

Changed paths

Path filters map directories or file patterns to commands. They are transparent, cheap, and often the best first baseline. They become difficult to maintain when shared packages, generated code, configuration, or cross-package imports make the mapping many-to-many.

Task or package graphs

Monorepo tools can calculate affected projects from their declared task graph. This is efficient when the repository already encodes project boundaries and task dependencies. The graph is only as complete as that configuration.

Source dependency graphs

A source analyzer follows imports from changed files toward tests. It can distinguish changes inside the same package more precisely, but resolution rules, dynamic imports, framework transforms, and unsupported languages create explicit boundaries.

The safest evaluation compares all three where possible: the existing full command, a simple path baseline, and the more precise selection.

Define full-suite triggers first

Fallback policy is part of the selector, not an error handler added later. Name the changes that invalidate narrow selection before measuring savings.

  • Dependency manifests and lockfiles: resolved packages can change across the repository.
  • Workflow and runner configuration: execution behavior can change without a source import.
  • Root compiler or test configuration: transforms, aliases, environments, and discovery rules can change globally.
  • Unsupported or unresolved imports: an incomplete graph cannot establish a complete affected set.
  • Missing Git history: shallow checkouts may not contain the comparison base.

Maintain an explicit always-run list for security checks, policy tests, configuration validation, and other repository-specific guardrails.

Preserve execution prerequisites

A selected test command may still need installation, code generation, build output, services, environment variables, or artifacts. A command that passes only because a developer's checkout already contains generated state is not a reproducible CI selection.

Record the command plan as well as test files. If prerequisites cannot be represented, label the selection advisory or run the full path.

Verify safety and economics separately

Safety asks whether the selected path detects the failures it should. Economics asks whether analysis plus selected execution is cheaper than the baseline. A selector can be safe and still save nothing.

  1. Replay known changes

    Include ordinary green changes and changes with known relevant failures.

  2. Execute the proposed command

    Do not infer success from selection counts or command construction alone.

  3. Confirm the selection was honored

    Test-runner output must match the intended set; otherwise withhold the timing.

  4. Compare job-equivalent cost

    Include analysis, installation, setup, and test startup where the adoption decision includes them.

Try an observation before changing CI

npx "@diffci.com/diffci@latest" observe --no-send

This produces affected-test and fallback evidence without running tests. Use check when paired full and selected execution is permitted:

npx "@diffci.com/diffci@latest" check

Neither command changes which tests required CI runs. Continue with the GitHub Actions guide or compare selection strategies.