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

Local CI

contrib/ci/local-ci.sh runs the same checks that a GitHub Actions workflow would run, in the same order, without needing a CI account or a push. Use it to catch failures before committing or to reproduce a CI failure locally.

Quick start

# Run the full pipeline
./contrib/ci/local-ci.sh all

# Run only formatting and lint checks
./contrib/ci/local-ci.sh fmt clippy

# List available jobs
./contrib/ci/local-ci.sh --list

Requirements

ToolInstall
cargohttps://rustup.rs/
rustfmtrustup component add rustfmt
clippyrustup component add clippy
mdbookcargo install mdbook (optional, for the doc job)
actionlinthttps://github.com/rhysd/actionlint (optional, for lint-workflows)
yamllintpip install yamllint (optional, fallback for lint-workflows)

The script detects which optional tools are present at startup and skips or degrades gracefully for any that are missing.

Jobs

JobCommandDepends on
buildcargo build --workspace + cargo build --benches
fmtcargo fmt --all -- --check
clippycargo clippy -- -D warningsbuild
doccargo doc --no-deps + mdbook build docs/build
testcargo testbuild
benchcargo build --benches (compile-only)build
lint-workflowsactionlint or yamllint on .github/workflows/*.yml

The bench job only compiles the benchmark binary; it does not run any issuance measurements. Use cargo bench --bench acme_bench directly when you want timing numbers (see Performance).

Dependency graph

When you request a job whose prerequisite has not run yet, the script runs the prerequisite automatically. If the prerequisite fails, the dependent job is skipped rather than attempted:

build ──┬── clippy
        ├── doc
        ├── test
        └── bench

fmt and lint-workflows have no prerequisites and can run independently.

Options

OptionEffect
--no-colorDisable ANSI colour output (also honoured via NO_COLOR=1)
--no-depsSkip prerequisite auto-dispatch — intended for use inside an actual CI system where needs: already serialises the jobs
--listPrint available job names and exit
--help / -hShow usage and exit

Environment variables

VariableEffect
CARGO_TARGET_DIRRedirect Cargo build artefacts to an isolated directory
NO_COLORSet to 1 to disable ANSI colour output

Summary output

After all requested jobs finish the script prints a table:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CI Summary
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  build                PASS  (22s)
  fmt                  PASS  (1s)
  clippy               PASS  (0s)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total time: 23s
All jobs passed.

The script exits with status 0 when all executed jobs pass and 1 if any job fails. Skipped jobs (due to a failed dependency) are shown as SKIP and do not affect the exit status.

Use inside GitHub Actions

When running a single job from within a workflow step, pass --no-deps so the script does not re-run prerequisites that the workflow needs: graph has already enforced:

- name: Clippy
  run: ./contrib/ci/local-ci.sh --no-deps clippy

Without --no-deps, the script would automatically invoke build before clippy, duplicating work that another job already performed.

Example invocations

# Full pipeline
./contrib/ci/local-ci.sh all

# Only the fast checks (no compilation required)
./contrib/ci/local-ci.sh fmt lint-workflows

# Isolated build directory (keeps the main target/ clean)
CARGO_TARGET_DIR=/tmp/akamu-ci ./contrib/ci/local-ci.sh all

# CI-mode: run one job without triggering its prerequisites
./contrib/ci/local-ci.sh --no-deps test

# No colour output (e.g. when piping to a log file)
./contrib/ci/local-ci.sh --no-color all