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

RuleSeverityWhat it catches
image-no-pinwarn:latest and bare image names are mutable; pin a digest.
missing-cachewarnnpm/pip/gradle/cargo etc. without cache: re-download every run.
missing-interruptiblewarnStale pipelines on superseded MR commits keep burning minutes.
missing-timeoutwarnA hung job runs to the project default (often 1h, max 24h).
expensive-runnerwarnsaas-linux-large/2xlarge, saas-windows, saas-macos cost 2x to 10x.
artifact-no-expirationwarnartifacts: without expire_in: accumulate storage cost.
deprecated-only-exceptinfoMigrate to rules: (composes with workflow:rules).
git-strategy-clonewarnclone re-fetches full history every job; prefer fetch + GIT_DEPTH.
parallel-overcommitwarnparallel: > 8 multiplies job minutes; sanity-check the matrix.
missing-needsinfoStages without needs: block on the entire previous stage.
wide-rulesinfoNo rules: and no workflow:rules runs on every push and every MR.
include-no-pinwarnRemote/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 install

Already on GitHub Actions? See the sister project.

ci-doctor ships 14 rules + auto-fix for .github/workflows/*.yml. Same engine, same opinions.

depmedic home ci-doctor on npm