Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Gating pruning in CI

The failure mode delta-explain was built to catch: a change quietly breaks pruning (a table gets rewritten without partitioning, a query loses its partition filter), nothing errors, and every downstream scan silently reads the whole table. A gate turns that into a failed build.

The flags

  • --min-pruning <PCT>: exit 1 if total pruning is below the threshold.
  • --assert-stats: exit 1 if any file is missing statistics.
delta-explain s3://lake/events -w "region = 'eu' AND ts > '2026-06-01'" \
  --min-pruning 80

On failure the report still prints (with result: "fail") and stderr carries ASSERTION FAILED: ... - the terminal shows both, and the exit code flips to 1:

$ delta-explain ./table -w "country = 'DE' AND age > 40" --min-pruning 90
ASSERTION FAILED: total pruning 83.3% is below threshold 90.0%
Delta table: ./table
Version:     5
Predicate:   country = 'DE' AND age > 40

Predicate Analysis:
  partition-safe: country = 'DE'
  stats-safe:     age > 40
  stats coverage:
    age [min_max]: 2/2 candidate files (100%)
  unsplittable:   -
  confidence:     conservative

Files in snapshot: 6

Phase 1: Partition pruning [exact]
  predicate:       country = 'DE'
  files remaining: 2  (-4, 67% pruned)

Phase 2: Data skipping (min/max statistics) [conservative]
  predicate:       age > 40
  files remaining: 1  (-1, 50% pruned)

Total reduction: 6 -> 1 files (83% pruned)

$ echo $?
1

The exit-code contract is precise and stable; see the table in What delta-explain guarantees.

Statistics are resolved through the kernel's log replay, checkpoint Parquet included, so --assert-stats flags a file only when its add action genuinely carries no statistics: long-lived tables whose older commits have been consolidated into a checkpoint do not produce false positives.

Calibrating the threshold

The --min-pruning threshold is per-invocation, applied to the current predicate against the current snapshot. Calibrate it against a baseline pruning percentage in dev (set the gate a few points below it); a flat threshold across heterogeneous partitions will misfire. Note also that 100% pruning can signal a broken or unexpectedly empty predicate, so pair --min-pruning with a sanity check on final_files > 0 when the workload is expected to read data.

Predicate parity

The pruning percentage delta-explain reports reflects the predicate you pass to -w. If the runtime query wraps a column in LOWER, CAST, or a UDF, the engine may prune less than the gate suggests. Use a CI predicate that is semantically equivalent to the runtime predicate and explicitly track that equivalence: a gate on country = 'DE' does not automatically validate a production query using LOWER(country) = 'de'.

In a pipeline (JSON)

delta-explain ./table -w "..." --min-pruning 80 --format json \
  | jq -e '.result == "pass"'

stdout is always a complete report or empty, so a downstream jq never parses a partial document.

GitHub Action

A composite action wraps the CLI with matching inputs. Pin the release tag:

- uses: cdelmonte-zg/delta-explain@v0.7.0
  with:
    table: s3://lake/events
    where: "region = 'eu'"
    min-pruning: "80"

Docker in a pipeline

The same gate without the composite action, from any CI system that can run a container:

- name: Verify pruning after ETL
  run: |
    docker run --rm \
      -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_DEFAULT_REGION \
      ghcr.io/cdelmonte-zg/delta-explain:0.7.0 \
      --env-creds s3://warehouse/events \
      -w "date = '2024-01-15'" \
      --min-pruning 90 --assert-stats --format json

Attach a report artifact

Generate a verbose JSON report and render it with the report viewer into a self-contained report.html, uploaded as a run artifact, so a reviewer of a failed gate sees which phase did not prune and which files survived, instead of an exit code.