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
198 changes: 118 additions & 80 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,60 @@ name: ci

on:
pull_request:
branches: [main]
push:
branches: [main]
# There was no way to ask this repository for a run, and on 2026-08-26 that
# mattered: GitHub dropped push events for about two hours, and six of the
# seven trees were left with no completed `ci` on the `main` they had just
# merged. The code was proven -- the same contexts were green on the pull
# request minutes earlier -- but nothing on `main` said so, and the only way
# to ask again was to push a commit that changed nothing.
#
# A repository whose proof can only be requested by changing it is a
# repository that invites empty commits. The monorepo has carried this
# trigger since its gate was built; the rendered trees did not, for no reason
# anyone chose.
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
group: ci-${{ github.event.pull_request.number || github.ref }}
# Obsolete pull-request heads are cancelled; a running main validation always completes.
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
rust:
name: rust
permissions:
contents: read
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/rust-ci.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
with:
toolchain: '1.98.1'
# The three-OS matrix is the evidence ADR-0113 asks for, and standard
# hosted runners are free with unlimited minutes on a public repository.
test_matrix_os: '["ubuntu-latest", "macos-latest", "windows-latest"]'
build_command: |
python tools/with_libclang.py cargo build --locked --all-targets
python tools/with_libclang.py python tools/build_crates_io.py --self-check
test_command: 'python tools/with_libclang.py cargo test --locked --all-targets'
fmt_command: 'cargo fmt --all --check'
clippy_command: 'python tools/with_libclang.py cargo clippy --locked --all-targets -- -D warnings'
msrv_toolchain: '1.89'
msrv_command: 'python tools/with_libclang.py cargo check --locked --all-targets'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Select the pinned Rust toolchain
run: |
rustup toolchain install 1.98.1 --profile minimal --component rustfmt,clippy
echo RUSTUP_TOOLCHAIN=1.98.1 >> "$GITHUB_ENV"
- uses: NDDev-Technocracy-Standarts/std-0004-ci-cd-workflows/.github/actions/hosted-cache@ab62f45b2a3067e5a7425d703f7fd07f1618b72c # nddev-cicd-v0.6.14
with:
ecosystems: cargo
- name: Format, Clippy, build and test
run: |
cargo fmt --all --check
python tools/with_libclang.py cargo clippy --locked --all-targets -- -D warnings
python tools/with_libclang.py cargo build --locked --all-targets
python tools/with_libclang.py python tools/build_crates_io.py --self-check
python tools/with_libclang.py cargo test --locked --all-targets

supply-chain:
name: supply-chain
permissions:
contents: read
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/rust-supply-chain.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
with:
enable_deny: true
enable_audit: true
# The pinned reusable job ignores an unsupported argument and its exit.
enable_machete: false

unused-dependencies:
name: unused-dependencies
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: taiki-e/install-action@94c31af3204a9f15ab40b35ad084410b905bbc73 # v2.87.17
- name: Select the pinned Rust toolchain
run: |
rustup toolchain install 1.98.1 --profile minimal
echo RUSTUP_TOOLCHAIN=1.98.1 >> "$GITHUB_ENV"
- uses: NDDev-Technocracy-Standarts/std-0004-ci-cd-workflows/.github/actions/tools@ab62f45b2a3067e5a7425d703f7fd07f1618b72c # nddev-cicd-v0.6.14
with:
tool: cargo-machete@0.9.2
- name: Refuse unused dependencies and tool failures
run: cargo-machete

actionlint:
name: actionlint
permissions:
contents: read
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/actionlint.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046

pr-hygiene:
name: pr-hygiene
if: github.event_name == 'pull_request'
permissions:
contents: read
# The labeler applies labels and the stale bot closes threads. Their jobs
# declare these statically, so the grant is required even when the toggle
# that would use them is off.
issues: write # the stale bot closes threads
pull-requests: write # the labeler applies labels
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/pr-hygiene.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046

capability: rust
- name: cargo-deny, cargo-audit and unused dependencies
run: |
cargo deny --all-features check bans licenses advisories sources
cargo audit
cargo-machete

boundary:
name: boundary (${{ matrix.os }})
Expand All @@ -104,7 +70,8 @@ jobs:
# `dumpbin` from a Visual Studio environment that is not on `PATH` by
# default. A step that sometimes finds its tool is worse than a gap
# nobody was told about, so the gap is written down here instead.
os: [ubuntu-latest, macos-latest]
# macOS joins on main; pull requests keep the Linux path.
os: ${{ fromJSON(github.event_name == 'pull_request' && '["ubuntu-24.04"]' || '["ubuntu-24.04","macos-26"]') }}
runs-on: ${{ matrix.os }}
timeout-minutes: 20
defaults:
Expand All @@ -116,15 +83,11 @@ jobs:
with:
persist-credentials: false

- name: Set up Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@ecabd13d1c56bd1345c230e542e9144811ad706f # v2.0.0
with:
toolchain: '1.98.1'
# The same reason the release job gives. This job's whole subject is
# the bytes that come out of the build, so restoring someone else's
# `target/` and then reading its import table would answer a question
# about a cache rather than about this commit.
cache: false
# No build cache here: this job reads the import table of bytes built by this commit.
- name: Select the pinned Rust toolchain
run: |
rustup toolchain install 1.98.1 --profile minimal
echo RUSTUP_TOOLCHAIN=1.98.1 >> "$GITHUB_ENV"

- run: python tools/with_libclang.py cargo build --locked --release

Expand Down Expand Up @@ -226,3 +189,78 @@ jobs:
exit 1
fi
echo "the import table agrees with the declaration"

platforms:
runs-on: ${{ matrix.os }}
timeout-minutes: 40
if: ${{ github.event_name != 'pull_request' }}
strategy:
fail-fast: false
matrix:
os: [macos-26, windows-2025]
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Select the pinned Rust toolchain
run: |
rustup toolchain install 1.98.1 --profile minimal
echo RUSTUP_TOOLCHAIN=1.98.1 >> "$GITHUB_ENV"
- name: Tests on the other supported platforms
run: python tools/with_libclang.py cargo test --locked --all-targets

msrv:
runs-on: ubuntu-24.04
timeout-minutes: 20
if: ${{ github.event_name != 'pull_request' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Select the pinned Rust toolchain
run: |
rustup toolchain install 1.89 --profile minimal
echo RUSTUP_TOOLCHAIN=1.89 >> "$GITHUB_ENV"
- name: Minimum supported Rust version
run: python tools/with_libclang.py cargo check --locked --all-targets

workflows:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
fetch-depth: 0
- uses: NDDev-Technocracy-Standarts/std-0004-ci-cd-workflows/.github/actions/tools@ab62f45b2a3067e5a7425d703f7fd07f1618b72c # nddev-cicd-v0.6.14
with:
capability: security
- name: Lint and audit workflows
run: |
actionlint
zizmor --offline --no-progress .github
- name: Scan new pull request commits, or the full history on main
env:
BASE: ${{ github.event.pull_request.base.sha }}
HEAD: ${{ github.event.pull_request.head.sha }}
run: |
if [ -n "$BASE" ]; then
gitleaks git --no-banner --redact --log-opts="$BASE..$HEAD" .
else
gitleaks git --no-banner --redact .
fi

gate:
needs: [rust, supply-chain, boundary, platforms, msrv, workflows]
if: ${{ !cancelled() }}
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: NDDev-Technocracy-Standarts/std-0004-ci-cd-workflows/.github/actions/gate@ab62f45b2a3067e5a7425d703f7fd07f1618b72c # nddev-cicd-v0.6.14
with:
needs: ${{ toJSON(needs) }}
expected: >-
{"rust":"success","supply-chain":"success","boundary":"success","platforms":"${{ github.event_name == 'pull_request' && 'skipped' || 'success' }}","msrv":"${{ github.event_name == 'pull_request' && 'skipped' || 'success' }}","workflows":"success"}
112 changes: 60 additions & 52 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,82 @@ name: security

on:
pull_request:
branches: [main]
push:
branches: [main]
schedule:
# Weekly, so an advisory published after the last push is still seen.
- cron: '17 4 * * 1'
# Same reason as `ci`: an advisory worth re-checking now, or a scheduled run
# that never started, should not require a commit to ask about.
workflow_dispatch:

permissions:
contents: read

concurrency:
group: security-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
group: security-${{ github.event.pull_request.number || github.ref }}
# Obsolete pull-request heads are cancelled; a running main validation always completes.
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
codeql:
name: codeql
permissions:
actions: read # CodeQL reads the workflow definitions it analyses
contents: read
security-events: write # CodeQL publishes its findings to code scanning
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/public-codeql.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
with:
languages: '["rust", "actions"]'
queries: security-and-quality

dependency-review:
name: dependency-review
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
contents: read
pull-requests: write # writes the review it produces
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/public-dependency-review.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
with:
fail_on_severity: moderate
security-events: write
strategy:
fail-fast: false
matrix:
language: [rust, actions]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
languages: ${{ matrix.language }}
build-mode: none
queries: security-and-quality
- uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
category: /language:${{ matrix.language }}

scorecard:
name: scorecard
if: github.event_name != 'pull_request'
if: ${{ github.event_name != 'pull_request' }}
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
# A called workflow cannot request more than its caller granted, and the
# run fails at startup rather than mid-job when it tries. Scorecard reads
# workflow definitions, so actions: read is part of the set, not an extra.
actions: read # Scorecard reads workflow definitions
contents: read
id-token: write # mints the OIDC token Scorecard's publication is signed with
security-events: write # Scorecard publishes its findings to code scanning
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/public-scorecard.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
security-events: write
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e # v2.5.0
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
sarif_file: results.sarif
category: scorecard

osv:
name: osv
permissions:
contents: read
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/osv-scan.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046

zizmor:
name: zizmor
permissions:
actions: read # the SARIF upload reads this run to attach its results
contents: read
security-events: write # zizmor publishes its findings to code scanning
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/zizmor-sarif.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
dependency-review:
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
fail-on-severity: moderate

secret-scan:
name: secret-scan
permissions:
contents: read
uses: NDDev-Technocracy-Archive/ci-workflows-20261014/.github/workflows/secret-scan.yml@93eeb2a65e98a29e9dbff7909f67c6419abff046 # commit:93eeb2a65e98a29e9dbff7909f67c6419abff046
osv:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: NDDev-Technocracy-Standarts/std-0004-ci-cd-workflows/.github/actions/tools@ab62f45b2a3067e5a7425d703f7fd07f1618b72c # nddev-cicd-v0.6.14
with:
capability: security
- name: OSV-Scanner over the repository lockfiles
run: osv-scanner scan source --recursive .