Skip to content

ci-doctor

Actions

About

Audit GitHub Actions workflows for waste, cost, and security gaps. Posts a PR comment with findings
v0.5.0
Latest
Star (1)

ci-doctor

Sponsor

npm ci license

Audit GitHub Actions workflows for waste, cost, and security gaps. CLI and a GitHub Action. Posts a comment on every PR with a table of findings and fix-it suggestions.

Try it without installing: paste a workflow into the in-browser audit. Same rules engine, runs entirely client-side, nothing leaves your tab. Want the dollar number? budget.html prices the same workflow.

demo

$ npx ci-doctor examples/bad-workflow

Found 7 finding(s)  [error 1  warn 4  info 2]

.github/workflows/ci.yml
  ERROR  7:15  deprecated-action
         actions/checkout@v3 is on a deprecated major. Latest stable: v4.
         | actions/checkout@v4
  WARN   8:15  missing-cache
         actions/setup-node has no cache option. Add 'with: cache: <ecosystem>' to skip dep re-downloads. Saves 30-90 seconds per run.
         | with:
         |   cache: npm   # or pip, gradle, maven, go, etc.
  WARN   2:5   missing-concurrency
         No top-level concurrency block. New pushes will not cancel in-flight runs of stale commits, doubling spend on rapid-push branches.
         | concurrency:
         |   group: ${{ github.workflow }}-${{ github.ref }}
         |   cancel-in-progress: true
  WARN   5:5   missing-timeout
         Job 'build' has no timeout-minutes. Default is 360 (6h). A hung job can drain your CI budget.
         | timeout-minutes: 15   # tune to your job; cap below the default 360.
  WARN   1:7   missing-permissions
         No top-level permissions block. GITHUB_TOKEN inherits the repo default, often write-all. Set least-privilege explicitly.
         | permissions:
         |   contents: read   # add other scopes only as jobs need them.
  INFO   2:5   wide-trigger
         on: push fires on every branch. Restrict to main or release branches unless you need every-branch runs.
  INFO   14:15 artifact-no-retention
         upload-artifact has no retention-days. CI artifacts pile up at the repo default (usually 90d). Set 7-14d unless you need long-term retention.

Above is real output from examples/bad-workflow/. Try it: git clone https://github.com/depmedicdev-byte/ci-doctor && cd ci-doctor && npx ci-doctor examples/bad-workflow.

Why

act runs your workflow locally. actionlint checks syntax. Neither tells you the workflow is burning money. ci-doctor focuses on the cost and security defaults you actually control.

Install

CLI

npm install -g ci-doctor
# or one-shot
npx ci-doctor

Node 18+.

GitHub Action

name: ci-doctor
on:
  pull_request:
permissions:
  contents: read
  pull-requests: write
jobs:
  audit:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4
      - uses: depmedicdev-byte/ci-doctor@v1
        with:
          fail-on: error
          comment: 'true'

It runs against every workflow under .github/workflows/, posts a single sticky comment on the PR, and updates that comment on subsequent runs.

Use

ci-doctor                          # scan .github/workflows in cwd
ci-doctor path/to/repo             # scan another repo
ci-doctor --file ci.yml            # one file
ci-doctor --json                   # machine output for CI
ci-doctor --markdown               # PR-comment table
ci-doctor --severity=warn          # only warn + error
ci-doctor --only=missing-cache     # one rule
ci-doctor --disable=fetch-depth-zero
ci-doctor --rules                  # list rules
ci-doctor --fix                    # auto-apply safe fixes in place (new in 0.2)
ci-doctor --fix --dry-run          # preview the patched yaml on stdout
ci-doctor --sarif                  # SARIF 2.1.0 for GitHub Code Scanning (new in 0.3)

Exit codes: 0 no error-level findings, 1 one or more errors, 2 internal error.

Auto-fix

ci-doctor --fix rewrites your workflows in place to fix the issues that have a single safe answer. It uses the document model (preserves comments and ordering of existing keys) and only adds:

Rule What --fix adds
missing-permissions top-level permissions: { contents: read }
missing-concurrency concurrency: { group: ..., cancel-in-progress: true }
missing-timeout timeout-minutes: 15 per job missing it
artifact-no-retention retention-days: 7 on each actions/upload-artifact

Rules with judgment calls (cache ecosystem, action major-version bumps, SHA pinning, runner cost) keep their warning so you decide. SHA pinning specifically is delegated to pin-actions.

Use --fix --dry-run first if you want to see the diff before writing.

GitHub Code Scanning (SARIF)

--sarif emits SARIF 2.1.0 you can upload with the official codeql-action/upload-sarif action. Findings appear as inline PR annotations and in the repo's Security tab.

name: ci-doctor
on:
  pull_request:
permissions:
  contents: read
  security-events: write
jobs:
  audit:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4
      - run: npx ci-doctor --sarif > ci-doctor.sarif || true
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ci-doctor.sarif

Severity maps error -> error, warn -> warning, info -> note.

Rules

Rule Severity Category
deprecated-action error maintenance
pinned-action-sha warn security
missing-cache warn cost
missing-concurrency warn cost
missing-timeout warn cost
expensive-runner warn cost
missing-permissions warn security
matrix-overcommit warn cost
stale-cache-key warn cost
wide-trigger info cost
artifact-no-retention info cost
fetch-depth-zero info cost
fail-fast-true info cost
always-run-on-pr info cost

ci-doctor --rules prints them with descriptions.

Action inputs

Input Default What it does
directory . Repo root. Action looks for .github/workflows under it.
fail-on error Threshold to fail the job: error, warn, info, never.
comment true Post a single sticky PR comment with the findings.
only (empty) Comma-separated rule ids to run exclusively.
disable (empty) Comma-separated rule ids to skip.
github-token ${{ github.token }} Token used to post the PR comment.

Pro

A paid Pro tier is in development:

  • Org-wide policy file: enforce a baseline across every repo.
  • Cost projection: estimate $ saved per finding using your runner mix.
  • Audit history page on GitHub Pages.
  • Private-repo support via license key.

License via Polar: $9/month or $39/year. Free CLI and Action stay free, MIT.

Companion

  • depmedic - surgical npm vulnerability triage from the same author.

Honesty

Built with AI assistance. Every change reviewed. Open an issue if anything breaks.

License

MIT.

ci-doctor is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.

About

Audit GitHub Actions workflows for waste, cost, and security gaps. Posts a PR comment with findings
v0.5.0
Latest

ci-doctor is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.