Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 44 additions & 11 deletions .github/actions/setup-rust/action.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
name: Setup Rust
description: Install Rust toolchain from rust-toolchain.toml and cache cargo artifacts
description: Install the pinned Rust toolchain, wire sccache as a shared compiler cache, and cache cargo artifacts.

inputs:
toolchain:
description: 'Rust toolchain to install (e.g. "1.93", "stable", "nightly").'
required: false
default: "1.93"
components:
description: Rust components to install (comma-separated)
description: Rust components to install (comma-separated).
required: false
default: ""
targets:
description: Rust targets to install (comma-separated).
required: false
default: ""
cache:
description: 'Cache cargo deps + target with Swatinem/rust-cache. Set "false" for jobs whose build dir is not the workspace target (they keep their own cache).'
required: false
default: "true"
cache-shared-key:
description: Swatinem/rust-cache shared-key. Set the same value on two jobs to share one dependency cache; empty keeps the cache per-job.
required: false
default: ""

Expand All @@ -12,14 +28,31 @@ runs:
steps:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.93"
toolchain: ${{ inputs.toolchain }}
components: ${{ inputs.components }}
- uses: actions/cache@v4
targets: ${{ inputs.targets }}

# Content-addressed compiler cache shared across every job and runner: a crate
# compiled once (in any job) is reused everywhere its inputs match. This is what
# lets the parallel fmt/clippy/test/build jobs stop recompiling the same
# dependency graph — the per-job target cache below cannot cross job boundaries.
- uses: mozilla-actions/sccache-action@v0.0.9

- name: Wire sccache as the rustc wrapper
shell: bash
run: |
{
echo "RUSTC_WRAPPER=sccache"
echo "SCCACHE_GHA_ENABLED=true"
echo "CARGO_INCREMENTAL=0"
} >> "$GITHUB_ENV"

# Restores a warm ~/.cargo (registry + git) and target/ for repeat runs of the
# SAME job, caching dependencies only (not the fast-changing workspace crates)
# and pruning stale artifacts so the cache does not grow unbounded. Complements
# sccache, which is what shares compiled crates ACROSS jobs.
- uses: Swatinem/rust-cache@v2
if: inputs.cache == 'true'
with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
shared-key: ${{ inputs.cache-shared-key }}
cache-on-failure: "true"
205 changes: 111 additions & 94 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ on:
permissions:
contents: read

concurrency:
# Cancel superseded in-progress runs on the same PR to save runner minutes;
# never cancel a main-branch run (each pushed commit must be fully verified).
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -D warnings
Expand Down Expand Up @@ -49,17 +55,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: ./.github/actions/setup-rust
with:
toolchain: stable
components: clippy
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-clippy-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-clippy-
# `fips`/`cnsa` are mutually exclusive (RT-012 compile_error! in
# auths-crypto/src/provider.rs), so --all-features can't compile. Lint the
# bulk workspace minus the five dual-provider crypto crates, then lint those
Expand All @@ -77,17 +76,10 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: dtolnay/rust-toolchain@stable
- uses: ./.github/actions/setup-rust
with:
toolchain: stable
components: rustfmt, clippy
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-precommit-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-precommit-
# Run the same hooks developers run locally, so a commit that passes local
# hooks cannot fail CI on format/lint/hygiene drift. The workspace
# cargo-fmt and cargo-clippy hooks run byte-identical commands in the
Expand Down Expand Up @@ -124,24 +116,49 @@ jobs:
- name: Crypto primitive inventory is current
run: python3 scripts/check_primitive_inventory.py

build-cli:
name: Build CLI binaries (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-rust
# Build the debug binaries once and share them as an artifact so the smoke
# and e2e jobs run against a prebuilt CLI instead of each recompiling it.
# sccache already dedupes the compiles across jobs; the artifact additionally
# lets those downstream jobs drop the Rust toolchain entirely.
- name: Build auths CLI + MCP gateway
run: cargo build --package auths-cli --package auths-mcp-gateway
- name: Stage binaries
run: |
mkdir -p cli-bins
cp target/debug/auths target/debug/auths-sign target/debug/auths-verify target/debug/auths-mcp-gateway cli-bins/
- name: Upload CLI binaries
uses: actions/upload-artifact@v4
with:
name: cli-bins-${{ matrix.os }}
path: cli-bins/

smoke:
name: Golden-path smoke test
needs: build-cli
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: actions/cache@v4
- name: Download CLI binaries
uses: actions/download-artifact@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-smoke-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-smoke-
- name: Build CLI
run: cargo build -p auths-cli
name: cli-bins-ubuntu-latest
path: cli-bins
- name: Make binaries executable
run: chmod +x cli-bins/*
- name: Run golden-path smoke test
run: python3 docs/smoketests/end_to_end.py
env:
AUTHS_BIN: ${{ github.workspace }}/cli-bins/auths
- name: Upload smoke results
if: always()
uses: actions/upload-artifact@v4
Expand All @@ -154,15 +171,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: actions/cache@v4
- uses: ./.github/actions/setup-rust
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-schemas-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-schemas-
toolchain: stable
- name: Regenerate schemas and check for drift
run: |
cargo run -p xtask -- generate-schemas
Expand All @@ -186,16 +197,9 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: actions/cache@v4
- uses: ./.github/actions/setup-rust
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-test-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-test-
toolchain: stable

- name: Install nextest
uses: taiki-e/install-action@nextest
Expand Down Expand Up @@ -236,9 +240,12 @@ jobs:
# dual-provider crypto crates, then run those five under FIPS (the provider
# this job has always exercised — aws-lc-rs needs the Go/CMake toolchain
# installed above).
# postgres_integration is excluded here — it needs a live Postgres and runs
# in the dedicated `postgres-tests` job. Without a server it would spend the
# sqlx acquire_timeout (30s) per test retrying a dead socket, then skip.
- name: Run tests (Ubuntu — all features, crypto crates excluded)
if: matrix.os == 'ubuntu-latest'
run: cargo nextest run --workspace --all-features --no-fail-fast --exclude auths-crypto --exclude auths-core --exclude auths-keri --exclude auths-pairing-protocol --exclude auths-pairing-daemon
run: cargo nextest run --workspace --all-features --no-fail-fast --exclude auths-crypto --exclude auths-core --exclude auths-keri --exclude auths-pairing-protocol --exclude auths-pairing-daemon -E 'not binary(postgres_integration)'
- name: Run tests (Ubuntu — crypto crates under FIPS)
if: matrix.os == 'ubuntu-latest'
run: cargo nextest run -p auths-crypto -p auths-core -p auths-keri -p auths-pairing-protocol -p auths-pairing-daemon --features fips --no-fail-fast
Expand All @@ -257,6 +264,40 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: cargo audit

postgres-tests:
name: Postgres integration tests
needs: [fmt, clippy]
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
# The harness reads these first (overriding its passwordless localhost
# default): the admin URL provisions auths_registry_test, the test URL
# connects to it. Service containers are Linux-only, so these tests get
# their own ubuntu job rather than the cross-OS matrix — the macOS test leg
# never enables backend-postgres, so it does not run them anyway.
AUTHS_TEST_ADMIN_DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/postgres
AUTHS_TEST_DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/auths_registry_test
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-rust
- name: Install nextest
uses: taiki-e/install-action@nextest
- name: Run Postgres integration tests
run: cargo nextest run -p auths-storage --features backend-postgres -E 'binary(postgres_integration)'

# capsec-audit:
# name: Capability Audit
# runs-on: ubuntu-latest
Expand Down Expand Up @@ -291,15 +332,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: actions/cache@v4
- uses: ./.github/actions/setup-rust
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-pq-hybrid-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-pq-hybrid-
toolchain: stable
- name: Install nextest
uses: taiki-e/install-action@nextest
# fn-129.T10: exercise the experimental `pq-hybrid` feature. The
Expand All @@ -317,32 +352,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.93
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-msrv-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-msrv-
- uses: ./.github/actions/setup-rust
- run: cargo check --workspace
wasm:
name: WASM build (auths-verifier)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: ./.github/actions/setup-rust
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-wasm-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-wasm-
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Build WASM with wasm-pack
Expand Down Expand Up @@ -375,7 +395,13 @@ jobs:
targets: fuzz_cesr_import fuzz_parse_cesr fuzz_validate_kel fuzz_receipt_couples fuzz_attachment_parse
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
# cache: false — the fuzz build dir is ${{ matrix.dir }}/target, not the
# workspace target Swatinem manages, so this job keeps its own matrix-keyed
# cache below and only takes the toolchain + shared sccache from the composite.
- uses: ./.github/actions/setup-rust
with:
toolchain: nightly
cache: "false"
- uses: actions/cache@v4
with:
path: |
Expand Down Expand Up @@ -405,15 +431,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.93
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-conformance-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-conformance-
- uses: ./.github/actions/setup-rust
- uses: astral-sh/setup-uv@v4
# keripy's crypto (pysodium) loads libsodium via ctypes at runtime.
- name: Install libsodium (keripy runtime dependency)
Expand Down Expand Up @@ -447,27 +465,26 @@ jobs:

e2e-tests:
name: E2E Tests (${{ matrix.os }})
needs: [test]
needs: [test, build-cli]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.93
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-e2e-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-e2e-
- uses: astral-sh/setup-uv@v4

- name: Build auths binaries
run: cargo build --package auths-cli --package auths-mcp-gateway
# Consume the prebuilt CLI + gateway from build-cli instead of recompiling.
# Restoring them into target/debug keeps the AUTHS_*_BIN paths below and the
# harness's target/debug fallback (for auths-mcp-gateway) unchanged.
- name: Download auths binaries
uses: actions/download-artifact@v4
with:
name: cli-bins-${{ matrix.os }}
path: target/debug
- name: Make binaries executable
run: chmod +x target/debug/auths target/debug/auths-sign target/debug/auths-verify target/debug/auths-mcp-gateway

- name: Configure git
run: |
Expand Down
Loading
Loading