diff --git a/.commitlintrc.json b/.commitlintrc.json new file mode 100644 index 0000000..e912347 --- /dev/null +++ b/.commitlintrc.json @@ -0,0 +1,12 @@ +{ + "extends": ["@commitlint/config-conventional"], + "rules": { + "header-max-length": [2, "always", 100], + "body-max-line-length": [0, "always"], + "footer-max-line-length": [0, "always"], + "type-enum": [2, "always", [ + "build", "chore", "ci", "docs", "feat", "fix", + "perf", "refactor", "revert", "style", "test" + ]] + } +} diff --git a/.github/workflows/cargo-audit.yml b/.github/workflows/cargo-audit.yml new file mode 100644 index 0000000..165b8e9 --- /dev/null +++ b/.github/workflows/cargo-audit.yml @@ -0,0 +1,62 @@ +name: cargo audit + +# RustSec advisory scan. Runs alongside the existing cargo-deny check in +# ci.yml — deny enforces license + ban policy from deny.toml; audit fires +# on the latest RustSec database so a new advisory against any transitive +# dep surfaces in ≤ 1 CI run rather than waiting for the next manual sweep. +# +# Advisory findings (cargo audit exit 1) surface as PR check warnings, +# non-blocking. Execution failures (exit 2+) fail the job — see the +# explicit exit-code branching in the Run step below. Promote advisories +# to blocking by removing that branch once the backlog is clean and new +# findings can be actioned within SLO. +# Ignore list mirrors deny.toml [advisories].ignore — keep them in sync. + +on: + pull_request: + branches: [main] + push: + branches: [main] + schedule: + # Daily at 04:00 UTC — surfaces freshly-published advisories without + # needing a PR to trigger the scan. + - cron: '0 4 * * *' + workflow_dispatch: + +permissions: + contents: read + +jobs: + audit: + name: cargo audit (advisory scan) + runs-on: ubuntu-22.04 + env: + # Pin to a known-good cargo-audit so the security scan stays + # reproducible across runs. Bump intentionally via PR (so behaviour + # changes are reviewed, not silently picked up from latest-stable). + CARGO_AUDIT_VERSION: "0.22.1" + steps: + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - name: Install cargo-audit + run: cargo install cargo-audit --locked --version "$CARGO_AUDIT_VERSION" + - name: Run cargo audit + # Distinguish advisory findings (cargo audit exit 1, non-blocking + # warning) from tool execution failures (exit 2+, must fail the + # job). The previous `|| echo` swallowed both. + # Ignore list mirrors deny.toml [advisories].ignore — each ID + # has a documented reason there; if you add one here, add it + # there too. + run: | + set +e + cargo audit \ + --ignore RUSTSEC-2024-0436 \ + --ignore RUSTSEC-2025-0134 + status=$? + set -e + case "$status" in + 0) echo "no advisories" ;; + 1) echo "::warning::cargo audit findings (non-blocking, see deny.toml for ignored IDs)" ;; + *) echo "::error::cargo audit execution failed with exit $status"; exit "$status" ;; + esac diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..630cda2 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,22 @@ +name: commitlint + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: read + +jobs: + commitlint: + name: commitlint + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + with: + fetch-depth: 0 + + - uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6 + with: + configFile: .commitlintrc.json diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..5ce62ad --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,33 @@ +name: Dependency review + +# Runs GitHub's dependency-review-action on PRs. Diffs the lockfile changes +# in the PR vs the base branch and BLOCKS merge if newly-introduced +# dependencies have vulnerabilities OR licenses outside our allowlist. +# +# Pair with Dependabot: Dependabot opens upgrade PRs; this gate enforces +# nothing bad slips in through manual deps changes that bypass Dependabot. +# Complements the existing `deny` job in ci.yml — that runs against the +# full dep tree post-merge; this one runs against the diff pre-merge. + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: write + +jobs: + dependency-review: + name: Dependency review + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + + - uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4 + with: + fail-on-severity: high + # Mirror deny.toml [licenses].allow. + allow-licenses: MIT, Apache-2.0, Apache-2.0 WITH LLVM-exception, BSD-2-Clause, BSD-3-Clause, ISC, MPL-2.0, Unicode-DFS-2016, Unicode-3.0, CC0-1.0, Zlib, 0BSD, BUSL-1.1, CDLA-Permissive-2.0 + allow-dependencies-licenses: pkg:githubactions/Swatinem/rust-cache + comment-summary-in-pr: on-failure