PipeChecker
Catch CI/CD pipeline errors before you push β not after CI fails.
What Problem Does This Solve?
Every developer has been here:
π You push a small change β CI fails 10 minutes later β
you fix it β push again β CI fails again β repeat 3 more times
PipeChecker runs locally and validates your CI/CD workflows before you commit, so you catch:
| Catches | Example |
|---|---|
| β Circular dependencies | Job A β Job B β Job A |
| β Missing job references | needs: [build] but no build job exists |
| β Empty pipelines | No jobs or steps defined |
| β οΈ Hardcoded secrets | API_KEY=sk_live_abc123 in env vars |
| β οΈ Undeclared env vars | ${{ env.UNKNOWN }} never defined |
| β οΈ Unpinned actions | uses: actions/checkout without @v4 |
β οΈ Docker :latest tags |
image: nginx:latest (unreproducible builds) |
| β οΈ Missing job timeouts | No timeout-minutes set β jobs can run forever |
Visual Overview
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR WORKFLOW FILE β
β (.github/workflows/ci.yml) β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β PIPECHECKER β
β β
β ββββββββββββββββββ β
β β YAML Parser β β
β β GitHub/GitLab β β
β β CircleCI β β
β βββββββββ¬βββββββββ β
β β β
β βββββββββΌβββββββββ β
β β Auditors β β
β β β β
β β π Syntax β β
β β π DAG/Cycle β β
β β π Secrets β β
β β π³ Docker β β
β β π Pinning β β
β βββββββββ¬βββββββββ β
β β β
ββββββββββββΌββββββββββββ
β
ββββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
β
PASS β οΈ WARNINGS β ERRORS
No issues Fix before Must fix
found! production before push
Documentation
Comprehensive documentation can be found in the docs/ folder:
Supported Platforms
| Platform | File Pattern | Status |
|---|---|---|
| GitHub Actions | .github/workflows/*.yml |
β Full support |
| GitLab CI | .gitlab-ci.yml |
β Full support |
| CircleCI | .circleci/config.yml |
β Full support |
Installation
From crates.io
From source
Via npm (once published)
Quick Start
1. Check a single file
2. Auto-detect your workflow
# β Auto-detected: .github/workflows/ci.yml
# Provider: GitHubActions
# 0 errors, 0 warnings
3. Audit everything
# Checking 3 workflow file(s)...
#
# π .github/workflows/ci.yml
# Provider: GitHubActions
# β
No issues found
#
# π .github/workflows/deploy.yml
# Provider: GitHubActions
# 1 errors, 2 warnings
# β ERROR: Circular dependency detected (job: deploy)
# π‘ Remove one of the dependencies to break the cycle
# β οΈ WARNING: Job 'deploy' has no steps
#
# ββββββββββββββββββββββββββββββββββββββββ
# Total: 1 errors, 2 warnings across 3 files
Interactive TUI
PipeChecker includes a terminal UI for browsing results across multiple files:
ββββββββββββββββββββββββββββββββββββββββββββ
β π Pipecheck - Interactive Mode β
ββββββββββββββββββββββββββββββββββββββββββββ€
β Workflows β
ββΆ β deploy.yml β 2 errors β 1 warnings β
β β
ci.yml β 0 errors β 0 warnings β
β β οΈ lint.yml β 0 errors β 3 warnings β
ββββββββββββββββββββββββββββββββββββββββββββ€
β [β/β] Navigate [Enter] Details [Q] Quitβ
ββββββββββββββββββββββββββββββββββββββββββββ
Keyboard shortcuts:
| Key | Action |
|---|---|
β / k |
Move up |
β / j |
Move down |
Enter / Space |
Toggle detail view |
q / Esc |
Quit |
All CLI Flags
| Flag | Description |
|---|---|
FILE |
Path to a specific workflow file |
--all, -a |
Audit all discovered workflow files |
--tui |
Launch the interactive terminal UI |
--watch, -w |
Watch for file changes and re-run audits |
--fix |
Auto-fix issues (pin unpinned actions + Docker :latest tags) |
--install-hook |
Install a git pre-commit hook |
--format, -f <text|json> |
Output format (default: text) |
--strict, -s |
Treat warnings as errors (exit code 1) |
--quiet, -q |
Only output errors β suppress warnings and info. Perfect for CI |
--verbose |
Show diagnostic info (auditors ran, per-severity counts, discovered files) |
--no-pinning |
Skip Docker image and action-pinning checks |
--version |
Show version |
--help |
Show help |
Output Explained
Severity Levels
| Symbol | Level | Meaning |
|---|---|---|
| β | Error | Must fix β will break your pipeline |
| β οΈ | Warning | Should fix β may cause issues later |
| βΉοΈ | Info | Informational β nothing to worry about |
Example output with details
Provider: GitHubActions
2 errors, 1 warnings
β ERROR: Circular dependency detected (job: deploy) [line 42]
π‘ Remove one of the dependencies to break the cycle
β ERROR: Job 'deploy' depends on non-existent job 'build' (job: deploy) [line 45]
π‘ Add a job with id 'build' or remove the dependency
β οΈ WARNING: Job 'lint' has no steps (job: lint) [line 12]
π‘ Add steps to perform work in this job
Each issue includes:
- What went wrong (clear message)
- Where it happened (job name + line number)
- How to fix it (actionable suggestion)
JSON Output
Perfect for CI/CD integration or programmatic consumption:
Modes of Operation
π§ Auto-Fix Mode
Automatically pins unpinned GitHub Actions to known versions:
π§ Auto-fix mode
β¨ Fixed 2 issue(s) in .github/workflows/ci.yml:
actions/checkout β actions/checkout@v4
actions/setup-node β actions/setup-node@v4
π‘ Review the changes and commit them!
π Watch Mode
Monitors workflow files and re-runs on every save β perfect for development:
π Watching for workflow changes...
Press Ctrl+C to stop
π File changed: .github/workflows/ci.yml
Provider: GitHubActions
0 errors, 0 warnings
β
All checks passed
π€« Quiet Mode (CI-Friendly)
Only output errors β suppress warnings and info. Perfect for CI pipelines where you want clean output:
# or
β Circular dependency detected (job: deploy) (in .github/workflows/deploy.yml)
Exit code is still 1 if there are errors β works perfectly with --strict for failing CI on any issue.
π’ Verbose Mode
See exactly what PipeChecker is doing β which files it found, which auditors ran, and per-severity breakdowns:
π Auditing: .github/workflows/ci.yml
π Auditors ran: syntax, dag, secrets, pinning
π Found: 0 errors, 1 warnings, 0 info
β±οΈ Checked in 3.2ms
β±οΈ Timing Metrics
Every audit now shows how long it took β because speed matters:
Provider: GitHubActions
0 errors, 0 warnings
β
All checks passed
β±οΈ Checked in 2.1ms
π Pre-commit Hook
Never commit a broken workflow again:
β
Pre-commit hook installed!
Pipecheck will run before every commit
Use 'git commit --no-verify' to skip
The hook automatically validates any workflow files you stage:
)
Configuration File
Create a .pipecheckerrc.yml in your project root to customize behavior:
# Files to skip (glob patterns supported)
ignore:
- .github/workflows/experimental-*.yml
- .github/workflows/draft-*.yml
- old-pipeline.yml
# Toggle individual audit rules
rules:
circular_dependencies: true # Detect dependency cycles
missing_secrets: true # Flag hardcoded secrets
docker_latest_tag: true # Warn about :latest tags
PipeChecker searches for config in this order:
.pipecheckerrc.yml.pipecheckerrc.yaml.pipechecker.yml
How the Auditors Work
π Syntax Auditor
Validates the structural integrity of your pipeline:
- β Jobs are defined
- β Steps exist within jobs
- β No duplicate job IDs
- β
needs/depends_ontargets exist
π DAG Auditor (Cycle Detection)
Builds a dependency graph of your jobs and runs Tarjan's Strongly Connected Components algorithm:
job-a ββdependsβββΆ job-b
β² β
β βΌ
βββββdependsββββ job-c
β β Circular dependency detected: job-a β job-b β job-c β job-a
π Secrets Auditor
Scans for security issues in environment variables and run blocks:
env:
API_KEY: sk_live_abc123 # β οΈ Hardcoded secret
TOKEN: ${{ secrets.TOKEN }} # β
Correct way
RUN: echo ${{ secrets.API_KEY }} # βΉοΈ Info β ensure it's configured
RUN: echo ${{ env.UNDEFINED }} # β οΈ Undeclared env var
Detects:
- Hardcoded API keys, passwords, tokens
- Secret references in
with:blocks - Undeclared
${{ env.X }}references - Suspicious values (long alphanumeric strings, base64)
π³ Docker & π Pinning Auditor
Ensures reproducible builds:
uses: actions/checkout # β οΈ No version pin
uses: actions/checkout@v4 # β
Pinned
image: nginx:latest # β οΈ Unpredictable
image: nginx:1.25-alpine # β
Specific
Real-World Examples
Example 1: Valid workflow
Example 2: Circular dependency
jobs:
deploy:
needs:
steps:
test:
needs:
steps:
)
Example 3: Hardcoded secrets
jobs:
build:
env:
API_SECRET: sk_live_hardcoded_value
steps:
Architecture
pipechecker/
βββ src/
β βββ main.rs # CLI entry point (clap)
β βββ lib.rs # Public API β audit_file, audit_content, discover_workflows
β βββ models.rs # Core types β Pipeline, Job, Step, Issue, Severity
β βββ error.rs # Error enum (thiserror)
β βββ config.rs # .pipecheckerrc.yml loading
β βββ fix.rs # Auto-fix for action pinning
β βββ tui.rs # Interactive terminal UI (ratatui + crossterm)
β βββ parsers/
β β βββ mod.rs # Provider detection + dispatch
β β βββ github.rs # GitHub Actions YAML parser
β β βββ gitlab.rs # GitLab CI YAML parser
β β βββ circleci.rs # CircleCI YAML parser
β βββ auditors/
β βββ mod.rs # Module gate
β βββ syntax.rs # Structural validation
β βββ dag.rs # Dependency graph + cycle detection (petgraph)
β βββ secrets.rs # Secret/env var scanning (regex)
β βββ pinning.rs # Action/Docker image pinning
βββ tests/
β βββ parser_test.rs # Parser integration tests
β βββ auditors_test.rs # Auditor + fixture tests
βββ tests/fixtures/ # Sample workflow files for testing
CI/CD Integration
Add PipeChecker to your own CI pipeline:
- name: Validate workflows
run: |
cargo install pipechecker
pipechecker --all --strict --format json
Or use it as a pre-commit hook (recommended):
Development
Run tests
# 103 tests β all passing
Lint & format
Coverage
License
This project is licensed under either MIT or Apache-2.0 at your option.
SPDX: MIT OR Apache-2.0
PipeChecker β because waiting 10 minutes for CI to tell you about a typo is nobody's idea of fun.