gitlab-ci-doctor
Audit any .gitlab-ci.yml for waste, cost leaks, and security gaps.
Twelve rules. One command. MIT. Sister project to
ci-doctor
(which does the same job for GitHub Actions).
npm npmjs.com/package/gitlab-ci-doctor | source github.com/depmedicdev-byte/gitlab-ci-doctor | try it in-browser scanner
Try it in 5 seconds
$ npx gitlab-ci-doctor # audit current repo $ npx gitlab-ci-doctor --markdown # MR-comment friendly output $ npx gitlab-ci-doctor --json # machine-readable $ npx gitlab-ci-doctor --severity=warn # warn + error only $ npx gitlab-ci-doctor --rules # list checks $ npx gitlab-ci-doctor --demo # smoke-test against bundled bad pipeline
Exit code is 1 when there are error-level findings, so it drops into a GitLab CI lint stage (or a pre-commit hook) without ceremony.
What it catches
| Rule | Severity | What it catches |
|---|---|---|
image-no-pin | warn | :latest and bare image names are mutable; pin a digest. |
missing-cache | warn | npm/pip/gradle/cargo etc. without cache: re-download every run. |
missing-interruptible | warn | Stale pipelines on superseded MR commits keep burning minutes. |
missing-timeout | warn | A hung job runs to the project default (often 1h, max 24h). |
expensive-runner | warn | saas-linux-large/2xlarge, saas-windows, saas-macos cost 2x to 10x. |
artifact-no-expiration | warn | artifacts: without expire_in: accumulate storage cost. |
deprecated-only-except | info | Migrate to rules: (composes with workflow:rules). |
git-strategy-clone | warn | clone re-fetches full history every job; prefer fetch + GIT_DEPTH. |
parallel-overcommit | warn | parallel: > 8 multiplies job minutes; sanity-check the matrix. |
missing-needs | info | Stages without needs: block on the entire previous stage. |
wide-rules | info | No rules: and no workflow:rules runs on every push and every MR. |
include-no-pin | warn | Remote/project includes without an immutable ref give upstream control of your pipeline. |
Drop it into a GitLab pipeline
ci-doctor:
stage: lint
image: node:22-alpine
interruptible: true
cache:
key: "$CI_COMMIT_REF_SLUG-npx"
paths:
- .npm/
script:
- npx --yes gitlab-ci-doctor --markdown > ci-doctor.md
- cat ci-doctor.md
artifacts:
when: always
paths:
- ci-doctor.md
expire_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
That job posts the audit as an artifact on every MR pipeline, with a tiny cache so the npx fetch is one-off per branch. Add a before_script that comments back to the MR if you want, but the artifact alone is usually enough.
One bad example, one fix
Before
image: node:latest
stages: [build, test]
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths: [dist/]
test:
stage: test
tags: [saas-linux-2xlarge-amd64]
script:
- npm test
parallel: 16
After
image: node@sha256:<digest>
stages: [build, test]
default:
interruptible: true
cache:
key: "$CI_COMMIT_REF_SLUG"
paths: [node_modules/, .npm/]
timeout: 15 minutes
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths: [dist/]
expire_in: 1 week
test:
stage: test
needs: [build]
script:
- npm test
parallel: 4
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
That's roughly a 5x cost reduction on the test stage (4-way parallel on medium runners vs 16-way on 2xlarge), plus reproducible builds, plus stale pipelines auto-cancel.
Programmatic use
const { auditPipeline, summarize } = require('gitlab-ci-doctor');
const fs = require('node:fs');
const findings = auditPipeline(fs.readFileSync('.gitlab-ci.yml', 'utf8'), '.gitlab-ci.yml');
console.log(summarize(findings));
Compared to other tools
vs gitlab-ci-lint (GitLab's official): validates syntax and merges extends:; doesn't check cost or security hygiene.
vs yamllint: checks YAML formatting; doesn't understand GitLab's job model.
vs gcl / local runners: they execute the pipeline; gitlab-ci-doctor reads it and tells you what to fix without running anything.
Try it now without installing
The same engine runs in your browser. Paste a project path or a URL.
Open the in-browser scanner npm installAlready on GitHub Actions? See the sister project.
ci-doctor ships 14 rules + auto-fix for .github/workflows/*.yml. Same engine, same opinions.