Run in CI
Wire the doctor into GitHub Actions, GitLab CI, or any CI that can run Node. SARIF, exit codes, and inline annotations.
The doctor is designed to be boring in CI. One command, one exit code, one report artifact. This page walks through the three integration shapes you actually need.
GitHub Actions
The recommended pattern uses a composite action plus the SARIF
uploader. The doctor writes .doctor/report.sarif, and the
github/codeql-action/upload-sarif step surfaces every finding as an
inline PR annotation.
name: doctor
on:
pull_request:
push:
branches: [main]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed for --diff
- uses: actions/setup-node@v4
with:
node-version: 24
- name: Run the doctor
run: npx -y @geoql/vue-doctor --format sarif --output .doctor/report.sarif --fail-on warn
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: .doctor/report.sarif
category: doctor
The --fail-on warn flag makes the step exit 1 on any warn or
error. Pick the threshold that matches your team's tolerance:
| threshold | meaning |
|---|---|
error | exit 1 only on error findings (default) |
warn | exit 1 on warn and error |
none | never exit 1; useful for SARIF-only integrations |
Always upload the SARIF file with if: always(). If the doctor
crashes, the SARIF step still runs and the failure surfaces as a
workflow error — which is what you want, not a silent green check.
GitLab CI
GitLab uses the same SARIF artifact and a separate step to surface it
as a codequality report.
doctor:
image: node:24
script:
- npx -y @geoql/vue-doctor --format sarif --output doctor.sarif --fail-on warn
artifacts:
when: always
reports:
codequality: doctor.sarif
paths:
- doctor.sarif
expire_in: 30 days
GitLab renders the SARIF on the merge request's "Code Quality" widget. Each finding links back to the file and line in your repo.
Generic CI
For anything that can run Node, the surface is three flags and a report path:
npx -y @geoql/vue-doctor \
--format sarif \
--output ./doctor.sarif \
--fail-on warn
The exit codes are stable:
| exit | meaning |
|---|---|
0 | clean, score above threshold |
1 | at or above --fail-on threshold (or score below) |
2 | invalid arguments, missing config, doctor crash |
Exit 2 is reserved for infrastructure failures, not findings.
If your CI script checks if exit_code == 1, exit 2 will not match
— that's intentional. Investigate exit 2 like a build crash.
Diff mode for PRs
The doctor supports a --diff flag that scopes the audit to files
changed in the current branch vs. the merge base. This is much faster
on large repos and produces a smaller SARIF artifact.
npx -y @geoql/vue-doctor --diff --fail-on warn
For pre-commit / pre-push hooks, use --staged instead — it scopes
to files in the git index.
The diff is computed against origin/HEAD (or the configured merge
base). Make sure your CI step has fetch-depth: 0 so the full
history is available.
Composite actions
The published composite actions wrap the above patterns with sensible defaults:
- uses: geoql/doctor/.github/actions/doctor@v0
with:
fail-on: warn
format: sarif
The composite is idempotent and caches ~/.npm between runs. It
returns the same exit codes as the raw CLI.
Annotations on the CLI
Even without SARIF, the doctor can emit ::error file=…,line=…::
annotations directly. This is what the default agent reporter does
on a TTY.
$ npx -y @geoql/vue-doctor --annotations
::error file=app/composables/use-cart.ts,line=14,col=15::no-non-null-assertion-on-ref-value: Avoid `ref.value!` …
If your CI log is a TTY (most modern runners are), you'll see these as inline annotations without any extra configuration.