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
79 changes: 66 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,36 @@ on:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

# Cancel superseded runs on the same ref so a fresh push doesn't queue
# behind its own stale jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least privilege: CI only reads the repo. Jobs that need more request it.
permissions:
contents: read

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUSTFLAGS: "-D warnings"

# Third-party actions are pinned to commit SHAs (version in the trailing
# comment). Bump the SHA and the comment together; never use a mutable tag.
jobs:
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# `toolchain` must match rust-toolchain.toml / Cargo.toml rust-version (Q10);
# this pinned action requires the input explicitly. Keep the three in sync.
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.95.0"
components: rustfmt
- run: cargo fmt --all --check

Expand All @@ -29,11 +46,12 @@ jobs:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.95.0" # keep in lockstep with rust-toolchain.toml (Q10)
components: clippy
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2.9.1
- run: cargo clippy --workspace --all-targets -- -D warnings

test:
Expand All @@ -44,25 +62,60 @@ jobs:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@nextest
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.95.0" # keep in lockstep with rust-toolchain.toml (Q10)
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2.9.1
- uses: taiki-e/install-action@d9be7d8cda89035c9c843f78bd44d4f72d8403d4 # v2.79.7
with:
tool: nextest
- run: cargo nextest run --workspace

deny:
name: cargo-deny
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: EmbarkStudios/cargo-deny-action@v2
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: taiki-e/install-action@d9be7d8cda89035c9c843f78bd44d4f72d8403d4 # v2.79.7
with:
tool: cargo-deny
- run: cargo deny check

actionlint:
name: actionlint
runs-on: ubuntu-latest
# release.yml is generated by cargo-dist and trips shellcheck info/style
# notes (SC2086/SC2129) we don't own. Drop those severities so actionlint
# still catches real warnings/errors in our own workflows.
env:
SHELLCHECK_OPTS: --severity=warning
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install actionlint
# taiki-e/install-action does not ship actionlint and the crate has
# no prebuilt binaries, so we use the upstream downloader — pinned to
# actionlint's v1.7.7 commit and verified by sha256 before running, so
# this is never an unverified `curl | bash`.
id: install
env:
ACTIONLINT_SHA: 03d0035246f3e81f36aed592ffb4bebf33a03106 # v1.7.7
DOWNLOADER_SHA256: 221d1d16c03e4e4fcd867de34104e8d479bdce20ccdfa553b9a5c0dc29bf6af2
run: |
curl -fsSL -o download-actionlint.bash \
"https://raw.githubusercontent.com/rhysd/actionlint/${ACTIONLINT_SHA}/scripts/download-actionlint.bash"
echo "${DOWNLOADER_SHA256} download-actionlint.bash" | sha256sum --check --status
bash download-actionlint.bash 1.7.7
echo "path=$(pwd)/actionlint" >> "$GITHUB_OUTPUT"
- name: Run actionlint
run: ${{ steps.install.outputs.path }} -color

markdown:
name: markdownlint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: DavidAnson/markdownlint-cli2-action@v23
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd # v23
with:
globs: '**/*.md'
config: '.markdownlint-cli2.jsonc'
53 changes: 53 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CodeQL

# Whole-program static analysis for the Rust workspace. CodeQL builds the
# project, extracts a database, and runs the `security-and-quality` suite;
# findings land in the Security tab. Complements cargo-deny (CVE-driven,
# dependency-side) and Clippy (in-tree style + simple soundness) with taint
# tracking and cross-function patterns those cannot see.

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Weekly: catches drift in the query packs themselves (new queries may
# flag code already on main).
- cron: '0 7 * * 1'
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
analyze:
name: Analyze (Rust)
# No path gate: SAST covers every commit on the default branch.
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # upload SARIF to code-scanning
actions: read # required for private repos; harmless on public
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# toolchain pinned to match rust-toolchain.toml / Cargo.toml (Q10).
- uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # master
with:
toolchain: "1.95.0"
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2.9.1
- name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
languages: rust
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
- name: Perform analysis
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
category: "/language:rust"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# personal notes (not part of the project)
/.personal/

# generated review decks — keep the Typst source, not the rendered PDF
/docs/reviews/*.pdf

# Claude Code local (per-machine) settings — never shared. The shared
# .claude/settings.json may be tracked; the *.local.json overlay is not.
.claude/settings.local.json
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ exists). Do not relax them locally.

## Conventions

- Coding standards (Tidy First, CUPID & YAGNI, TDD + Reflect, Clean Code) live
in [`CODING_STANDARDS.md`](CODING_STANDARDS.md). This file (AGENTS.md) takes
precedence where they collide.
- Markdown prose: 80-col wrap (tables / code blocks exempt, see
`.markdownlint-cli2.jsonc`).
- Commit messages: no "Claude" signature (per global user instruction).
Expand Down
Loading
Loading