acc-estimate-pipeline-time
Pipeline Time Estimator
Estimates pipeline execution time and identifies optimization opportunities.
Pipeline Analysis
Execution Flow Visualization
┌─────────────────────────────────────────────────────────────────┐
│ PIPELINE EXECUTION FLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Time 0 2 4 6 8 10 12 14 16 18 20 │
│ │ │ │ │ │ │ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ │
│ │
│ install ████████ │
│ │ │
│ ├──▶ phpstan ████████ │
│ │ │
│ ├──▶ psalm ██████████ │
│ │ │
│ ├──▶ cs-fixer ██████ │
│ │ │
│ └──▶ deptrac ████ │
│ │ │
│ └──▶ test-unit ████████████████ │
│ │ │
│ └──▶ build ████│
│ │
│ Critical Path: install → psalm → test-unit → build = 20 min │
│ │
└─────────────────────────────────────────────────────────────────┘
Time Estimation Model
Job Time Components
Job Time = Setup Time + Execution Time + Teardown Time
Where:
- Setup Time = Runner startup + Checkout + Cache restore
- Execution Time = Actual command execution
- Teardown Time = Artifact upload + Cache save + Cleanup
Typical Job Times (PHP Project)
| Job | Cold (no cache) | Warm (cached) | Components |
|---|---|---|---|
| checkout | 10s | 10s | git clone |
| composer install | 180s | 30s | Download + autoload |
| phpstan | 120s | 120s | Analysis |
| psalm | 180s | 180s | Analysis + taint |
| cs-fixer | 60s | 60s | Style check |
| deptrac | 30s | 30s | Architecture |
| phpunit (unit) | 120s | 120s | Tests |
| phpunit (integration) | 300s | 300s | Tests + DB |
| docker build | 600s | 120s | Build + push |
Critical Path Analysis
# Pseudo-algorithm for critical path
def find_critical_path(jobs):
# Build dependency graph
graph = build_dependency_graph(jobs)
# Calculate earliest start time for each job
for job in topological_sort(graph):
job.earliest_start = max(
dep.earliest_finish for dep in job.dependencies
) if job.dependencies else 0
job.earliest_finish = job.earliest_start + job.duration
# Total pipeline time = max(earliest_finish)
total_time = max(job.earliest_finish for job in jobs)
# Critical path = jobs where slack = 0
critical_path = [job for job in jobs if job.slack == 0]
return critical_path, total_time
Optimization Strategies
1. Parallelize Independent Jobs
# BEFORE: Sequential (20 min)
# install → phpstan → psalm → cs-fixer → deptrac → test → build
# AFTER: Parallel lint (12 min)
# install ─┬─► phpstan ─────┐
# ├─► psalm ───────┼─► test → build
# ├─► cs-fixer ────┤
# └─► deptrac ─────┘
# Savings: 8 minutes (40%)
2. Split Long Jobs
# BEFORE: Single test job (10 min)
test:
script: vendor/bin/phpunit
# AFTER: Parallel test suites (4 min)
test-unit:
script: vendor/bin/phpunit --testsuite=unit
test-integration:
script: vendor/bin/phpunit --testsuite=integration
test-e2e:
script: vendor/bin/phpunit --testsuite=e2e
# Savings: 6 minutes (60%)
3. Optimize Cache Usage
# BEFORE: No caching (composer install: 3 min)
- run: composer install
# AFTER: With caching (composer install: 30 sec)
- uses: actions/cache@v4
with:
path: |
~/.composer/cache
vendor
key: composer-${{ hashFiles('composer.lock') }}
- run: composer install
# Savings: 2.5 minutes per job
4. Use Smaller Images
# BEFORE: Full PHP image (pull: 45 sec)
image: php:8.4-cli
# AFTER: Alpine image (pull: 15 sec)
image: php:8.4-cli-alpine
# Savings: 30 seconds per job
5. Matrix Optimization
# BEFORE: Matrix of 9 combinations, all run
strategy:
matrix:
php: ['8.2', '8.3', '8.4']
deps: ['lowest', 'locked', 'highest']
# AFTER: Strategic subset (3 combinations)
strategy:
matrix:
include:
- php: '8.2'
deps: 'lowest' # Min requirements
- php: '8.4'
deps: 'locked' # Primary target
- php: '8.4'
deps: 'highest' # Future compat
# Savings: 66% reduction in matrix jobs
Analysis Output Format
# Pipeline Time Analysis
**Pipeline:** CI
**Current Duration:** 25 min 30 sec
**Optimized Estimate:** 10 min 15 sec
**Potential Savings:** 15 min 15 sec (60%)
## Current Execution Timeline
Job Start Duration End Status ────────────────────────────────────────────────────────── install 0:00 3:00 3:00 ✓ phpstan 3:00 2:00 5:00 ✓ (waits 3:00) psalm 5:00 3:00 8:00 ✓ (waits 5:00) cs-fixer 8:00 1:00 9:00 ✓ (waits 8:00) deptrac 9:00 0:30 9:30 ✓ (waits 9:00) test-unit 9:30 6:00 15:30 ✓ (waits 9:30) test-integration 15:30 8:00 23:30 ✓ (waits 15:30) build 23:30 2:00 25:30 ✓ (waits 23:30)
## Critical Path
install (3:00) → psalm (3:00) → test-unit (6:00) → test-integration (8:00) → build (2:00) Total: 22:00 (critical path determines minimum possible time)
## Bottleneck Analysis
| Job | Duration | Wait Time | Utilization | Bottleneck? |
|-----|----------|-----------|-------------|-------------|
| install | 3:00 | 0:00 | 100% | No |
| phpstan | 2:00 | 3:00 | 40% | **Wait** |
| psalm | 3:00 | 5:00 | 37% | **Wait** |
| cs-fixer | 1:00 | 8:00 | 11% | **Wait** |
| test-integration | 8:00 | 15:30 | 34% | **Duration** |
## Optimization Recommendations
### 1. Parallelize Lint Jobs
**Impact:** -6:30 (25%)
```yaml
# Current: Sequential
# Proposed: All lint jobs run in parallel after install
2. Split Integration Tests
Impact: -4:00 (16%)
# Current: Single 8-minute job
# Proposed: Split into 3 parallel jobs of ~3 min each
3. Add Caching
Impact: -2:30 (10%)
# Current: Cold composer install (3:00)
# Proposed: Cached install (0:30)
4. Move Build Earlier
Impact: -0:30 (2%)
# Build can start after unit tests, doesn't need integration
Optimized Pipeline
Time 0 2 4 6 8 10
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
install (0:30) ─┬─► phpstan (2:00) ──────────┐
├─► psalm (3:00) ────────────┼─► test-unit (4:00) ─┬─► build (2:00)
├─► cs-fixer (1:00) ─────────┤ │
└─► deptrac (0:30) ──────────┘ │
│
test-int-1 (3:00) ───────────────────┤
test-int-2 (3:00) ───────────────────┤
test-int-3 (3:00) ───────────────────┘
Total: 10:15 (was 25:30)
Summary
| Metric | Before | After | Change |
|---|---|---|---|
| Total Duration | 25:30 | 10:15 | -60% |
| Critical Path | 22:00 | 10:15 | -53% |
| Parallelism | 12% | 68% | +56% |
| Wait Time | 41:30 | 8:00 | -81% |
## Estimation Formulas
### Total Pipeline Time
T_total = max(T_critical_path, T_resource_constrained)
Where: T_critical_path = sum of job times on longest dependency chain T_resource_constrained = total_job_time / max_parallel_runners
### Cache Benefit
T_cached = T_uncached * cache_hit_rate * cache_speedup + T_uncached * (1 - cache_hit_rate)
Example:
- Uncached composer: 180s
- Cache hit rate: 90%
- Cache speedup: 85% T_cached = 180 * 0.90 * 0.15 + 180 * 0.10 = 24.3 + 18 = 42s
## Usage
Provide:
- CI configuration file
- Historical run data (optional)
- Runner constraints (optional)
The estimator will:
1. Parse job dependencies
2. Estimate job durations
3. Calculate critical path
4. Identify bottlenecks
5. Suggest optimizations
6. Estimate savings
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12