CI integration
attest verify is built to gate CI and agent loops: it exits non-zero when a commit lacks the
trust a policy demands. This guide covers running it on macOS and Linux, the bundled attest-verify
composite action, the augur to attest trust pipeline, and exporting an audit trail for compliance.
Platform.
attestsupports macOS and Linux. The composite action runs on any runner with a Swift 6 toolchain (macos-latest, or a Linuxswift:6.0container). Windows is out of scope.
Running the binary directly
The simplest integration is to build attest and run verify against your range:
jobs:
trust:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # need history for the range
- run: git fetch origin "refs/notes/*:refs/notes/*" # pull attestation notes
- run: swift build -c release
- run: .build/release/attest verify --range origin/main..HEAD --policy .attest.json
Two details matter:
- Fetch the notes. Attestations live in
refs/notes/attest. They are not fetched by a plaincheckout, so pull them explicitly withgit fetch origin "refs/notes/*:refs/notes/*"(and push them on the producing side withgit push origin "refs/notes/*"). - Enough history. A range like
origin/main..HEADneeds the commits on both sides, so setfetch-depth: 0(or a depth large enough for the PR).
The attest-verify action
The repository ships a GitHub Action (action.yml) you can drop into any repo. It installs a
prebuilt attest for the runner (macOS universal or Linux x86_64) from the matching release, then
runs attest verify against your checkout — no Swift toolchain required. On other platforms it
falls back to building attest from its own source:
jobs:
trust:
runs-on: ubuntu-latest # or macos-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # range needs history
- uses: CorvidLabs/attest@v0 # pin to the major tag, not @main
with:
range: origin/main..HEAD # default
policy: .attest.json # default
working-directory: . # default
| Input | Default | Description |
|---|---|---|
range | origin/main..HEAD | git range to verify (needs full history). |
policy | .attest.json | policy file path, relative to working-directory. |
working-directory | . | directory to run attest verify in. |
version | (action ref) | attest release to install (v0.3.0 or latest); defaults to the pinned tag, else latest. |
The single output is binary (path to the attest used); the gate’s contract is the exit
code. A policy violation propagates attest’s non-zero exit and fails the job. Prebuilt binaries
cover GitHub-hosted macOS and Linux x86_64 runners; other runners need a Swift toolchain.
Honest scope. The action builds
attestfrom its own checkout withswift build -c release. Cross-repo packaging (shipping a prebuilt binary and installing it into other repos without a Swift toolchain) is a deferred later step.
The augur → attest trust pipeline
augur scores diff risk and emits a verdict (proceed /
review / block) with a risk score. That verdict is ephemeral; attest makes it durable. They
compose over a pipe; attest never links augur:
# An agent scores the diff, records the verdict as an attestation, then gates on the policy:
augur check --range main..HEAD --json \
| attest sign --commit HEAD --reviewer agent:claude --from-augur - --tests-passed
attest verify --commit HEAD || echo "trust policy not satisfied, escalating to a human"
--from-augur copies augur’s verdict and maps its riskScore (0…100) to confidence = 1 − riskScore/100. In an agent loop this turns a risk score into a recorded, optionally-signed trust
artifact that the next step, or a human, can verify. A typical loop:
augur check --jsonscores the change.attest sign --from-augur -records the verdict + confidence as an attestation (signed if the agent holds a key).attest verifygates: areview/blockverdict under a policy withrequireHumanApprovalWhenVerdictAtLeastexits non-zero until a human files a separate--human-approvedsign-off, so the agent escalates instead of merging blind.
Pair the policy with maxAgeDays (see Policy reference) so a stale verdict
from a previous run cannot keep clearing today’s commit.
Exporting an audit trail for compliance
attest export produces a single, stable JSON document covering the complete provenance trail
across a range: every commit, every attestation, each record’s cryptographic verification status,
and (with --policy) a per-commit pass/fail. It is deterministic (sorted keys; commits
oldest-first), so it diffs cleanly and is suitable for archival.
A natural CI step archives the trust trail alongside the build artifacts:
- run: |
.build/release/attest export \
--range origin/main..HEAD \
--policy .attest.json \
--no-pretty > audit.json
- uses: actions/upload-artifact@v4
with:
name: attest-audit
path: audit.json
export folds in verify’s policy verdict and the per-record signature checks, across the full
range, in one machine-stable file: the durable record an auditor keeps. See
CLI reference for the document shape and
examples/05-audit-export.sh
for an end-to-end run.