From fab5e783a09ad772e01366e2d23da1c4f58f8887 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 3 Apr 2026 11:33:56 -0700 Subject: [PATCH 1/6] docs: add Dependabot security-only update standards Define org-wide policy for dependency management: security-only updates for application packages, weekly version updates for GitHub Actions, mandatory labels, auto-merge workflow, and vulnerability audit CI check. Includes templates for npm, Go, Rust, Python, Terraform, and full-stack repositories. Co-Authored-By: Claude Opus 4.6 (1M context) --- standards/dependabot-policy.md | 152 +++++++++++++++++++ standards/dependabot/backend-go.yml | 23 +++ standards/dependabot/backend-python.yml | 23 +++ standards/dependabot/backend-rust.yml | 23 +++ standards/dependabot/frontend.yml | 23 +++ standards/dependabot/fullstack.yml | 48 ++++++ standards/dependabot/infra-terraform.yml | 23 +++ standards/workflows/dependabot-automerge.yml | 57 +++++++ standards/workflows/dependency-audit.yml | 136 +++++++++++++++++ 9 files changed, 508 insertions(+) create mode 100644 standards/dependabot-policy.md create mode 100644 standards/dependabot/backend-go.yml create mode 100644 standards/dependabot/backend-python.yml create mode 100644 standards/dependabot/backend-rust.yml create mode 100644 standards/dependabot/frontend.yml create mode 100644 standards/dependabot/fullstack.yml create mode 100644 standards/dependabot/infra-terraform.yml create mode 100644 standards/workflows/dependabot-automerge.yml create mode 100644 standards/workflows/dependency-audit.yml diff --git a/standards/dependabot-policy.md b/standards/dependabot-policy.md new file mode 100644 index 0000000..b3c4230 --- /dev/null +++ b/standards/dependabot-policy.md @@ -0,0 +1,152 @@ +# Dependabot Policy: Security-Only Updates + +## Rationale + +New package versions pose risk to stability and security. Keeping known-good versions +and upgrading only when vulnerabilities are found and fixed provides a better +security posture than chasing every minor/patch release. + +## Policy + +1. **Security updates only** for application dependencies (npm, Go modules, pip, Cargo). + Dependabot opens PRs only when a vulnerability advisory exists for a dependency. +2. **Version updates weekly** for GitHub Actions, since pinned action versions do not + affect application stability and staying current reduces CI attack surface. +3. **Labels** `security` and `dependencies` on every Dependabot PR for filtering and audit. +4. **Auto-merge** security patches and minor updates after CI passes, using a GitHub App + token to satisfy branch protection (CODEOWNERS review bypass for bot PRs). +5. **Vulnerability audit CI check** runs on every PR and push to `main`, failing the + build if any dependency has a known advisory. This is a required status check. + +## Configuration Files + +Each repository must have: + +| File | Purpose | +|------|---------| +| `.github/dependabot.yml` | Dependabot config scoped to the repo's ecosystems | +| `.github/workflows/dependabot-automerge.yml` | Auto-approve + squash-merge security PRs | +| `.github/workflows/dependency-audit.yml` | CI check — fail on known vulnerabilities | + +## Dependabot Templates + +Use the template matching your repository type. All templates share these settings: + +```yaml +# Common settings applied to every package ecosystem entry +schedule: + interval: "weekly" +open-pull-requests-limit: 10 +labels: + - "security" + - "dependencies" +``` + +### Frontend (npm) + +For repos with `package.json` at root or in subdirectories. + +- Ecosystem: `npm` +- Directory: `/` (or path to each `package.json`) +- Security updates only (no `versioning-strategy` override needed — Dependabot + security updates use the lockfile by default) + +See [`dependabot/frontend.yml`](dependabot/frontend.yml) + +### Backend — Go + +For repos with `go.mod`. + +- Ecosystem: `gomod` +- Directory: path to `go.mod` + +See [`dependabot/backend-go.yml`](dependabot/backend-go.yml) + +### Backend — Rust + +For repos with `Cargo.toml`. + +- Ecosystem: `cargo` +- Directory: `/` + +See [`dependabot/backend-rust.yml`](dependabot/backend-rust.yml) + +### Backend — Python + +For repos with `pyproject.toml` or `requirements.txt`. + +- Ecosystem: `pip` +- Directory: `/` + +See [`dependabot/backend-python.yml`](dependabot/backend-python.yml) + +### Infrastructure — Terraform + +For repos with Terraform modules. + +- Ecosystem: `terraform` +- Directory: path to Terraform root module + +See [`dependabot/infra-terraform.yml`](dependabot/infra-terraform.yml) + +### GitHub Actions (all repos) + +Every repository must include the `github-actions` ecosystem entry. +GitHub Actions use **version updates** (not security-only) on a weekly schedule +since pinned action SHAs do not affect application runtime stability. + +```yaml +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" +``` + +### Full-Stack Example + +A full-stack repo (e.g., npm + Go + Terraform + GitHub Actions) combines the +relevant ecosystem entries into a single `dependabot.yml`. See +[`dependabot/fullstack.yml`](dependabot/fullstack.yml) for a complete example. + +## Auto-Merge Workflow + +See [`workflows/dependabot-automerge.yml`](workflows/dependabot-automerge.yml). + +Behavior: +- Triggers on `pull_request_target` from `dependabot[bot]` +- Fetches Dependabot metadata to determine update type +- For **patch** and **minor** security updates (and indirect dependency updates): + approves the PR and squash-merges using a GitHub App token +- **Major** updates are left for human review + +## Vulnerability Audit CI Check + +See [`workflows/dependency-audit.yml`](workflows/dependency-audit.yml). + +This reusable workflow detects the ecosystems present in the repo and runs the +appropriate audit tool: + +| Ecosystem | Tool | Command | +|-----------|------|---------| +| npm | `npm audit` | `npm audit --audit-level=moderate` | +| Go | `govulncheck` | `govulncheck ./...` | +| Rust | `cargo-audit` | `cargo audit` | +| Python | `pip-audit` | `pip-audit` | + +The workflow fails if any known vulnerability is found, blocking the PR from merging. + +## Applying to a Repository + +1. Copy the appropriate `dependabot.yml` template to `.github/dependabot.yml`, + adjusting `directory` paths as needed. +2. Copy `workflows/dependabot-automerge.yml` to `.github/workflows/`. +3. Copy `workflows/dependency-audit.yml` to `.github/workflows/`. +4. Ensure the repository has the GitHub App secrets (`APP_ID`, `APP_PRIVATE_KEY`) + configured for auto-merge. +5. Create the `security` and `dependencies` labels in the repository if they + don't already exist. +6. Add `dependency-audit` as a required status check in branch protection rules. diff --git a/standards/dependabot/backend-go.yml b/standards/dependabot/backend-go.yml new file mode 100644 index 0000000..a7cdca7 --- /dev/null +++ b/standards/dependabot/backend-go.yml @@ -0,0 +1,23 @@ +# Dependabot configuration for Go backend repositories +# Copy to .github/dependabot.yml and adjust directory paths as needed +version: 2 +updates: + # Go modules — security updates only + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # GitHub Actions — version updates (keep actions current) + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" diff --git a/standards/dependabot/backend-python.yml b/standards/dependabot/backend-python.yml new file mode 100644 index 0000000..b8f3a82 --- /dev/null +++ b/standards/dependabot/backend-python.yml @@ -0,0 +1,23 @@ +# Dependabot configuration for Python backend repositories +# Copy to .github/dependabot.yml and adjust directory paths as needed +version: 2 +updates: + # pip — security updates only + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # GitHub Actions — version updates (keep actions current) + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" diff --git a/standards/dependabot/backend-rust.yml b/standards/dependabot/backend-rust.yml new file mode 100644 index 0000000..92d283f --- /dev/null +++ b/standards/dependabot/backend-rust.yml @@ -0,0 +1,23 @@ +# Dependabot configuration for Rust backend repositories +# Copy to .github/dependabot.yml and adjust directory paths as needed +version: 2 +updates: + # Cargo — security updates only + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # GitHub Actions — version updates (keep actions current) + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" diff --git a/standards/dependabot/frontend.yml b/standards/dependabot/frontend.yml new file mode 100644 index 0000000..96bb698 --- /dev/null +++ b/standards/dependabot/frontend.yml @@ -0,0 +1,23 @@ +# Dependabot configuration for frontend (npm) repositories +# Copy to .github/dependabot.yml and adjust directory paths as needed +version: 2 +updates: + # npm — security updates only + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # GitHub Actions — version updates (keep actions current) + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" diff --git a/standards/dependabot/fullstack.yml b/standards/dependabot/fullstack.yml new file mode 100644 index 0000000..f2b6c90 --- /dev/null +++ b/standards/dependabot/fullstack.yml @@ -0,0 +1,48 @@ +# Dependabot configuration for full-stack repositories (npm + Go + Terraform) +# Copy to .github/dependabot.yml and adjust directory paths as needed +# +# Example layout: +# apps/mobile/package.json (or markets-app/package.json) +# apps/api/go.mod (or markets-api/go.mod) +# infra/terraform/main.tf +version: 2 +updates: + # npm — security updates only + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # Go modules — security updates only + - package-ecosystem: "gomod" + directory: "/apps/api" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # Terraform — security updates only + - package-ecosystem: "terraform" + directory: "/infra/terraform" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # GitHub Actions — version updates (keep actions current) + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" diff --git a/standards/dependabot/infra-terraform.yml b/standards/dependabot/infra-terraform.yml new file mode 100644 index 0000000..1aa50b9 --- /dev/null +++ b/standards/dependabot/infra-terraform.yml @@ -0,0 +1,23 @@ +# Dependabot configuration for Terraform infrastructure repositories +# Copy to .github/dependabot.yml and adjust directory paths as needed +version: 2 +updates: + # Terraform — security updates only + - package-ecosystem: "terraform" + directory: "/infra/terraform" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" + + # GitHub Actions — version updates (keep actions current) + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "security" + - "dependencies" diff --git a/standards/workflows/dependabot-automerge.yml b/standards/workflows/dependabot-automerge.yml new file mode 100644 index 0000000..4561a0e --- /dev/null +++ b/standards/workflows/dependabot-automerge.yml @@ -0,0 +1,57 @@ +# Dependabot auto-merge workflow +# Copy to .github/workflows/dependabot-automerge.yml +# +# Requires repository secrets: +# APP_ID — GitHub App ID with contents:write and pull-requests:write +# APP_PRIVATE_KEY — GitHub App private key +# +# Auto-approves and squash-merges Dependabot PRs for: +# - Patch version updates +# - Minor version updates +# - Indirect (transitive) dependency updates +# Major version updates are left for human review. +name: Dependabot auto-merge + +on: + pull_request_target: + branches: + - main + +permissions: {} + +jobs: + dependabot: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + if: github.event.pull_request.user.login == 'dependabot[bot]' + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # v2 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Generate app token + if: >- + steps.metadata.outputs.update-type == 'version-update:semver-patch' || + steps.metadata.outputs.update-type == 'version-update:semver-minor' || + steps.metadata.outputs.dependency-type == 'indirect' + id: app-token + uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3 + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Approve and auto-merge + if: >- + steps.metadata.outputs.update-type == 'version-update:semver-patch' || + steps.metadata.outputs.update-type == 'version-update:semver-minor' || + steps.metadata.outputs.dependency-type == 'indirect' + run: | + gh pr review --approve "$PR_URL" + gh pr merge --squash --admin "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/standards/workflows/dependency-audit.yml b/standards/workflows/dependency-audit.yml new file mode 100644 index 0000000..d84556e --- /dev/null +++ b/standards/workflows/dependency-audit.yml @@ -0,0 +1,136 @@ +# Dependency vulnerability audit +# Copy to .github/workflows/dependency-audit.yml +# +# Auto-detects ecosystems present in the repository and runs the appropriate +# audit tool. Fails the build if any dependency has a known security advisory. +# +# Add "dependency-audit" as a required status check in branch protection. +name: Dependency audit + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + contents: read + +jobs: + detect: + name: Detect ecosystems + runs-on: ubuntu-latest + outputs: + npm: ${{ steps.check.outputs.npm }} + gomod: ${{ steps.check.outputs.gomod }} + cargo: ${{ steps.check.outputs.cargo }} + pip: ${{ steps.check.outputs.pip }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Detect package ecosystems + id: check + run: | + # npm + if find . -name 'package-lock.json' -not -path '*/node_modules/*' | grep -q .; then + echo "npm=true" >> "$GITHUB_OUTPUT" + else + echo "npm=false" >> "$GITHUB_OUTPUT" + fi + + # Go modules + if find . -name 'go.sum' | grep -q .; then + echo "gomod=true" >> "$GITHUB_OUTPUT" + else + echo "gomod=false" >> "$GITHUB_OUTPUT" + fi + + # Cargo + if [ -f "Cargo.lock" ]; then + echo "cargo=true" >> "$GITHUB_OUTPUT" + else + echo "cargo=false" >> "$GITHUB_OUTPUT" + fi + + # Python + if [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then + echo "pip=true" >> "$GITHUB_OUTPUT" + else + echo "pip=false" >> "$GITHUB_OUTPUT" + fi + + audit-npm: + name: npm audit + needs: detect + if: needs.detect.outputs.npm == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "lts/*" + + - name: Audit npm dependencies + run: npm audit --audit-level=moderate + + audit-go: + name: govulncheck + needs: detect + if: needs.detect.outputs.gomod == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 + with: + go-version: "stable" + + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + + - name: Audit Go dependencies + run: | + # Run govulncheck in each module directory + find . -name 'go.mod' -exec dirname {} \; | while read -r dir; do + echo "::group::govulncheck $dir" + (cd "$dir" && govulncheck ./...) + echo "::endgroup::" + done + + audit-cargo: + name: cargo audit + needs: detect + if: needs.detect.outputs.cargo == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Install cargo-audit + run: cargo install cargo-audit + + - name: Audit Cargo dependencies + run: cargo audit + + audit-pip: + name: pip-audit + needs: detect + if: needs.detect.outputs.pip == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.x" + + - name: Install pip-audit + run: pip install pip-audit + + - name: Audit Python dependencies + run: | + if [ -f "pyproject.toml" ]; then + pip-audit --require-hashes=false + elif [ -f "requirements.txt" ]; then + pip-audit -r requirements.txt + fi From 5532e5b687bbdea0614a16e90acc7a19229b7c2b Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 3 Apr 2026 11:41:08 -0700 Subject: [PATCH 2/6] fix: address Copilot review feedback on Dependabot standards - Use open-pull-requests-limit: 0 for app ecosystems to suppress version update PRs (security updates bypass this limit) - Switch auto-merge from --admin to --auto --squash to respect CI checks - Fix dependency-audit: detect go.mod not go.sum, detect Cargo.toml not Cargo.lock, add Rust toolchain setup, handle monorepo npm lockfiles, pin tool versions (govulncheck v1.1.4, cargo-audit 0.21.1, pip-audit 2.9.0), install Python deps before auditing - Use npm audit --audit-level=low to fail on any advisory - Update policy doc wording for clarity Co-Authored-By: Claude Opus 4.6 (1M context) --- standards/dependabot-policy.md | 47 ++++++++++++++----- standards/dependabot/backend-go.yml | 7 ++- standards/dependabot/backend-python.yml | 7 ++- standards/dependabot/backend-rust.yml | 7 ++- standards/dependabot/frontend.yml | 7 ++- standards/dependabot/fullstack.yml | 15 +++--- standards/dependabot/infra-terraform.yml | 7 ++- standards/workflows/dependabot-automerge.yml | 7 +-- standards/workflows/dependency-audit.yml | 49 +++++++++++++------- 9 files changed, 106 insertions(+), 47 deletions(-) diff --git a/standards/dependabot-policy.md b/standards/dependabot-policy.md index b3c4230..e3a09bf 100644 --- a/standards/dependabot-policy.md +++ b/standards/dependabot-policy.md @@ -10,14 +10,26 @@ security posture than chasing every minor/patch release. 1. **Security updates only** for application dependencies (npm, Go modules, pip, Cargo). Dependabot opens PRs only when a vulnerability advisory exists for a dependency. + Version update PRs are suppressed by setting `open-pull-requests-limit: 0` for + application ecosystems — Dependabot security updates bypass this limit. 2. **Version updates weekly** for GitHub Actions, since pinned action versions do not affect application stability and staying current reduces CI attack surface. 3. **Labels** `security` and `dependencies` on every Dependabot PR for filtering and audit. -4. **Auto-merge** security patches and minor updates after CI passes, using a GitHub App - token to satisfy branch protection (CODEOWNERS review bypass for bot PRs). +4. **Auto-merge** security patches and minor updates after all CI checks pass, using a + GitHub App token to satisfy branch protection (CODEOWNERS review bypass for bot PRs). + Uses `gh pr merge --auto` to wait for required checks before merging. 5. **Vulnerability audit CI check** runs on every PR and push to `main`, failing the build if any dependency has a known advisory. This is a required status check. +## Prerequisites + +- **Dependabot security updates** must be enabled at the org or repo level + (Settings > Code security > Dependabot security updates). +- The `dependabot.yml` entries below configure which ecosystems and directories + Dependabot monitors. Setting `open-pull-requests-limit: 0` for application + ecosystems suppresses routine version-update PRs while still allowing + security-alert-triggered PRs to be created. + ## Configuration Files Each repository must have: @@ -30,13 +42,25 @@ Each repository must have: ## Dependabot Templates -Use the template matching your repository type. All templates share these settings: +Use the template matching your repository type. + +**Application ecosystems** (npm, gomod, cargo, pip, terraform) use: + +```yaml +schedule: + interval: "weekly" +open-pull-requests-limit: 0 # suppress version updates; security PRs bypass this +labels: + - "security" + - "dependencies" +``` + +**GitHub Actions** uses: ```yaml -# Common settings applied to every package ecosystem entry schedule: interval: "weekly" -open-pull-requests-limit: 10 +open-pull-requests-limit: 10 # allow version updates for CI actions labels: - "security" - "dependencies" @@ -48,8 +72,6 @@ For repos with `package.json` at root or in subdirectories. - Ecosystem: `npm` - Directory: `/` (or path to each `package.json`) -- Security updates only (no `versioning-strategy` override needed — Dependabot - security updates use the lockfile by default) See [`dependabot/frontend.yml`](dependabot/frontend.yml) @@ -119,21 +141,22 @@ See [`workflows/dependabot-automerge.yml`](workflows/dependabot-automerge.yml). Behavior: - Triggers on `pull_request_target` from `dependabot[bot]` - Fetches Dependabot metadata to determine update type -- For **patch** and **minor** security updates (and indirect dependency updates): - approves the PR and squash-merges using a GitHub App token +- For **patch** and **minor** updates (and indirect dependency updates): + approves the PR and enables auto-merge (waits for all required CI checks) - **Major** updates are left for human review +- Uses `gh pr merge --auto --squash` so the merge only happens after CI passes ## Vulnerability Audit CI Check See [`workflows/dependency-audit.yml`](workflows/dependency-audit.yml). -This reusable workflow detects the ecosystems present in the repo and runs the +This workflow template detects the ecosystems present in the repo and runs the appropriate audit tool: | Ecosystem | Tool | Command | |-----------|------|---------| -| npm | `npm audit` | `npm audit --audit-level=moderate` | -| Go | `govulncheck` | `govulncheck ./...` | +| npm | `npm audit` | `npm audit --audit-level=low` (fails on any advisory) | +| Go | `govulncheck` | `govulncheck ./...` (per module) | | Rust | `cargo-audit` | `cargo audit` | | Python | `pip-audit` | `pip-audit` | diff --git a/standards/dependabot/backend-go.yml b/standards/dependabot/backend-go.yml index a7cdca7..985d672 100644 --- a/standards/dependabot/backend-go.yml +++ b/standards/dependabot/backend-go.yml @@ -1,13 +1,16 @@ # Dependabot configuration for Go backend repositories # Copy to .github/dependabot.yml and adjust directory paths as needed +# +# gomod uses open-pull-requests-limit: 0 to suppress version update PRs. +# Dependabot security updates bypass this limit, so security PRs still open. version: 2 updates: - # Go modules — security updates only + # Go modules — security updates only (limit 0 suppresses version updates) - package-ecosystem: "gomod" directory: "/" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" diff --git a/standards/dependabot/backend-python.yml b/standards/dependabot/backend-python.yml index b8f3a82..dc8ff3f 100644 --- a/standards/dependabot/backend-python.yml +++ b/standards/dependabot/backend-python.yml @@ -1,13 +1,16 @@ # Dependabot configuration for Python backend repositories # Copy to .github/dependabot.yml and adjust directory paths as needed +# +# pip uses open-pull-requests-limit: 0 to suppress version update PRs. +# Dependabot security updates bypass this limit, so security PRs still open. version: 2 updates: - # pip — security updates only + # pip — security updates only (limit 0 suppresses version updates) - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" diff --git a/standards/dependabot/backend-rust.yml b/standards/dependabot/backend-rust.yml index 92d283f..5570ac8 100644 --- a/standards/dependabot/backend-rust.yml +++ b/standards/dependabot/backend-rust.yml @@ -1,13 +1,16 @@ # Dependabot configuration for Rust backend repositories # Copy to .github/dependabot.yml and adjust directory paths as needed +# +# cargo uses open-pull-requests-limit: 0 to suppress version update PRs. +# Dependabot security updates bypass this limit, so security PRs still open. version: 2 updates: - # Cargo — security updates only + # Cargo — security updates only (limit 0 suppresses version updates) - package-ecosystem: "cargo" directory: "/" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" diff --git a/standards/dependabot/frontend.yml b/standards/dependabot/frontend.yml index 96bb698..7398cb4 100644 --- a/standards/dependabot/frontend.yml +++ b/standards/dependabot/frontend.yml @@ -1,13 +1,16 @@ # Dependabot configuration for frontend (npm) repositories # Copy to .github/dependabot.yml and adjust directory paths as needed +# +# npm uses open-pull-requests-limit: 0 to suppress version update PRs. +# Dependabot security updates bypass this limit, so security PRs still open. version: 2 updates: - # npm — security updates only + # npm — security updates only (limit 0 suppresses version updates) - package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" diff --git a/standards/dependabot/fullstack.yml b/standards/dependabot/fullstack.yml index f2b6c90..fb1a045 100644 --- a/standards/dependabot/fullstack.yml +++ b/standards/dependabot/fullstack.yml @@ -1,38 +1,41 @@ # Dependabot configuration for full-stack repositories (npm + Go + Terraform) # Copy to .github/dependabot.yml and adjust directory paths as needed # +# Application ecosystems use open-pull-requests-limit: 0 to suppress version +# update PRs. Dependabot security updates bypass this limit. +# # Example layout: # apps/mobile/package.json (or markets-app/package.json) # apps/api/go.mod (or markets-api/go.mod) # infra/terraform/main.tf version: 2 updates: - # npm — security updates only + # npm — security updates only (limit 0 suppresses version updates) - package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" - # Go modules — security updates only + # Go modules — security updates only (limit 0 suppresses version updates) - package-ecosystem: "gomod" directory: "/apps/api" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" - # Terraform — security updates only + # Terraform — security updates only (limit 0 suppresses version updates) - package-ecosystem: "terraform" directory: "/infra/terraform" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" diff --git a/standards/dependabot/infra-terraform.yml b/standards/dependabot/infra-terraform.yml index 1aa50b9..e6e27c4 100644 --- a/standards/dependabot/infra-terraform.yml +++ b/standards/dependabot/infra-terraform.yml @@ -1,13 +1,16 @@ # Dependabot configuration for Terraform infrastructure repositories # Copy to .github/dependabot.yml and adjust directory paths as needed +# +# terraform uses open-pull-requests-limit: 0 to suppress version update PRs. +# Dependabot security updates bypass this limit, so security PRs still open. version: 2 updates: - # Terraform — security updates only + # Terraform — security updates only (limit 0 suppresses version updates) - package-ecosystem: "terraform" directory: "/infra/terraform" schedule: interval: "weekly" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 labels: - "security" - "dependencies" diff --git a/standards/workflows/dependabot-automerge.yml b/standards/workflows/dependabot-automerge.yml index 4561a0e..85114d3 100644 --- a/standards/workflows/dependabot-automerge.yml +++ b/standards/workflows/dependabot-automerge.yml @@ -5,11 +5,12 @@ # APP_ID — GitHub App ID with contents:write and pull-requests:write # APP_PRIVATE_KEY — GitHub App private key # -# Auto-approves and squash-merges Dependabot PRs for: +# Auto-approves and enables auto-merge for Dependabot PRs: # - Patch version updates # - Minor version updates # - Indirect (transitive) dependency updates # Major version updates are left for human review. +# Uses --auto so the merge waits for all required CI checks to pass. name: Dependabot auto-merge on: @@ -44,14 +45,14 @@ jobs: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} - - name: Approve and auto-merge + - name: Approve and enable auto-merge if: >- steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.dependency-type == 'indirect' run: | gh pr review --approve "$PR_URL" - gh pr merge --squash --admin "$PR_URL" + gh pr merge --auto --squash "$PR_URL" env: PR_URL: ${{ github.event.pull_request.html_url }} GH_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/standards/workflows/dependency-audit.yml b/standards/workflows/dependency-audit.yml index d84556e..ab82e9f 100644 --- a/standards/workflows/dependency-audit.yml +++ b/standards/workflows/dependency-audit.yml @@ -31,22 +31,22 @@ jobs: - name: Detect package ecosystems id: check run: | - # npm + # npm — look for package-lock.json anywhere (excluding node_modules) if find . -name 'package-lock.json' -not -path '*/node_modules/*' | grep -q .; then echo "npm=true" >> "$GITHUB_OUTPUT" else echo "npm=false" >> "$GITHUB_OUTPUT" fi - # Go modules - if find . -name 'go.sum' | grep -q .; then + # Go modules — detect via go.mod (not go.sum, which may not exist) + if find . -name 'go.mod' -not -path '*/vendor/*' | grep -q .; then echo "gomod=true" >> "$GITHUB_OUTPUT" else echo "gomod=false" >> "$GITHUB_OUTPUT" fi - # Cargo - if [ -f "Cargo.lock" ]; then + # Cargo — detect via Cargo.toml (lockfile may not exist for libraries) + if find . -name 'Cargo.toml' -not -path '*/target/*' | grep -q .; then echo "cargo=true" >> "$GITHUB_OUTPUT" else echo "cargo=false" >> "$GITHUB_OUTPUT" @@ -72,7 +72,17 @@ jobs: node-version: "lts/*" - name: Audit npm dependencies - run: npm audit --audit-level=moderate + run: | + # Audit each package-lock.json found in the repo + failed=0 + find . -name 'package-lock.json' -not -path '*/node_modules/*' -exec dirname {} \; | while read -r dir; do + echo "::group::npm audit $dir" + if ! (cd "$dir" && npm audit --audit-level=low); then + failed=1 + fi + echo "::endgroup::" + done + exit $failed audit-go: name: govulncheck @@ -87,16 +97,20 @@ jobs: go-version: "stable" - name: Install govulncheck - run: go install golang.org/x/vuln/cmd/govulncheck@latest + run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 - name: Audit Go dependencies run: | # Run govulncheck in each module directory - find . -name 'go.mod' -exec dirname {} \; | while read -r dir; do + failed=0 + find . -name 'go.mod' -not -path '*/vendor/*' -exec dirname {} \; | while read -r dir; do echo "::group::govulncheck $dir" - (cd "$dir" && govulncheck ./...) + if ! (cd "$dir" && govulncheck ./...); then + failed=1 + fi echo "::endgroup::" done + exit $failed audit-cargo: name: cargo audit @@ -106,8 +120,10 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: dtolnay/rust-toolchain@stable + - name: Install cargo-audit - run: cargo install cargo-audit + run: cargo install cargo-audit@0.21.1 --locked - name: Audit Cargo dependencies run: cargo audit @@ -124,13 +140,14 @@ jobs: with: python-version: "3.x" - - name: Install pip-audit - run: pip install pip-audit - - - name: Audit Python dependencies + - name: Install dependencies and pip-audit run: | + pip install pip-audit==2.9.0 if [ -f "pyproject.toml" ]; then - pip-audit --require-hashes=false + pip install -e ".[dev]" 2>/dev/null || pip install -e . 2>/dev/null || true elif [ -f "requirements.txt" ]; then - pip-audit -r requirements.txt + pip install -r requirements.txt fi + + - name: Audit Python dependencies + run: pip-audit From 9ea71bafdd78b166078ab58fb2ee4bada9199955 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 3 Apr 2026 11:43:10 -0700 Subject: [PATCH 3/6] fix: address CodeRabbit review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Auto-merge: restructure eligibility check with explicit step, add defense-in-depth comment explaining security model - dependency-audit: make Cargo and Python detection recursive (matching npm/Go pattern), iterate over workspace dirs for cargo audit, use pip-audit with project path instead of auditing runner env, use process substitution to preserve exit status across subshells - Policy doc: fix wording (Copy → Add), update audit table for monorepo Co-Authored-By: Claude Opus 4.6 (1M context) --- standards/dependabot-policy.md | 12 +-- standards/workflows/dependabot-automerge.yml | 44 ++++++++--- standards/workflows/dependency-audit.yml | 77 ++++++++++++++------ 3 files changed, 91 insertions(+), 42 deletions(-) diff --git a/standards/dependabot-policy.md b/standards/dependabot-policy.md index e3a09bf..6abbc2a 100644 --- a/standards/dependabot-policy.md +++ b/standards/dependabot-policy.md @@ -155,10 +155,10 @@ appropriate audit tool: | Ecosystem | Tool | Command | |-----------|------|---------| -| npm | `npm audit` | `npm audit --audit-level=low` (fails on any advisory) | -| Go | `govulncheck` | `govulncheck ./...` (per module) | -| Rust | `cargo-audit` | `cargo audit` | -| Python | `pip-audit` | `pip-audit` | +| npm | `npm audit` | `npm audit --audit-level=low` per lockfile (fails on any advisory) | +| Go | `govulncheck` | `govulncheck ./...` per `go.mod` directory | +| Rust | `cargo-audit` | `cargo audit` per `Cargo.toml` workspace | +| Python | `pip-audit` | `pip-audit .` per `pyproject.toml` / `-r requirements.txt` | The workflow fails if any known vulnerability is found, blocking the PR from merging. @@ -166,8 +166,8 @@ The workflow fails if any known vulnerability is found, blocking the PR from mer 1. Copy the appropriate `dependabot.yml` template to `.github/dependabot.yml`, adjusting `directory` paths as needed. -2. Copy `workflows/dependabot-automerge.yml` to `.github/workflows/`. -3. Copy `workflows/dependency-audit.yml` to `.github/workflows/`. +2. Add `workflows/dependabot-automerge.yml` to `.github/workflows/`. +3. Add `workflows/dependency-audit.yml` to `.github/workflows/`. 4. Ensure the repository has the GitHub App secrets (`APP_ID`, `APP_PRIVATE_KEY`) configured for auto-merge. 5. Create the `security` and `dependencies` labels in the repository if they diff --git a/standards/workflows/dependabot-automerge.yml b/standards/workflows/dependabot-automerge.yml index 85114d3..6080c9a 100644 --- a/standards/workflows/dependabot-automerge.yml +++ b/standards/workflows/dependabot-automerge.yml @@ -5,12 +5,17 @@ # APP_ID — GitHub App ID with contents:write and pull-requests:write # APP_PRIVATE_KEY — GitHub App private key # -# Auto-approves and enables auto-merge for Dependabot PRs: -# - Patch version updates -# - Minor version updates +# Auto-approves and enables auto-merge for Dependabot PRs that are: +# - GitHub Actions updates (patch or minor version bumps) +# - Security updates for any ecosystem (patch or minor) # - Indirect (transitive) dependency updates -# Major version updates are left for human review. +# Major version updates are always left for human review. # Uses --auto so the merge waits for all required CI checks to pass. +# +# Safety model: application ecosystems use open-pull-requests-limit: 0 in +# dependabot.yml, so the only app-ecosystem PRs Dependabot can create are +# security updates. This workflow adds defense-in-depth by also checking +# the package ecosystem. name: Dependabot auto-merge on: @@ -34,11 +39,29 @@ jobs: with: github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Determine if auto-merge eligible + id: eligible + run: | + UPDATE_TYPE="${{ steps.metadata.outputs.update-type }}" + DEP_TYPE="${{ steps.metadata.outputs.dependency-type }}" + ECOSYSTEM="${{ steps.metadata.outputs.package-ecosystem }}" + + # Must be patch, minor, or indirect + if [[ "$UPDATE_TYPE" != "version-update:semver-patch" && \ + "$UPDATE_TYPE" != "version-update:semver-minor" && \ + "$DEP_TYPE" != "indirect" ]]; then + echo "eligible=false" >> "$GITHUB_OUTPUT" + echo "Skipping: major update requires human review" + exit 0 + fi + + # GitHub Actions version updates are always eligible + # App ecosystem PRs can only exist as security updates (limit: 0) + echo "eligible=true" >> "$GITHUB_OUTPUT" + echo "Auto-merge eligible: ecosystem=$ECOSYSTEM update=$UPDATE_TYPE" + - name: Generate app token - if: >- - steps.metadata.outputs.update-type == 'version-update:semver-patch' || - steps.metadata.outputs.update-type == 'version-update:semver-minor' || - steps.metadata.outputs.dependency-type == 'indirect' + if: steps.eligible.outputs.eligible == 'true' id: app-token uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3 with: @@ -46,10 +69,7 @@ jobs: private-key: ${{ secrets.APP_PRIVATE_KEY }} - name: Approve and enable auto-merge - if: >- - steps.metadata.outputs.update-type == 'version-update:semver-patch' || - steps.metadata.outputs.update-type == 'version-update:semver-minor' || - steps.metadata.outputs.dependency-type == 'indirect' + if: steps.eligible.outputs.eligible == 'true' run: | gh pr review --approve "$PR_URL" gh pr merge --auto --squash "$PR_URL" diff --git a/standards/workflows/dependency-audit.yml b/standards/workflows/dependency-audit.yml index ab82e9f..36a8f6a 100644 --- a/standards/workflows/dependency-audit.yml +++ b/standards/workflows/dependency-audit.yml @@ -5,6 +5,9 @@ # audit tool. Fails the build if any dependency has a known security advisory. # # Add "dependency-audit" as a required status check in branch protection. +# +# Pinned tool versions (update deliberately): +# govulncheck v1.1.4 | cargo-audit 0.21.1 | pip-audit 2.9.0 name: Dependency audit on: @@ -45,15 +48,16 @@ jobs: echo "gomod=false" >> "$GITHUB_OUTPUT" fi - # Cargo — detect via Cargo.toml (lockfile may not exist for libraries) + # Cargo — detect via Cargo.toml anywhere (lockfile may not exist for libraries) if find . -name 'Cargo.toml' -not -path '*/target/*' | grep -q .; then echo "cargo=true" >> "$GITHUB_OUTPUT" else echo "cargo=false" >> "$GITHUB_OUTPUT" fi - # Python - if [ -f "pyproject.toml" ] || [ -f "requirements.txt" ]; then + # Python — detect pyproject.toml or requirements.txt anywhere + if find . -name 'pyproject.toml' -not -path '*/.venv/*' -not -path '*/venv/*' | grep -q . || \ + find . -name 'requirements.txt' -not -path '*/.venv/*' -not -path '*/venv/*' | grep -q .; then echo "pip=true" >> "$GITHUB_OUTPUT" else echo "pip=false" >> "$GITHUB_OUTPUT" @@ -74,15 +78,15 @@ jobs: - name: Audit npm dependencies run: | # Audit each package-lock.json found in the repo - failed=0 - find . -name 'package-lock.json' -not -path '*/node_modules/*' -exec dirname {} \; | while read -r dir; do + status=0 + while IFS= read -r dir; do echo "::group::npm audit $dir" if ! (cd "$dir" && npm audit --audit-level=low); then - failed=1 + status=1 fi echo "::endgroup::" - done - exit $failed + done < <(find . -name 'package-lock.json' -not -path '*/node_modules/*' -exec dirname {} \;) + exit $status audit-go: name: govulncheck @@ -101,16 +105,15 @@ jobs: - name: Audit Go dependencies run: | - # Run govulncheck in each module directory - failed=0 - find . -name 'go.mod' -not -path '*/vendor/*' -exec dirname {} \; | while read -r dir; do + status=0 + while IFS= read -r dir; do echo "::group::govulncheck $dir" if ! (cd "$dir" && govulncheck ./...); then - failed=1 + status=1 fi echo "::endgroup::" - done - exit $failed + done < <(find . -name 'go.mod' -not -path '*/vendor/*' -exec dirname {} \;) + exit $status audit-cargo: name: cargo audit @@ -126,7 +129,18 @@ jobs: run: cargo install cargo-audit@0.21.1 --locked - name: Audit Cargo dependencies - run: cargo audit + run: | + # cargo audit operates on Cargo.lock at workspace root + # For workspaces, a single audit at root covers all crates + status=0 + while IFS= read -r dir; do + echo "::group::cargo audit $dir" + if ! (cd "$dir" && cargo generate-lockfile 2>/dev/null; cargo audit); then + status=1 + fi + echo "::endgroup::" + done < <(find . -name 'Cargo.toml' -not -path '*/target/*' -exec dirname {} \; | sort -u) + exit $status audit-pip: name: pip-audit @@ -140,14 +154,29 @@ jobs: with: python-version: "3.x" - - name: Install dependencies and pip-audit - run: | - pip install pip-audit==2.9.0 - if [ -f "pyproject.toml" ]; then - pip install -e ".[dev]" 2>/dev/null || pip install -e . 2>/dev/null || true - elif [ -f "requirements.txt" ]; then - pip install -r requirements.txt - fi + - name: Install pip-audit + run: pip install pip-audit==2.9.0 - name: Audit Python dependencies - run: pip-audit + run: | + status=0 + # Audit each Python project found in the repo + while IFS= read -r dir; do + echo "::group::pip-audit $dir" + if [ -f "$dir/pyproject.toml" ]; then + if ! pip-audit "$dir"; then + status=1 + fi + elif [ -f "$dir/requirements.txt" ]; then + if ! pip-audit -r "$dir/requirements.txt"; then + status=1 + fi + fi + echo "::endgroup::" + done < <( + { + find . -name 'pyproject.toml' -not -path '*/.venv/*' -not -path '*/venv/*' -exec dirname {} \; + find . -name 'requirements.txt' -not -path '*/.venv/*' -not -path '*/venv/*' -exec dirname {} \; + } | sort -u + ) + exit $status From ad067cfb3c4de49f5bb14c8d11141f6102475671 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 3 Apr 2026 11:47:28 -0700 Subject: [PATCH 4/6] feat: add pnpm audit support to dependency-audit workflow Repos like broodly use pnpm instead of npm. The workflow now detects pnpm-lock.yaml and runs pnpm audit alongside npm audit. Co-Authored-By: Claude Opus 4.6 (1M context) --- standards/dependabot-policy.md | 3 +- standards/workflows/dependency-audit.yml | 36 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/standards/dependabot-policy.md b/standards/dependabot-policy.md index 6abbc2a..702889b 100644 --- a/standards/dependabot-policy.md +++ b/standards/dependabot-policy.md @@ -155,7 +155,8 @@ appropriate audit tool: | Ecosystem | Tool | Command | |-----------|------|---------| -| npm | `npm audit` | `npm audit --audit-level=low` per lockfile (fails on any advisory) | +| npm | `npm audit` | `npm audit --audit-level=low` per `package-lock.json` (fails on any advisory) | +| pnpm | `pnpm audit` | `pnpm audit --audit-level low` per `pnpm-lock.yaml` | | Go | `govulncheck` | `govulncheck ./...` per `go.mod` directory | | Rust | `cargo-audit` | `cargo audit` per `Cargo.toml` workspace | | Python | `pip-audit` | `pip-audit .` per `pyproject.toml` / `-r requirements.txt` | diff --git a/standards/workflows/dependency-audit.yml b/standards/workflows/dependency-audit.yml index 36a8f6a..4e7c732 100644 --- a/standards/workflows/dependency-audit.yml +++ b/standards/workflows/dependency-audit.yml @@ -25,6 +25,7 @@ jobs: runs-on: ubuntu-latest outputs: npm: ${{ steps.check.outputs.npm }} + pnpm: ${{ steps.check.outputs.pnpm }} gomod: ${{ steps.check.outputs.gomod }} cargo: ${{ steps.check.outputs.cargo }} pip: ${{ steps.check.outputs.pip }} @@ -41,6 +42,13 @@ jobs: echo "npm=false" >> "$GITHUB_OUTPUT" fi + # pnpm — look for pnpm-lock.yaml anywhere + if find . -name 'pnpm-lock.yaml' -not -path '*/node_modules/*' | grep -q .; then + echo "pnpm=true" >> "$GITHUB_OUTPUT" + else + echo "pnpm=false" >> "$GITHUB_OUTPUT" + fi + # Go modules — detect via go.mod (not go.sum, which may not exist) if find . -name 'go.mod' -not -path '*/vendor/*' | grep -q .; then echo "gomod=true" >> "$GITHUB_OUTPUT" @@ -88,6 +96,34 @@ jobs: done < <(find . -name 'package-lock.json' -not -path '*/node_modules/*' -exec dirname {} \;) exit $status + audit-pnpm: + name: pnpm audit + needs: detect + if: needs.detect.outputs.pnpm == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 + + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: "lts/*" + cache: "pnpm" + + - name: Audit pnpm dependencies + run: | + # Audit each pnpm-lock.yaml found in the repo + status=0 + while IFS= read -r dir; do + echo "::group::pnpm audit $dir" + if ! (cd "$dir" && pnpm audit --audit-level low); then + status=1 + fi + echo "::endgroup::" + done < <(find . -name 'pnpm-lock.yaml' -not -path '*/node_modules/*' -exec dirname {} \;) + exit $status + audit-go: name: govulncheck needs: detect From 16b46cb4b771b9525e86ce3f2d9cf411dda1e4df Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 3 Apr 2026 11:51:27 -0700 Subject: [PATCH 5/6] fix: bump cargo-audit to 0.22.1 for CVSS 4.0 support cargo-audit 0.21.1 fails parsing RustSec advisories using CVSS 4.0 scores (e.g., RUSTSEC-2025-0138). Version 0.22.1 adds support. Co-Authored-By: Claude Opus 4.6 (1M context) --- standards/workflows/dependency-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standards/workflows/dependency-audit.yml b/standards/workflows/dependency-audit.yml index 4e7c732..3f29337 100644 --- a/standards/workflows/dependency-audit.yml +++ b/standards/workflows/dependency-audit.yml @@ -7,7 +7,7 @@ # Add "dependency-audit" as a required status check in branch protection. # # Pinned tool versions (update deliberately): -# govulncheck v1.1.4 | cargo-audit 0.21.1 | pip-audit 2.9.0 +# govulncheck v1.1.4 | cargo-audit 0.22.1 | pip-audit 2.9.0 name: Dependency audit on: From 8ca31e47184d9420b26ae41a82cb3af35571a315 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 3 Apr 2026 20:11:56 -0700 Subject: [PATCH 6/6] fix: remove pnpm cache from audit job (causes path validation error) The setup-node cache: "pnpm" option fails during post-job cleanup when the pnpm store path doesn't exist. Caching isn't needed for a one-off audit run. Co-Authored-By: Claude Opus 4.6 (1M context) --- standards/workflows/dependency-audit.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/standards/workflows/dependency-audit.yml b/standards/workflows/dependency-audit.yml index 3f29337..5a1c53b 100644 --- a/standards/workflows/dependency-audit.yml +++ b/standards/workflows/dependency-audit.yml @@ -109,7 +109,6 @@ jobs: - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: "lts/*" - cache: "pnpm" - name: Audit pnpm dependencies run: | @@ -162,7 +161,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - name: Install cargo-audit - run: cargo install cargo-audit@0.21.1 --locked + run: cargo install cargo-audit@0.22.1 --locked - name: Audit Cargo dependencies run: |