The Gate Dependency Graph
Layer 0 (Parallel - No Dependencies):
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Linting │ │ Type Checking │ │ Unit Tests │
└──────────────┘ └──────────────┘ └──────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ SAST Bandit │ │ SAST Semgrep │ │ SCA │
└──────────────┘ └──────────────┘ └──────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Allowlist │ │ Lockfile │ │ SBOM │
└──────────────┘ └──────────────┘ └──────────────┘
┌──────────────┐
│ AI Review │
└──────────────┘
Layer 1 (Depends on Unit Tests):
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Mutation │ │ PBT │ │ Coverage │
└──────────────┘ └──────────────┘ └──────────────┘
Layer 2 (Depends on All):
┌──────────────┐
│ Deployment │
└──────────────┘
Independent Gates (Layer 0)
These gates have no dependencies and run in parallel:
- Linting, Type Checking, SAST (Bandit), SAST (Semgrep), SCA, Allowlist, Lockfile, SBOM, AI Review
Dependent Gates (Layer 1)
These gates depend on Unit Tests:
- Mutation Testing (runs tests against mutants)
- Property-Based Testing (runs after tests pass)
- Coverage (measured during test execution)
Final Gate (Layer 2)
Deployment gate depends on ALL gates:
- Deployment (only runs if all other gates pass)
The 3-layer parallel execution model
Layer 0: 10 independent gates run in parallel. Total time = max(gate times) = ~60s (AI Review is the longest). Layer 1: 3 dependent gates run in parallel after Unit Tests pass. Total time = max(gate times) = ~300s (Mutation Testing is the longest). Layer 2: Deployment gate runs after all gates pass. Total time = ~10s. Total parallel time: 60 + 300 + 10 = 370s (~6 minutes). Sequential time: sum(all gate times) = ~1200s (~20 minutes). Speedup: 3.2x.
How does the 3-layer parallel execution model reduce CI time from 20 minutes to 6 minutes?
The 3-layer parallel execution model reduces CI time from 20 minutes to 6 minutes by running independent gates simultaneously instead of sequentially. Here's the math: Sequential execution: Each gate runs one at a time. Total time = sum of all gate times. Linting (15s) + Type Checking (30s) + Unit Tests (45s) + SAST Bandit (20s) + SAST Semgrep (25s) + SCA (15s) + Mutation Testing (300s) + PBT (180s) + Coverage (30s) + AI Review (60s) + Allowlist (5s) + Lockfile (20s) + SBOM (10s) = 755s. With tool installation overhead (10s per gate 13 gates = 130s), total = 885s (~15 minutes). Without caching, add another 250s = 1135s (~19 minutes). Parallel execution (3-layer model): Layer 0 (independent gates, run in parallel): Linting (15s), Type Checking (30s), Unit Tests (45s), SAST Bandit (20s), SAST Semgrep (25s), SCA (15s), Allowlist (5s), Lockfile (20s), SBOM (10s), AI Review (60s). Total Layer 0 time = max(all gate times) = 60s (AI Review is the longest). But wait -- Unit Tests is in Layer 0 because it has no dependencies. It runs in parallel with the other Layer 0 gates. Layer 1 (depends on Unit Tests, run in parallel after Unit Tests pass): Mutation Testing (300s), PBT (180s), Coverage (30s). Total Layer 1 time = max(300s, 180s, 30s) = 300s (Mutation Testing is the longest). But Layer 1 starts after Unit Tests completes (45s), so Layer 1 finishes at 45 + 300 = 345s. Layer 2 (depends on all gates): Deployment (10s). Starts after Layer 1 finishes. Total Layer 2 time = 10s. Total parallel time: Layer 0 finishes at 60s (max of all Layer 0 gates). Layer 1 starts at 45s (when Unit Tests finishes) and finishes at 45 + 300 = 345s. Layer 2 starts at max(60, 345) = 345s and finishes at 345 + 10 = 355s. Total: ~355s (~6 minutes). With caching: Subtract cache savings (pip: 10s 10 jobs = 100s, mutmut: 200s, mypy: 15s, semgrep: 10s, pip-audit: 5s = 330s). But caching savings are per-gate, not per-layer. In parallel execution, caching reduces each gate's time, which reduces the max per layer. With caching: Layer 0: max(5, 20, 35, 10, 15, 10, 5, 10, 5, 60) = 60s (AI Review doesn't benefit from caching). Layer 1: max(100, 130, 20) = 130s (Mutation Testing with mutmut cache: 300-200=100s, PBT: 180-50=130s, Coverage: 30-10=20s). Layer 2: 10s. Total with caching: 60 + 130 + 10 = 200s (~3.3 minutes). Speedup: Sequential without cache: ~19 minutes. Parallel with cache: ~3.3 minutes. Speedup: 5.8x. The key insight: parallel time = max(gate times) per layer, while sequential time = sum(gate times). With 10+ gates, this difference is dramatic. The bottleneck is Mutation Testing (300s / 100s with cache) -- it's the longest gate and determines Layer 1's total time. Optimizing Mutation Testing (e.g., running it on a subset of files, using parallel mutation testing) would further reduce CI time."