Diffr is a high-performance Test Impact Analysis CLI and minimal developer dashboard for Go repositories. Given two git references (e.g. HEAD~1 and HEAD), Diffr calculates the syntactic diff, walks the Go AST to build a function-level reverse call graph, resolves the minimal set of impacted tests transitively using BFS, executes only those tests, and records time-saved metrics into MongoDB with sub-millisecond Redis caching.
In modern continuous integration (CI) pipelines, re-running an entire test suite on every single-line commit wastes compute, delays developer feedback loops, and inflates cloud infrastructure costs. Diffr solves this by implementing an intelligent Test Impact Analysis engine for Go: it parses syntactic diffs, traces caller-callee hierarchies through reverse call graphs, prunes non-impacted tests with high fidelity, and maintains low-overhead caching and telemetry across pipeline runs.
┌─────────────────────┐
│ Developer / CI │
│ (diffr CLI) │
└──────────┬──────────┘
│
┌───────────────┼────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ Diff Engine │ │ AST / Call │ │ Test Runner │
│ (git diff) │ │ Graph Engine │ │ (go test) │
└──────┬──────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└───────┬───────┘ │
▼ │
┌──────────────────┐ │
│ Impact Resolver │◄──────────────┘
│ (changed → test) │
└────────┬─────────┘
│
┌────────┴─────────┐
▼ ▼
┌───────────┐ ┌──────────────┐
│ Redis │ │ MongoDB │
│ (cache) │ │ (telemetry) │
└───────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│Dashboard API │
│(net/http Go) │
└──────┬───────┘
▼
┌──────────────┐
│ Static Web UI│
│ (HTML/JS/CSS)│
└──────────────┘
- Diff Engine (
internal/diffengine): Shells out togit diff -U0, parses hunk headers, and extracts modified line ranges per Go file. - AST / Call Graph Engine (
internal/astgraph): Walks the repository withgo/parser, maps line ranges to enclosing top-levelFuncDeclnodes, and constructs an adjacency call graph and reverse graph (callee -> callers). - Impact Resolver (
internal/resolver): Performs BFS traversal over the reverse call graph from changed functions to locate directly and transitively impactedTest*functions, handling_test.goedits directly. - Cache Layer (
internal/cache): Keyed bydiffr:{repoHash}:{ref1}:{ref2}in Redis with a 24-hour TTL; bypasses AST parsing on repeated runs. - Test Runner (
internal/runner): Compiles target test functions into a targeted-run '^(TestA|TestB)$'regex and invokes scopedgo testwith wall-clock timing. - Storage Layer (
internal/store): Logs run records to MongoDB collectionrunswith compound indexes on{repo_path: 1, ref1: 1, ref2: 1}and{timestamp: -1}, equipped with automatic resilient local file fallback (.diffr/runs.json). - Dashboard & API (
internal/api&web/): Clean developer-tool dashboard (monochrome, monospace data, SVG/Canvas cumulative savings chart, zebra-striped run table) served via Go stdlibnet/http.
To start Redis, MongoDB, and the Diffr container together:
docker-compose up -dOr build and run natively with Go:
go build -o diffr ./cmd/diffr./diffr diff HEAD~1 HEADOutput: Lists changed files, enclosing functions, and impacted tests.
./diffr run HEAD~1 HEADOutput: Calibrates baseline test suite duration, executes only the impacted tests, reports milliseconds and % time saved, and persists metrics to MongoDB.
Run the identical command again:
./diffr run HEAD~1 HEADOutput: Reports CACHE HIT with near-zero analysis latency.
./diffr statsOutput: Queries MongoDB and prints cumulative test time saved.
./diffr serve --addr :8080Open http://localhost:8080 to inspect real-time cumulative compute savings, run history, and cache statuses:
Production Kubernetes manifests are included in /deploy/k8s/:
api-deployment.yaml: Dual-replica Deployment and ClusterIP Service for the web dashboard and REST API.ci-job.yaml: Parameterized KubernetesJobtemplate designed to execute within cloud-native CI pipelines (e.g. Argo Workflows, Tekton, or cloud runner pods) utilizing external managed services (GCP Memorystore for Redis and MongoDB Atlas via VPC peering).
(Note: Designed deployment target, not exercised in local environments).
- Syntactic Call Graph: Constructs call graphs via AST inspection without full type-checked interface resolution or reflection dispatch.
- Function-Level Granularity: Tracks mutations at function/method boundaries rather than statement-level delta slices.
- Single Language: Focused on Go repositories in v1.
- Flaky-Test Isolation: Does not currently track historical test flakiness.
- Incremental Graph Persistence: Rather than re-parsing the entire AST per run, maintain an incremental dependency graph stored in an in-memory graph database, updating only modified nodes per git commit.
- Semantic Cache Invalidation: Invalidate cache keys using commit tree hashes and dependency closure hashes rather than simple time-to-live expiration.
- Failure-Risk Test Prioritization: Combine static call graph distance with historical defect density to prioritize the execution order of impacted tests within large test suites.
