pipechecker 0.3.1

CI/CD Pipeline Auditor - Catch errors before you push
Documentation

PipeChecker

Catch CI/CD pipeline errors before you push β€” not after CI fails.

CI Crates.io License Test Coverage Rust


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
⚠️ Missing permissions No permissions: block β€” inherits write-all token
⚠️ Missing concurrency cancel Concurrency group without cancel-in-progress
⚠️ Static cache keys actions/cache without hashFiles(...)
ℹ️ Missing retention-days actions/upload-artifact with default 90-day retention

Visual Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    YOUR WORKFLOW FILE                    β”‚
β”‚              (.github/workflows/ci.yml)                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
                         β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚    PIPECHECKER       β”‚
              β”‚                      β”‚
              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
              β”‚  β”‚  YAML Parser   β”‚  β”‚
              β”‚  β”‚ GitHub/GitLab  β”‚  β”‚
              β”‚  β”‚   CircleCI     β”‚  β”‚
              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
              β”‚          β”‚           β”‚
              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
              β”‚  β”‚    Auditors    β”‚  β”‚
              β”‚  β”‚                β”‚  β”‚
              β”‚  β”‚  πŸ“‹ Syntax     β”‚  β”‚
              β”‚  β”‚  πŸ”— DAG/Cycle  β”‚  β”‚
              β”‚  β”‚  πŸ”’ Secrets    β”‚  β”‚
              β”‚  β”‚  ⏱️  Timeout    β”‚  β”‚
              β”‚  β”‚  πŸ” Permissionsβ”‚  β”‚
              β”‚  β”‚  πŸ“ Schema     β”‚  β”‚
              β”‚  β”‚  πŸ”„ Concurrencyβ”‚  β”‚
              β”‚  β”‚  πŸ“¦ Artifacts  β”‚  β”‚
              β”‚  β”‚  🐳 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

cargo install pipechecker

From source

git clone https://github.com/Ayyankhan101/PipeChecker.git
cd PipeChecker
cargo install --path .

Via npm (once published)

npm install -g pipechecker

GitHub Action

PipeChecker can be used directly in your GitHub workflows:

name: CI Pipeline Check
on: [push, pull_request]

jobs:
  pipechecker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Ayyankhan101/PipeCheck/actions/pipecheck@v0.3.0

Action Inputs

Input Required Default Description
path No .github/workflows Path to workflow file(s)
strict No false Exit with error on warnings
diff No false Check only changed files
diff-branch No main Base branch for diff mode

Diff Mode

Check only workflow files that changed since a base branch:

# Check files changed since main
pipechecker --diff --diff-branch main

# Short form
pipechecker -d

This uses git diff --name-only to find changed workflow files, then checks only those. Faster in monorepos with many workflows.


Quick Start

1. Check a single file

pipechecker .github/workflows/ci.yml

2. Auto-detect your workflow

pipechecker
# βœ“ Auto-detected: .github/workflows/ci.yml
# Provider: GitHubActions
# 0 errors, 0 warnings

3. Audit everything

pipechecker --all
# 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:

pipechecker --tui
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  πŸ” 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)
--init Initialize a new workflow from a template
--template Template name: node, rust, docker, gitlab-node
--force Force overwrite existing files (with --init)
--install-hook Install a git pre-commit hook
--diff, -d Check only files changed since base branch
--diff-branch Base branch for diff mode (default: main)
--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
--ci CI mode β€” implies --quiet --strict --format json
--verbose Show diagnostic info (auditors ran, per-severity counts)
--explain Print detailed explanation for a rule code (e.g. PC005)
--no-pinning Skip Docker image and action-pinning checks
--no-permissions Skip permissions auditor (GitHub Actions only)
--no-schema Skip schema validation
--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) [PC005] [line 42]
   πŸ’‘ Remove one of the dependencies to break the cycle

❌ ERROR: Job 'deploy' depends on non-existent job 'build' (job: deploy) [PC004] [line 45]
   πŸ’‘ Add a job with id 'build' or remove the dependency

⚠️ WARNING: Job 'lint' has no steps (job: lint) [PC003] [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:

pipechecker --format json
{
  "provider": "GitHubActions",
  "issues": [
    {
      "severity": "Error",
      "message": "Circular dependency detected: job-a -> job-b -> job-a",
      "location": { "line": 42, "column": 3, "job": "deploy" },
      "suggestion": "Remove one of the dependencies to break the cycle",
      "rule_code": "PC005"
    }
  ],
  "summary": "1 errors, 0 warnings"
}

Modes of Operation

πŸ”§ Auto-Fix Mode

Automatically pins unpinned GitHub Actions to known versions:

pipechecker --fix
πŸ”§ 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:

pipechecker --watch
πŸ‘€ 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:

pipechecker --quiet
# or
pipechecker -q
❌ 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.

πŸ€– CI Mode

One flag that implies --quiet --strict --format json. Ideal for CI automation:

pipechecker --ci

πŸ“– Explain Mode

Get a detailed explanation for any rule code:

pipechecker --explain PC005
πŸ“– Rule PC005 β€” Circular dependency detected

Two or more jobs form a dependency cycle (A needs B, B needs A).
The pipeline can never start because each job is waiting for another.
Remove one of the edges in the cycle to break it.

Available rule codes:

Code Rule
PC001 Empty pipeline
PC002 Duplicate job ID
PC003 Empty job steps
PC004 Missing dependency
PC005 Circular dependency
PC006 Hardcoded secret
PC007 Secret reference
PC008 Undeclared env var
PC009 Unpinned action
PC010 Docker :latest tag
PC011 Missing timeout
PC012 Missing trigger
PC013 Missing runs-on
PC014 Missing permissions
PC015 Invalid YAML
PC016 Missing concurrency cancel
PC017 Static cache key
PC018 Missing artifact retention

πŸ“’ Verbose Mode

See exactly what PipeChecker is doing β€” which files it found, which auditors ran, and per-severity breakdowns:

pipechecker --verbose
πŸ“„ Auditing: .github/workflows/ci.yml
πŸ” Auditors ran: syntax, dag, secrets, timeout, permissions, schema, concurrency, artifacts, 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:

pipechecker .github/workflows/ci.yml
Provider: GitHubActions
0 errors, 0 warnings
βœ… All checks passed
⏱️  Checked in 2.1ms

πŸ”’ Pre-commit Hook

Never commit a broken workflow again:

pipechecker --install-hook
βœ… 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:

$ git commit -m "Update CI pipeline"
πŸ” Checking workflows with pipechecker...
❌ ERROR: Circular dependency detected (job: deploy) [line 42]
   πŸ’‘ Remove one of the dependencies to break the cycle

❌ Workflow validation failed!
Fix errors above or use 'git commit --no-verify' to skip

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
  timeout_validation: true      # Warn about missing timeouts
  permissions_check: true       # Warn about missing permissions
  schema_validation: true       # Structural YAML validation
  concurrency_validation: true  # Check cancel-in-progress
  artifacts_check: true         # Cache/artifact best practices

PipeChecker searches for config in this order:

  1. .pipecheckerrc.yml
  2. .pipecheckerrc.yaml
  3. .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_on targets 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

⏱️ Timeout Auditor

Warns when jobs lack timeout-minutes β€” prevents runaway CI jobs:

build:
  runs-on: ubuntu-latest
  # ⚠️ No timeout-minutes β€” can run forever if something hangs
  steps: [...]

πŸ” Permissions Auditor

Warns when GitHub Actions jobs have no explicit permissions: block:

build:
  runs-on: ubuntu-latest
  # ⚠️ No permissions block β€” inherits write-all token
  steps: [...]

πŸ“ Schema Auditor

Validates YAML structure against provider-specific schemas β€” catches missing keys, bad types, and structural issues.

πŸ”„ Concurrency Auditor

Checks for cancel-in-progress: true when concurrency groups are used β€” prevents wasted CI minutes on outdated runs.

πŸ“¦ Artifacts & Cache Auditor

Checks actions/cache for static keys (should include hashFiles(...)) and actions/upload-artifact for missing retention-days.


Real-World Examples

Example 1: Valid workflow

$ pipechecker .github/workflows/ci.yml
Provider: GitHubActions
0 errors, 0 warnings

Example 2: Circular dependency

jobs:
  deploy:
    needs: [test]
    steps: [{ run: echo deploy }]
  test:
    needs: [deploy]
    steps: [{ run: echo test }]
$ pipechecker broken.yml
Provider: GitHubActions
1 errors, 0 warnings

❌ ERROR: Circular dependency detected (job: deploy)
   πŸ’‘ Remove one of the dependencies to break the cycle

Example 3: Hardcoded secrets

jobs:
  build:
    env:
      API_SECRET: sk_live_hardcoded_value
    steps: [{ run: echo building }]
$ pipechecker secrets.yml
Provider: GitHubActions
0 errors, 1 warnings

⚠️ WARNING: Job 'build' env 'API_SECRET' may contain a hardcoded secret
   πŸ’‘ Use secrets.API_SECRET instead of hardcoding

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, rule codes
β”‚   β”œβ”€β”€ 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 (PC001–PC004)
β”‚       β”œβ”€β”€ dag.rs       # Dependency graph + cycle detection (PC005)
β”‚       β”œβ”€β”€ secrets.rs   # Secret/env var scanning (PC006–PC008)
β”‚       β”œβ”€β”€ timeout.rs   # Missing timeout detection (PC011)
β”‚       β”œβ”€β”€ permissions.rs # GitHub Actions permissions (PC014)
β”‚       β”œβ”€β”€ schema.rs    # Structural YAML validation (PC012–PC013, PC015)
β”‚       β”œβ”€β”€ concurrency.rs # Concurrency group checks (PC016)
β”‚       β”œβ”€β”€ artifacts.rs # Cache/artifact best practices (PC017–PC018)
β”‚       β”œβ”€β”€ include.rs   # GitLab include: block parsing
β”‚       └── pinning.rs   # Action/Docker image pinning (PC009–PC010)
β”œβ”€β”€ templates/           # Embedded workflow templates
β”œβ”€β”€ 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:

# Option 1: Use the GitHub Action
- uses: Ayyankhan101/PipeCheck/actions/pipecheck@v0.3.0

# Option 2: Run directly
- name: Validate workflows
  run: |
    cargo install pipechecker
    pipechecker --ci

Or use it as a pre-commit hook (recommended):

pipechecker --install-hook

Development

Run tests

cargo test
# 134 tests β€” all passing

Lint & format

cargo clippy -- -D warnings
cargo fmt -- --check

Coverage

cargo tarpaulin --fail-under 55

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.

Report a bug Β· Request a feature Β· Contributing