normalize ci is the single entry point for running all normalize checks in CI. It runs all
configured rule engines in sequence, aggregates violations into a unified report, and exits
non-zero if any errors are found.
Add two steps to any CI pipeline:
# 1. Install normalize
curl -fsSL https://rhi.zone/normalize/install.sh | sh
# 2. Run all checks
normalize cinormalize ci exits 0 when there are no errors, exits 1 when errors are found. Warnings
don't fail CI by default — use --strict to make them fail too.
If .normalize/ratchet.json doesn't exist, the ratchet check is a no-op. Repos that
haven't configured ratchet or budget are not penalized.
The command runs three engines in sequence:
Tree-sitter-based pattern rules defined in .scm query files. Checks code patterns like
unwrapped results, bare excepts, hardcoded secrets, and any custom rules you've added.
normalize rules list --type syntax # see which syntax rules are enabledBuilt-in Rust checks that don't fit the .scm model:
- stale-docs: documentation files referencing removed symbols
- check-examples: code examples in docs that no longer parse
- check-refs: cross-file references that point to missing targets
- ratchet: metric regression check against
.normalize/ratchet.jsonbaseline - budget: diff-based budget check against
.normalize/budget.json
Datalog-style rules that reason across the full codebase graph (imports, calls, symbols). Used for cross-file checks like circular dependency detection.
normalize rules list --type fact # see which fact rules are enabledComplete working example with version pinning and binary install:
name: normalize
on:
push:
branches: [main]
pull_request:
jobs:
normalize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install normalize
run: |
curl -fsSL https://rhi.zone/normalize/install.sh | sh
env:
NORMALIZE_VERSION: "0.3.1"
INSTALL_DIR: /usr/local/bin
- name: Run normalize ci
run: normalize ci
# Optional: SARIF upload for inline PR annotations
- name: Generate SARIF
if: always()
run: normalize ci --sarif > normalize.sarif || true
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: normalize.sarif
continue-on-error: trueFor SARIF annotations on PRs, run normalize ci --sarif and upload the output to
GitHub's code scanning API. The --sarif flag outputs SARIF 2.1.0 JSON to stdout.
Generate the SARIF file before uploading it.
- name: Run normalize ci (syntax only)
run: normalize ci --no-native --no-factnormalize:
image: ubuntu:latest
stage: test
before_script:
- apt-get update -qq && apt-get install -y -qq curl
- curl -fsSL https://rhi.zone/normalize/install.sh | sh
script:
- normalize ci
artifacts:
when: always
reports:
codequality: normalize.json
after_script:
- normalize ci --json > normalize.json || trueTo pin the version:
variables:
NORMALIZE_VERSION: "0.3.1"
INSTALL_DIR: /usr/local/binOverride rule severity in .normalize/config.toml:
[rules.rule."rust/unwrap-in-impl"]
severity = "warning" # downgrade from error
[rules.rule."python/bare-except"]
enabled = false # disable entirelynormalize rules enable python/bare-except # enable a rule
normalize rules disable no-todo-comment # disable a rule
normalize rules enable --tag correctness # enable a tag groupTo apply stricter rules only in CI, use the --strict flag:
- run: normalize ci --strict # warnings also fail CIRatchet prevents metric regressions (complexity creep, test ratio decline, etc.). Budget limits how much a metric can change in a single diff.
# Pin current baselines for all Rust files
normalize ratchet add src/ --metric complexity
# Commit the baseline
git add .normalize/ratchet.json
git commit -m "chore: add normalize ratchet baselines"CI then runs normalize ci and catches regressions automatically.
# Accept the new (higher) value as the new baseline
normalize ratchet update src/big_module.rs --metric complexity --force
# Commit the updated baseline alongside your change
git add .normalize/ratchet.json
git commit -m "refactor: increase complexity baseline for big_module"# Limit complexity growth to +10 per PR
normalize budget add src/ --metric complexity --limit 10
git add .normalize/budget.json
git commit -m "chore: add complexity budget"See normalize ratchet --help and normalize budget --help for the full API.
Pin to a specific version for reproducible CI:
# Via install script (fast — downloads a prebuilt binary)
NORMALIZE_VERSION=0.3.1 curl -fsSL https://rhi.zone/normalize/install.sh | sh
# Via cargo (slower — compiles from source)
cargo install normalize --version "0.2.0" --lockedCheck for new versions with:
normalize update --checkIndex not built: Fact rules require the index. Run normalize structure rebuild before
normalize ci, or skip the fact engine with --no-fact if you haven't set up the index yet.
No config file: If .normalize/config.toml doesn't exist, normalize uses built-in defaults.
Run normalize init to generate a config file with commented-out options.
Rules not finding violations: Verify grammars are installed (normalize grammars list).
Syntax rules require the tree-sitter grammar for the target language. If the grammar is missing,
those rules silently produce no results.
SHA256 mismatch on install: The install script downloads SHA256SUMS.txt from the same
release and verifies the archive before installing. A mismatch means the download was corrupted
or the release assets don't match — retry the download. Do not skip verification.