ci-doctor
v0.5.1
Published
Audit GitHub Actions workflows for waste, cost, and security gaps. Fast, opinionated, CI-friendly.
Downloads
1,998
Maintainers
Readme
ci-doctor
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.
$ 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-doctorNode 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.sarifSeverity 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.
Sponsor / support depmedic
If this saved you 10 minutes of CI debugging, consider one of these. All of them keep the free CLIs free:
- Tip what you want — pay-what-you-want, $0 minimum: https://buy.polar.sh/polar_cl_tipjar?utm_source=npm&utm_medium=readme&utm_campaign=ci-doctor
- depmedic Pro $5/mo — one license, unlocks Pro tier in every depmedic CLI + the VS Code / Cursor extension, free access to every paid playbook for as long as you stay subscribed: https://buy.polar.sh/polar_cl_SUzmX5RCQCV8MJV3dDEBFMu3MGWu2WQhzZ1s02ZhK09?utm_source=npm&utm_medium=readme&utm_campaign=ci-doctor
- Everything Bundle $59 once — every paid playbook (current and future): https://buy.polar.sh/polar_cl_everything_bundle?utm_source=npm&utm_medium=readme&utm_campaign=ci-doctor
- Sponsor on GitHub — https://github.com/sponsors/depmedicdev-byte
More from depmedic
| | |
| --- | --- |
| ci-doctor | audit GitHub Actions for cost + security (16 rules) |
| gitlab-ci-doctor | same engine for .gitlab-ci.yml (14 rules) |
| bitbucket-ci-doctor | for bitbucket-pipelines.yml (8 rules) |
| azure-pipelines-ci-doctor | for azure-pipelines.yml (8 rules) |
| circleci-ci-doctor | for .circleci/config.yml (8 rules) |
| gha-budget | $-denominated cost estimate of any GHA workflow |
| pin-actions | one-shot SHA pinner for uses: blocks |
| cursor-rules-init | scaffold .cursor/rules/ for your stack |
| depmedic | all-in-one cli, finds outdated/risky deps |
| depmedic/ci-doctor-action | composite GitHub Action: PR comment + SARIF |
In-browser scanners (no install): GitHub · GitLab · Bitbucket · Azure · CircleCI.
Newsletter (weekly, low-volume): https://depmedicdev-byte.github.io/newsletter.html?utm_source=npm&utm_medium=readme&utm_campaign=ci-doctor.
