Skip to content

fix: stop rereading files in content digest #153

fix: stop rereading files in content digest

fix: stop rereading files in content digest #153

Workflow file for this run

# ──────────────────────────────────────────────────────────────────────
# CI — runs on every PR, push to main, and weekly on a schedule.
#
# PURPOSE:
# Gate merges behind automated checks: lint, test, and security
# scanning. This prevents regressions and catches vulnerabilities
# before code reaches the release workflow.
#
# JOBS (run in parallel where possible):
# changes — detects which files changed (dorny/paths-filter)
# check — fmt → clippy → test (skipped for docs-only changes)
# supply-chain — cargo-deny + cargo-audit (dep changes OR schedule)
# secrets — gitleaks (always runs — any file can contain secrets)
# unsafe-audit — cargo-geiger (dep changes OR schedule)
#
# OPTIMIZATIONS:
# • Path filtering: dorny/paths-filter skips expensive Rust jobs when
# only docs/scripts/config changed (saves ~35s+ per docs-only PR).
# • Concurrency: cancel-in-progress prevents wasted runs when you
# push again quickly or when push+PR events both fire.
# • Fail-fast: steps in `check` ordered cheapest-first (fmt → clippy
# → test) so broken PRs fail in seconds, not minutes.
#
# SUPPLY CHAIN SECURITY:
# • All Actions pinned to full commit SHAs (see release.yml header).
# • `cargo deny` checks licenses and advisories on every PR.
# • `cargo audit` catches known CVEs in the dependency tree.
# • `gitleaks` scans for accidentally committed secrets.
# • `cargo-geiger` audits unsafe code surface area.
# • Minimal permissions — only `contents: read` for checkout.
# • Audit tool versions are pinned and verified via SHA-256 checksums
# before execution — no silent upgrades from upstream `latest`.
# • Scheduled weekly run ensures new advisories are caught even when
# no dependency files changed.
#
# RUNNERS:
# • Blacksmith runners for Linux (2× faster, colocated cache).
# • Swatinem/rust-cache automatically uses Blacksmith's cache backend
# when running on Blacksmith runners — no special config needed.
# ──────────────────────────────────────────────────────────────────────
name: CI
on:
pull_request:
push:
branches: [main]
schedule:
# Weekly on Monday at 06:00 UTC — catches new advisories even
# when no dependency files have changed since the last PR.
- cron: '0 6 * * 1'
# Cancel in-progress runs when a new push arrives on the same branch.
# This prevents wasted compute when you push rapid fixes, and deduplicates
# the push + pull_request events that GitHub fires simultaneously.
# On main/schedule, use run_id so runs don't cancel each other.
concurrency:
group: ci-${{ (github.event_name == 'push' || github.event_name == 'schedule') && github.run_id || github.head_ref }}
cancel-in-progress: true
# Least-privilege: CI only needs to read the repo
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
# ── Path Detection ───────────────────────────────────────────────
# Runs in <5s on a minimal runner. Downstream jobs use its outputs
# to skip expensive work when only docs/scripts/config changed.
changes:
name: Detect changes
runs-on: blacksmith-2vcpu-ubuntu-2204
outputs:
rust: ${{ steps.filter.outputs.rust }}
deps: ${{ steps.filter.outputs.deps }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
rust:
- 'crates/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'rust-toolchain.toml'
- 'deny.toml'
- '.github/workflows/**'
deps:
- 'Cargo.toml'
- 'Cargo.lock'
- 'crates/**/Cargo.toml'
- 'deny.toml'
check:
name: Lint & test
needs: changes
if: needs.changes.outputs.rust == 'true'
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
components: clippy, rustfmt
# rust-toolchain.toml overrides action inputs, so ensure
# components are installed. This is a no-op if they're
# already listed in rust-toolchain.toml (belt + suspenders).
- name: Ensure toolchain components
run: rustup component add clippy rustfmt
# Blacksmith intercepts cache calls on its runners — this
# uses the colocated cache automatically, no extra config.
- name: Cache Cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
# ── Fail-fast: cheapest checks first ────────────────────
# ~1s — pure text check, no compilation. Catches formatting
# issues before waiting for a full compile.
- name: Formatting
run: cargo fmt --check
# ~30s — compiles all targets AND lints in a single pass.
# No separate `cargo build` step needed — clippy does both.
# -D warnings ensures zero warnings merge.
- name: Clippy
run: cargo clippy --locked --all-targets -- -D warnings
# ~3s — reuses build artifacts from clippy above, so this
# is essentially just running the test harness.
- name: Test
run: cargo test --locked
# Runs in parallel with check — no dependency between them.
# Uses pre-built binaries (not `cargo install`) to avoid the 60s+
# compile-from-source overhead of building cargo-audit.
supply-chain:
name: Supply chain audit
needs: changes
if: needs.changes.outputs.deps == 'true' || github.event_name == 'schedule'
runs-on: blacksmith-2vcpu-ubuntu-2204
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Download pre-built binaries (~2s each) instead of
# `cargo install` which compiles from source (~60s+).
# Versions are pinned; SHA-256 checksums are verified before
# extraction to detect tampering or download corruption.
- name: Install cargo-deny
run: |
DENY_VERSION="0.19.1"
DENY_SHA256="baa0d618ce06bd1fb352115de47e31acba439c3e639b990dc43429c948364d70"
curl -sSL "https://github.com/EmbarkStudios/cargo-deny/releases/download/${DENY_VERSION}/cargo-deny-${DENY_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
-o cargo-deny.tar.gz
echo "${DENY_SHA256} cargo-deny.tar.gz" | sha256sum --check --strict
tar xzf cargo-deny.tar.gz --strip-components=1 -C /usr/local/bin
rm cargo-deny.tar.gz
cargo-deny --version
# rustsec/rustsec is a monorepo; cargo-audit releases don't
# include a checksums file, so the SHA-256 is embedded here
# (computed from the official release asset at pin time).
- name: Install cargo-audit
run: |
AUDIT_VERSION="0.22.1"
AUDIT_SHA256="c32506f338bdcdaef5a17fb9f33abb6ecf9561324cfd34237fd335f9283a1eab"
curl -sSL "https://github.com/rustsec/rustsec/releases/download/cargo-audit%2Fv${AUDIT_VERSION}/cargo-audit-x86_64-unknown-linux-musl-v${AUDIT_VERSION}.tgz" \
-o cargo-audit.tgz
echo "${AUDIT_SHA256} cargo-audit.tgz" | sha256sum --check --strict
tar xzf cargo-audit.tgz --strip-components=1 -C /usr/local/bin
rm cargo-audit.tgz
cargo-audit --version
# cargo-deny checks: advisories, licenses, bans, sources
- name: cargo deny check
run: cargo deny check
# cargo-audit is a second layer — checks the RustSec advisory DB
- name: cargo audit
run: cargo audit
# ── Secrets Scanning ─────────────────────────────────────────────
# Gitleaks detects hardcoded secrets (API keys, tokens, passwords)
# in the repo history and staged changes. Runs on a minimal runner
# since it's I/O-bound, not CPU-bound. Blocks the build on any
# finding — secrets in the repo are always a hard stop.
secrets:
name: Secrets scan
runs-on: blacksmith-2vcpu-ubuntu-2204
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0 # full history for scanning all commits
- name: Install gitleaks
run: |
GL_VERSION="8.30.1"
GL_SHA256="551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb"
curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GL_VERSION}/gitleaks_${GL_VERSION}_linux_x64.tar.gz" \
-o gitleaks.tar.gz
echo "${GL_SHA256} gitleaks.tar.gz" | sha256sum --check --strict
tar xzf gitleaks.tar.gz -C /usr/local/bin gitleaks
rm gitleaks.tar.gz
gitleaks version
# Scan the full repo history for secrets. On PRs, you could
# scope to just the diff with --log-opts="origin/main..HEAD"
# but scanning everything catches pre-existing issues too.
- name: Scan for secrets
run: gitleaks detect --source . --config .gitleaks.toml --verbose
# ── Unsafe Code Audit ────────────────────────────────────────────
# cargo-geiger counts `unsafe` usage across the entire dependency
# tree. This is informational (non-blocking) — many safe crates
# use unsafe internally (e.g. ring for crypto, libc for FFI).
# The value is visibility: track unsafe surface area over time
# and catch unexpected new unsafe dependencies in PRs.
unsafe-audit:
name: Unsafe code audit
needs: changes
if: needs.changes.outputs.deps == 'true' || github.event_name == 'schedule'
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- name: Ensure toolchain components
run: rustup component add clippy rustfmt
# Blacksmith caches the compiled cargo-geiger binary after
# the first run — subsequent runs skip the 60s+ compile.
- name: Cache Cargo
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Install cargo-geiger
run: cargo install cargo-geiger --locked
# Non-blocking (|| true) — geiger can exit non-zero if it
# encounters crates it can't analyze. The output itself is
# the valuable part: review it in PR checks to spot new
# unsafe dependencies entering the tree.
- name: Audit unsafe code usage
run: cargo geiger --all-targets --output-format ascii 2>&1 || true