prune

CI/CD Integration

How to integrate Prune into automated pipelines using exit codes, GitHub Actions, and streaming output.

Prune is designed for use in CI/CD pipelines. It respects exit codes for pipeline gating, supports machine-readable output formats, and can stream findings incrementally for large codebases.


Exit Code Behavior

By default, prune scan exits with code 0 regardless of findings. This is suitable for report-only mode, where you want findings logged but do not want to block a build.

To make Prune fail the pipeline when findings are detected, pass --fail-on-findings:

prune scan --fail-on-findings

If any findings pass the --min-confidence filter, Prune exits with code 1 and prints an error message to stderr:

Error: found 3 findings

Combine --fail-on-findings with --min-confidence to control the severity threshold that blocks the build:

# Fail only if there are safe (high-confidence) dead code findings
prune scan --fail-on-findings --min-confidence safe

# Fail on safe or likely_dead findings
prune scan --fail-on-findings --min-confidence likely_dead

GitHub Actions

Basic setup (build from source)

name: Code Quality

on:
  push:
  pull_request:

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

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.24'

      - name: Install Prune
        run: go install github.com/carlosedujs/prune/cmd/prune@latest

      - name: Run dead code analysis
        run: prune scan --fail-on-findings

Using a pre-built binary

Download a specific release binary to avoid requiring Go in the CI image:

- name: Install Prune
  run: |
    curl -L https://github.com/carlosedujs/prune/releases/latest/download/prune_Linux_x86_64.tar.gz | tar xz
    mv prune /usr/local/bin/prune

Report-only mode (no build failure)

To run Prune and log findings without blocking the pipeline:

- name: Run dead code analysis (report only)
  run: prune scan --format json | tee findings.json
  continue-on-error: true

- name: Upload findings
  uses: actions/upload-artifact@v4
  with:
    name: dead-code-findings
    path: findings.json

Using JSON Output for Post-Processing

In CI, JSON or NDJSON output is more useful than the table format for downstream tools:

// [!code ++]

# Count total safe findings (updated for new JSON structure)
prune scan --format json | jq '.findings | map(select(.confidence == "safe")) | length'

# List all orphaned files
prune scan --format json | jq '.findings[] | select(.kind == "unused_file") | .file'

# Fail if more than 10 safe findings
COUNT=$(prune scan --format json | jq '.findings | map(select(.confidence == "safe")) | length')
if [ "$COUNT" -gt 10 ]; then
  echo "Too many dead code findings: $COUNT"
  exit 1
fi

The new JSON format wraps findings in a root object with summary and metadata. Update any jq filters to access .findings first.

// [!code --]

// [!code highlight]

# Count total safe findings
prune scan --format json | jq 'map(select(.confidence == "safe")) | length'

# List all orphaned files
prune scan --format json | jq '.[] | select(.kind == "unused_file") | .file'

# Fail if more than 10 safe findings
COUNT=$(prune scan --format json | jq 'map(select(.confidence == "safe")) | length')
if [ "$COUNT" -gt 10 ]; then
  echo "Too many dead code findings: $COUNT"
  exit 1
fi

// [!code focus]


Streaming for Large Codebases

For large projects, --stream with NDJSON output allows results to appear in CI logs before the full scan completes:

prune scan --stream --format ndjson

Each finding is printed to stdout as it is discovered. This is useful when the full scan takes several seconds and you want early visibility in logs.

Streaming mode processes files in batches of up to 50, emitted every --stream-interval milliseconds (default: 250ms). Results from streaming mode may appear in a different order than standard mode.


A production configuration for a TypeScript project using Prune in CI:

prune.yaml:

version: 2
project:
  name: my-app
  language: js-ts

ts_config:
  enabled: true
  baseUrl: .
  paths:
    "@/*":
      - src/*
    "~/*":
      - src/components/*

scan:
  paths:
    - src
  include:
    - '**/*.ts'
    - '**/*.tsx'
  exclude:
    - node_modules/**
    - dist/**
    - .next/**
    - '**/*.test.ts'
    - '**/*.spec.ts'
entrypoints:
  files:
    - src/index.ts
  patterns:
    - src/pages/**
rules:
  unused_function:
    enabled: true
  unused_variable:
    enabled: true
  unused_export:
    enabled: true
  unused_file:
    enabled: true
  dead_feature_flag:
    enabled: false
  suspicious_dynamic_usage:
    enabled: true
report:
  format: table
  min_confidence: safe

GitHub Actions step:

- name: Analyze dead code
  run: prune scan --config prune.yaml --fail-on-findings --min-confidence safe

This configuration excludes test files from the scan, disables the feature flag rule (not applicable to all projects), and fails the build on any high-confidence dead code finding.

On this page