CI pipelines
Gate a build on DepWall — copy-paste recipes for GitHub Actions, GitLab CI and Jenkins, and the exit codes they read.
DepWall gates a build the same way it gates a developer's shell: it exits by verdict, and the runner reads the exit code. There is nothing to install into the pipeline beyond the CLI itself.
Use guard, not check#
This is the one thing to get right, because both commands look like they would work and only one of them does.
depwall guard | depwall check | |
|---|---|---|
| ALLOW | 0 | 0 |
| ASK | 2 | 0 — passes |
| BLOCK | 1 | 1 |
| Registry unreachable | fails closed | 0 — passes |
check is the informational command. It answers a question a human
asked, and it deliberately fails open: if the registry is down it
prints the error and exits 0, because refusing to answer a query
is not the same as refusing an install. Wire that into a pipeline and the
build goes green on the day the npm registry has an outage — which is a good
day to ship something unchecked and a bad day to find out.
guard is the enforcing command. It reads the
resolved lockfile tree, fails closed, and gives ASK its own exit code so a
pipeline can decide what to do about it.
GitHub Actions#
- name: DepWall
run: |
npm install -g depwall
depwall guard npm install
Runs before npm ci. A BLOCK exits 1 and fails the
step; an ASK exits 2 and also fails it, which is the right
default — ASK means nobody has looked yet, and a pipeline has no human to ask.
To let ASK through and still see it, split the codes:
- name: DepWall
run: |
npm install -g depwall
depwall guard npm install || case $? in
1) echo "::error::DepWall blocked a dependency"; exit 1 ;;
2) echo "::warning::DepWall wants a human to look at this"; exit 0 ;;
*) exit 1 ;;
esac
GitLab CI#
depwall:
image: node:22
script:
- npm install -g depwall
- depwall guard npm install
# allow_failure with exit_codes reports ASK without failing the pipeline
allow_failure:
exit_codes: 2
Jenkins#
stage('DepWall') {
steps {
script {
sh 'npm install -g depwall'
def code = sh(script: 'depwall guard npm install', returnStatus: true)
if (code == 1) { error 'DepWall blocked a dependency' }
if (code == 2) { unstable 'DepWall wants a human to look at this' }
}
}
}
What it checks in CI#
Exactly what it checks locally. With a lockfile present,
guard npm install expands the full resolved tree (capped at 200
packages; a truncated tree escalates to ASK rather than passing), verifies each
entry's resolved URL against the registry it claims to come from,
and runs every signal over the packages themselves. Without a lockfile it falls
back to the names declared in package.json.
Set ANTHROPIC_API_KEY as a secret if you want the gray-zone judge
to run in CI. Without it the gray zone stays ASK and never escalates on its
own — the gate does not silently get more permissive because a key is missing,
it gets noisier.
guard works the same way for the other managers:
depwall guard pip install, depwall guard cargo, and
so on. See Coverage for the full list.