Running in CI
Copy-paste pipelines for GitHub Actions, GitLab CI, and anywhere else.
Documentation pages
Flag Marshal is a command-line tool, so it runs in any pipeline that has Node 20
or later. It makes no network calls of its own; the only download is the package
itself through npx. Pin the version you have tested, as below.
These reference recipes use Flag Marshal 0.2.0, the final release, which added
--changed-sinceand thegithubandcodequalityformats.
Two ways to gate a pipeline
| Approach | Command | Fails on |
|---|---|---|
| Compare with the pull request’s base | flag-marshal check --changed-since=auto |
Policy violations this change adds |
| Ratchet against a committed baseline | flag-marshal check |
Violations not in .flagmarshal-baseline.json |
The comparison needs no file in the repository and suits pull requests. The
baseline suits a main-branch build, and trend reads its history. Either way,
check exits 0 when clean, 2 on a new violation and 1 on a usage error, so the
job fails on 2 and a broken invocation fails too.
Both need full history. A shallow clone, the default checkout in most CI systems, has no merge base to compare with, and its log would make every flag look new. Flag Marshal treats a shallow clone as having no history and warns.
GitHub Actions
Annotations on the pull request, failing on new violations:
name: Flag Marshal
on: pull_request
jobs:
flags:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # history is analysis input, and the base must be present
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npx --yes @stackblender/flag-marshal@0.2 check --changed-since=auto --format=github
--changed-since=auto reads GITHUB_BASE_REF, and --format=github prints one
annotation per violation on the changed lines. Annotations need no extra
permission and no code-scanning license.
A Markdown summary on the job page, alongside the annotations:
- run: npx --yes @stackblender/flag-marshal@0.2 scan --changed-since=auto --format=markdown >> "$GITHUB_STEP_SUMMARY"
Code scanning, if the repository has it (public repositories, or GitHub Advanced Security on private ones):
permissions:
contents: read
security-events: write
steps:
# checkout and setup-node as above
- run: npx --yes @stackblender/flag-marshal@0.2 scan --format=sarif > flag-marshal.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: flag-marshal.sarif
GitLab CI
The Code Quality widget on the merge request, failing on new violations:
flag-marshal:
image: node:22
variables:
GIT_DEPTH: 0 # history is analysis input, and the base must be present
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- npx --yes @stackblender/flag-marshal@0.2 check --changed-since=auto --format=codequality > gl-code-quality.json
artifacts:
when: always # upload the report even when check exits 2
reports:
codequality: gl-code-quality.json
In a merge request pipeline, --changed-since=auto uses
CI_MERGE_REQUEST_DIFF_BASE_SHA, the merge base GitLab computed, which a full
clone always contains. Code Quality fingerprints ignore line numbers, so moving
code does not make the widget report an issue as new.
Anywhere else
Bitbucket Pipelines (BITBUCKET_PR_DESTINATION_BRANCH) and Azure Pipelines
(SYSTEM_PULLREQUEST_TARGETBRANCH) are read by --changed-since=auto too. On any
other system, name the base:
git fetch origin main
npx --yes @stackblender/flag-marshal@0.2 check --changed-since origin/main
A main-branch build that ratchets against the committed baseline:
npx --yes @stackblender/flag-marshal@0.2 check
Accept today’s violations once, and commit the result:
npx --yes @stackblender/flag-marshal@0.2 check --update-baseline
The same commands work in a pre-push hook. --no-git skips history for a fast,
deterministic run, at the cost of flag ages.