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
187 changes: 131 additions & 56 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,104 +6,179 @@ on:
pull_request:
branches: ["**"]

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

env:
CARGO_TERM_COLOR: always

jobs:
lint:
name: Lint
name: Lint (clippy + fmt)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2

- name: Setup Rust cache
uses: Swatinem/rust-cache@v2

- name: Check formatting
run: cargo fmt --all -- --check

- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings

test:
name: Test on ${{ matrix.os }}
needs: lint
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- uses: actions/checkout@v4

- name: Install Rust 1.95 (MSRV)
uses: dtolnay/rust-toolchain@stable
with:
shared-key: ci-ubuntu
- run: cargo fmt --all -- --check
- run: cargo clippy --all-targets --all-features -- -D warnings
toolchain: "1.95"

- name: Setup Rust cache
uses: Swatinem/rust-cache@v2

- name: Build
run: cargo build --verbose

- uses: taiki-e/install-action@nextest

# Every test needs a backend feature; the default set (`std`) has none.
- name: Run tests
run: cargo nextest run --no-tests=pass

- name: Run tests with all features
run: cargo nextest run --all-features

- name: Test documentation
run: cargo test --doc

wasm:
name: WASM
name: WASM build
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2

- name: Setup Rust cache
uses: Swatinem/rust-cache@v2

- name: Build for WASM
run: cargo build --target wasm32-unknown-unknown --all-features

minimal-versions:
name: Minimal versions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
shared-key: ci-ubuntu
- run: cargo build --target wasm32-unknown-unknown --features std
toolchain: stable

- name: Setup Rust cache
uses: Swatinem/rust-cache@v2

- name: Install cargo-hack
run: cargo install cargo-hack

- name: Check minimal versions
run: cargo hack check --all --ignore-private
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-ubuntu
- uses: taiki-e/install-action@cargo-llvm-cov
- run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
- uses: codecov/codecov-action@v4

- name: Setup Rust cache
uses: Swatinem/rust-cache@v2

- name: Install cargo-llvm-cov
run: cargo install cargo-llvm-cov

- uses: taiki-e/install-action@nextest

- name: Generate test coverage
run: cargo llvm-cov nextest --all-features --workspace --lcov --output-path lcov.info

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: lcov.info
fail_ci_if_error: true
typos:
name: Typos

feature-checks:
name: Feature checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crate-ci/typos@master

audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci-ubuntu
- name: Generate Lockfile
run: cargo generate-lockfile
- uses: rustsec/audit-check@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable

unused-deps:
name: Unused Dependencies
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2

- name: Install cargo-hack
run: cargo install cargo-hack

- name: Check each feature
run: cargo hack check --each-feature --no-dev-deps

- name: Check feature combinations
run: cargo hack check --feature-powerset --no-dev-deps

audit:
name: Security audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2

- name: Generate lockfile
run: cargo generate-lockfile

- uses: rustsec/audit-check@v2
with:
shared-key: ci-ubuntu
- uses: taiki-e/install-action@cargo-machete
- run: cargo machete
token: ${{ secrets.GITHUB_TOKEN }}

feature-checks:
name: Features
unused-deps:
name: Unused dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
shared-key: ci-ubuntu
- uses: taiki-e/install-action@cargo-hack
- run: cargo hack check --each-feature --no-dev-deps
- run: cargo hack check --feature-powerset --no-dev-deps
toolchain: stable

test:
name: Test
uses: ./.github/workflows/test.yml
- uses: taiki-e/install-action@cargo-machete

- run: cargo machete
101 changes: 101 additions & 0 deletions .github/workflows/dep-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Dependency Check

on:
schedule:
- cron: "0 9 * * 1"
workflow_dispatch:

permissions:
issues: write
contents: read

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Detect project type
id: detect
run: |
if [ -f Cargo.toml ]; then
echo "type=rust" >> "$GITHUB_OUTPUT"
elif [ -f package.json ]; then
echo "type=node" >> "$GITHUB_OUTPUT"
elif [ -f Package.swift ]; then
echo "type=swift" >> "$GITHUB_OUTPUT"
else
echo "type=unknown" >> "$GITHUB_OUTPUT"
fi

- name: Setup Rust
if: steps.detect.outputs.type == 'rust'
uses: dtolnay/rust-toolchain@stable

- name: Rust cache
if: steps.detect.outputs.type == 'rust'
uses: Swatinem/rust-cache@v2

- name: Check Rust dependencies
if: steps.detect.outputs.type == 'rust'
run: |
cargo install cargo-outdated --locked
cargo outdated -R --exit-code 1 > outdated.txt 2>&1 || true
cat outdated.txt

- name: Setup Node
if: steps.detect.outputs.type == 'node'
uses: actions/setup-node@v4
with:
node-version: lts/*

- name: Check Node dependencies
if: steps.detect.outputs.type == 'node'
run: |
npm install --ignore-scripts 2>/dev/null || true
npm outdated --long 2>/dev/null > outdated.txt || true
cat outdated.txt

- name: Check Swift dependencies
if: steps.detect.outputs.type == 'swift'
run: |
swift package show-dependencies 2>/dev/null > outdated.txt || echo "Unable to check Swift dependencies" > outdated.txt
cat outdated.txt

- name: Report
if: steps.detect.outputs.type != 'unknown'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh label create "dependencies" --description "Dependency updates" --color "0075ca" 2>/dev/null || true

if [ ! -s outdated.txt ]; then
echo "No outdated dependencies"
existing=$(gh issue list --label "dependencies" --state open --json number --jq '.[0].number' 2>/dev/null || true)
if [ -n "$existing" ] && [ "$existing" != "null" ]; then
gh issue close "$existing" -c "All dependencies are up to date."
fi
exit 0
fi

content=$(cat outdated.txt)
body=$(cat <<BODY
## Outdated Dependencies

\`\`\`
${content}
\`\`\`

_Last checked: $(date -u +%Y-%m-%dT%H:%M:%SZ) · updated weekly_
BODY
)

existing=$(gh issue list --label "dependencies" --state open --json number --jq '.[0].number' 2>/dev/null || true)

if [ -n "$existing" ] && [ "$existing" != "null" ]; then
gh issue edit "$existing" --body "$body"
echo "Updated issue #$existing"
else
gh issue create --title "Outdated dependencies" --body "$body" --label "dependencies"
echo "Created tracking issue"
fi
Loading
Loading