CI Integration

pydepgate integrates with CI pipelines in three ways: direct invocation via the CLI, the Docker image for containerized pipelines, and pre-commit hooks for commit-time scanning. This page covers all three.

Exit code contract

All three integration paths depend on pydepgate’s exit codes:

Code Meaning
0 Clean. No findings at or above --min-severity.
1 Findings present, none HIGH or CRITICAL.
2 At least one HIGH or CRITICAL finding.
3 Tool error. Scan could not complete.

The standard CI pattern is to fail the build on exit code 2. Exit code 1 represents findings below the blocking threshold and does not fail the build unless you use --strict-exit, which treats any finding as blocking regardless of severity.

Direct CLI invocation

GitHub Actions

name: pydepgate scan

on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Build wheel
        run: |
          pip install build
          python -m build --wheel

      - name: Install pydepgate
        run: pip install pydepgate

      - name: Scan wheel
        run: pydepgate scan --ci --min-severity high dist/*.whl

--ci is a CI-output mode flag, not a severity filter. When set, it forces --format json if format is not already set, and forces --color never if color is currently auto. It does not change --min-severity. Pair it with --min-severity high (as above) when you want CI to block only on HIGH and CRITICAL findings.

To scan an installed package instead of a wheel:

      - name: Install target package
        run: pip install some-package

      - name: Scan installed package
        run: pydepgate scan --ci --min-severity high some-package

GitLab CI

stages:
  - build
  - scan

build-wheel:
  stage: build
  image: python:3.12-slim
  script:
    - pip install build
    - python -m build --wheel
  artifacts:
    paths:
      - dist/

scan-wheel:
  stage: scan
  image: python:3.12-slim
  script:
    - pip install pydepgate
    - pydepgate scan --ci --min-severity high dist/*.whl
  dependencies:
    - build-wheel

Docker image

The official Docker image is at ghcr.io/nuclear-treestump/pydepgate. It is a multi-stage Alpine build under 50 MB, runs as non-root (uid 1000), and is published for linux/amd64 and linux/arm64.

docker pull ghcr.io/nuclear-treestump/pydepgate:latest
docker pull ghcr.io/nuclear-treestump/pydepgate:0.4.0
docker pull ghcr.io/nuclear-treestump/pydepgate:0.4

Scan a wheel from the host filesystem:

docker run --rm \
    -v "$(pwd):/scan" \
    ghcr.io/nuclear-treestump/pydepgate:latest \
    scan --ci --min-severity high some-package.whl

The container’s working directory is /scan, so paths are resolved against the bind-mounted directory.

GitHub Actions with Docker

      - name: Scan wheel with pydepgate
        run: |
          docker run --rm \
            -v "$/dist:/scan" \
            ghcr.io/nuclear-treestump/pydepgate:0.4 \
            scan --ci --min-severity high /scan/*.whl

Or using the container directive:

      - name: Scan wheel with pydepgate
        uses: docker://ghcr.io/nuclear-treestump/pydepgate:0.4
        with:
          args: scan --ci --min-severity high dist/*.whl

GitLab CI with Docker

scan-wheel:
  stage: scan
  image:
    name: ghcr.io/nuclear-treestump/pydepgate:0.4
    entrypoint: [""]
  script:
    - pydepgate scan --ci --min-severity high dist/*.whl
  dependencies:
    - build-wheel

The entrypoint: [""] line overrides the image’s pydepgate entrypoint so GitLab can run its own shell wrapper before the script section executes.

Multi-stage Dockerfile

For projects that already containerize their build, reference the pydepgate image as a build stage:

FROM python:3.12-slim AS build
WORKDIR /src
COPY . .
RUN pip install build && python -m build --wheel

FROM ghcr.io/nuclear-treestump/pydepgate:0.4 AS scan
COPY --from=build /src/dist/*.whl /scan/
RUN pydepgate scan --ci --min-severity high /scan/*.whl

The pydepgate stage fails the build if blocking findings are present, stopping the pipeline before any downstream stage receives the artifact.

Environment variables in Docker

All PYDEPGATE_* variables work inside the container:

docker run --rm \
    -v "$(pwd):/scan" \
    -e PYDEPGATE_PEEK=1 \
    -e PYDEPGATE_MIN_SEVERITY=high \
    -e PYDEPGATE_FORMAT=json \
    ghcr.io/nuclear-treestump/pydepgate:latest \
    scan some-package.whl

pre-commit hooks

pydepgate ships two pre-commit hook IDs that integrate with pre-commit.

Hook IDs

pydepgate runs pydepgate scan --single against every staged .py file. It defaults to --min-severity high so commits are not blocked by informational findings. The threshold is tunable via args.

pydepgate-pth runs the same scanner against staged .pth files with no severity filter. .pth files have no legitimate use case for any pattern pydepgate detects, so even an INFO finding there warrants a human look.

Adding to your project

In your project’s .pre-commit-config.yaml:

repos:
  - repo: https://github.com/nuclear-treestump/pydepgate
    rev: v0.4.0
    hooks:
      - id: pydepgate
      - id: pydepgate-pth

Install and run an initial scan:

pre-commit install
pre-commit run --all-files

Tuning

Lower the threshold to catch MEDIUM and above:

      - id: pydepgate
        args: [--min-severity, medium, --no-color]

Enable payload peeking during the hook run:

      - id: pydepgate
        args: [--min-severity, high, --no-color, --peek]

Exclude generated or vendored directories:

      - id: pydepgate
        exclude: ^(generated/|vendor/|third_party/)

pre-commit in CI

The hook configuration also works under pre-commit run --all-files in CI:

GitHub Actions:

      - uses: pre-commit/action@v3.0.1

GitLab CI:

pre-commit:
  image: python:3.12-slim
  script:
    - pip install pre-commit
    - pre-commit run --all-files
Context Recommended flag Rationale
CI artifact scan --ci --min-severity high JSON output, no color, blocking only on HIGH/CRITICAL
pre-commit .py hook --min-severity high Avoids blocking commits on density informational signals
pre-commit .pth hook (no filter) All findings on .pth files warrant review
Interactive investigation --min-severity low or no filter Full signal visibility
Strict CI (zero tolerance) --strict-exit Any finding blocks the build

JSON output for downstream processing

To consume pydepgate output in a downstream step rather than failing the pipeline directly:

pydepgate scan --format json dist/*.whl > scan-results.json || true

The || true prevents the shell from stopping on a non-zero exit. Parse scan-results.json to apply custom logic. Exit code is still set correctly; use $? if you need it after the redirect.

See Output Formats for the JSON schema.


This site uses Just the Docs, a documentation theme for Jekyll.