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
20 changes: 10 additions & 10 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ on:
push:
paths:
- .github/workflows/audit.yml
- '**/Cargo.toml'
- '**/Cargo.lock'
- "**/Cargo.toml"
- "**/Cargo.lock"
pull_request:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
- "**/Cargo.toml"
- "**/Cargo.lock"
schedule:
- cron: '0 6 * * 1' # Monday at 6 AM UTC
- cron: "0 6 * * 1" # Monday at 6 AM UTC
workflow_dispatch:

permissions:
Expand All @@ -21,15 +21,15 @@ jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
with:
cache: true # toolchain/components are specified in rust-toolchain.toml
cache: true # toolchain/components are specified in rust-toolchain.toml

- name: Cache advisory database
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.cargo/advisory-db
key: advisory-db-${{ github.ref_name }}-v1
Expand All @@ -44,7 +44,7 @@ jobs:
cargo audit

- name: Upload audit results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: audit-results
Expand Down
159 changes: 146 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: CI
# cspell:ignore rhysd binstall mktemp sha256sum sha256sums shasum
permissions:
contents: read
concurrency:
Expand All @@ -21,12 +22,17 @@ on:
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
ACTIONLINT_VERSION: "1.7.10"
MARKDOWNLINT_VERSION: "0.47.0"
CSPELL_VERSION: "9.4.0"
SHFMT_VERSION: "3.12.0"
UV_VERSION: "0.9.21"

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false # Continue other jobs if one fails
fail-fast: false # Continue other jobs if one fails
matrix:
os:
- ubuntu-latest
Expand All @@ -41,47 +47,174 @@ jobs:
target: x86_64-pc-windows-msvc

steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
with:
target: ${{ matrix.target }}
cache: true # Built-in caching; toolchain/components are specified in rust-toolchain.toml
cache: true # Built-in caching
# toolchain, components, etc. are specified in rust-toolchain.toml

- name: Install just
if: matrix.os != 'windows-latest'
uses: taiki-e/install-action@bfc291e1e39400b67eda124e4a7b4380e93b3390 # v2.65.0
uses: taiki-e/install-action@4c6723ec9c638cccae824b8957c5085b695c8085 # v2.65.7
with:
tool: just

- name: Install uv (for Python scripts and pytest)
if: matrix.os != 'windows-latest'
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
with:
version: "0.9.17" # Pinned for reproducible CI
version: ${{ env.UV_VERSION }}

- name: Install Node.js (for markdownlint and cspell)
if: matrix.os != 'windows-latest'
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: '20'
node-version: "20"

- name: Install Node.js packages
if: matrix.os != 'windows-latest'
run: |
npm install -g markdownlint-cli cspell
npm install -g markdownlint-cli@${{ env.MARKDOWNLINT_VERSION }} cspell@${{ env.CSPELL_VERSION }}

- name: Install jq (Linux)
- name: Install taplo (for TOML formatting and linting)
if: matrix.os != 'windows-latest'
uses: taiki-e/install-action@4c6723ec9c638cccae824b8957c5085b695c8085 # v2.65.7
with:
tool: taplo-cli

- name: Install actionlint (Linux/macOS)
if: matrix.os != 'windows-latest'
run: |
set -euo pipefail

# actionlint is published as prebuilt binaries (Go), not a Rust crate.
# Install directly from rhysd/actionlint releases to avoid cargo-binstall fallback failures.
# Verify SHA256 checksums from the upstream release for supply-chain hardening.
OS="$(uname -s)"
ARCH="$(uname -m)"

case "$OS" in
Linux) ACTIONLINT_OS="linux" ;;
Darwin) ACTIONLINT_OS="darwin" ;;
*)
echo "Unsupported OS for actionlint: $OS" >&2
exit 1
;;
esac

case "$ARCH" in
x86_64|amd64) ACTIONLINT_ARCH="amd64" ;;
arm64|aarch64) ACTIONLINT_ARCH="arm64" ;;
*)
echo "Unsupported architecture for actionlint: $ARCH" >&2
exit 1
;;
esac

verify_sha256() {
local checksum_file="$1"
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c "$checksum_file"
else
shasum -a 256 -c "$checksum_file"
fi
}

VERSION="${ACTIONLINT_VERSION}"
TARBALL="actionlint_${VERSION}_${ACTIONLINT_OS}_${ACTIONLINT_ARCH}.tar.gz"
CHECKSUMS_FILE="actionlint_${VERSION}_checksums.txt"
BASE_URL="https://github.com/rhysd/actionlint/releases/download/v${VERSION}"

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

curl -fsSL "${BASE_URL}/${TARBALL}" -o "$tmpdir/$TARBALL"
curl -fsSL "${BASE_URL}/${CHECKSUMS_FILE}" -o "$tmpdir/$CHECKSUMS_FILE"

orig_dir="$PWD"
cd "$tmpdir"
awk -v f="$TARBALL" '$NF==f {print; found=1} END {exit found?0:1}' "$CHECKSUMS_FILE" > checksum.txt
verify_sha256 checksum.txt
cd "$orig_dir"

tar -xzf "$tmpdir/$TARBALL" -C "$tmpdir"

actionlint_path="$(find "$tmpdir" -type f -name actionlint | head -n 1)"
if [[ -z "$actionlint_path" ]]; then
echo "actionlint binary not found in $TARBALL" >&2
exit 1
fi

sudo install -m 0755 "$actionlint_path" /usr/local/bin/actionlint

- name: actionlint -version
if: matrix.os != 'windows-latest'
run: actionlint -version

- name: Install additional tools (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
# Install shellcheck, jq, and yamllint
sudo apt-get update
sudo apt-get install -y jq
sudo apt-get install -y shellcheck jq yamllint

# Install shfmt (pinned for CI consistency)
SHFMT_ASSET="shfmt_v${SHFMT_VERSION}_linux_amd64"
SHFMT_BASE_URL="https://github.com/mvdan/sh/releases/download/v${SHFMT_VERSION}"

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

curl -fsSL \
"${SHFMT_BASE_URL}/${SHFMT_ASSET}" \
-o "$tmpdir/${SHFMT_ASSET}"
curl -fsSL \
"${SHFMT_BASE_URL}/sha256sums.txt" \
-o "$tmpdir/sha256sums.txt"

(
cd "$tmpdir"
awk -v f="${SHFMT_ASSET}" '$NF==f {print; found=1} END {exit found?0:1}' sha256sums.txt > checksum.txt
sha256sum -c checksum.txt
)

- name: Install jq (macOS)
sudo install -m 0755 "$tmpdir/${SHFMT_ASSET}" /usr/local/bin/shfmt

- name: Install additional tools (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install jq
# Install shellcheck, jq, and yamllint via Homebrew
brew install shellcheck jq yamllint

# Install shfmt (pinned for CI consistency with Linux)
SHFMT_ARCH="amd64"
if [[ "$(uname -m)" == "arm64" ]]; then
SHFMT_ARCH="arm64"
fi

SHFMT_ASSET="shfmt_v${SHFMT_VERSION}_darwin_${SHFMT_ARCH}"
SHFMT_BASE_URL="https://github.com/mvdan/sh/releases/download/v${SHFMT_VERSION}"

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

curl -fsSL \
"${SHFMT_BASE_URL}/${SHFMT_ASSET}" \
-o "$tmpdir/${SHFMT_ASSET}"
curl -fsSL \
"${SHFMT_BASE_URL}/sha256sums.txt" \
-o "$tmpdir/sha256sums.txt"

(
cd "$tmpdir"
awk -v f="${SHFMT_ASSET}" '$NF==f {print; found=1} END {exit found?0:1}' sha256sums.txt > checksum.txt
shasum -a 256 -c checksum.txt
)

sudo install -m 0755 "$tmpdir/${SHFMT_ASSET}" /usr/local/bin/shfmt

- name: Run CI checks (Linux/macOS)
if: matrix.os != 'windows-latest'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ on:
# The branches below must be a subset of the branches above
branches: ["main"]
schedule:
- cron: '42 0 * * 1'
- cron: "42 0 * * 1"
workflow_dispatch:

permissions:
Expand All @@ -47,7 +47,7 @@ jobs:
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Set Codacy paths
run: |
Expand Down Expand Up @@ -144,7 +144,7 @@ jobs:
# Upload the identified SARIF file
- name: Upload identified SARIF file
if: always() && env.SARIF_FILE != ''
uses: github/codeql-action/upload-sarif@b36bf259c813715f76eafece573914b94412cd13 # v3
uses: github/codeql-action/upload-sarif@b36bf259c813715f76eafece573914b94412cd13 # v3
with:
sarif_file: ${{ env.SARIF_FILE }}
continue-on-error: true
16 changes: 8 additions & 8 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ jobs:
TARPAULIN_VERSION: "0.32.8"
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0 # Needed for Codecov diff analysis
fetch-depth: 0 # Needed for Codecov diff analysis

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
with:
cache: true # toolchain/components are specified in rust-toolchain.toml
cache: true # toolchain/components are specified in rust-toolchain.toml

- name: Cache tarpaulin
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: ~/.cargo/bin/cargo-tarpaulin
key: tarpaulin-${{ runner.os }}-${{ env.TARPAULIN_VERSION }}
Expand All @@ -48,7 +48,7 @@ jobs:
fi

- name: Install just
uses: taiki-e/install-action@bfc291e1e39400b67eda124e4a7b4380e93b3390 # v2.65.0
uses: taiki-e/install-action@bfc291e1e39400b67eda124e4a7b4380e93b3390 # v2.65.0
with:
tool: just

Expand Down Expand Up @@ -76,7 +76,7 @@ jobs:

- name: Upload coverage to Codecov
if: ${{ success() && hashFiles('coverage/cobertura.xml') != '' }}
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
with:
files: coverage/cobertura.xml
flags: unittests
Expand All @@ -86,7 +86,7 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Archive coverage results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: coverage-report
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/rust-clippy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: "Clippy Security Analysis"
on:
# Only run on schedule and manual trigger to avoid duplication with CI
schedule:
- cron: '17 22 * * 0' # Weekly on Sunday
- cron: "17 22 * * 0" # Weekly on Sunday
workflow_dispatch:
# Run on main branch pushes for security scanning
push:
Expand All @@ -24,15 +24,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1.15.2
with:
cache: true # toolchain/components are specified in rust-toolchain.toml
cache: true # toolchain/components are specified in rust-toolchain.toml

- name: Cache clippy tools
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with:
path: |
~/.cargo/bin/clippy-sarif
Expand All @@ -58,7 +58,7 @@ jobs:
continue-on-error: true

- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@b36bf259c813715f76eafece573914b94412cd13 # v3
uses: github/codeql-action/upload-sarif@b36bf259c813715f76eafece573914b94412cd13 # v3
with:
sarif_file: rust-clippy-results.sarif
category: "clippy"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ venv/
.pytest_cache/
.mypy_cache/
uv.lock
/node_modules/
/package-lock.json
Loading
Loading