-
Notifications
You must be signed in to change notification settings - Fork 1
chore: add Dependabot security-only update config #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ee86714
c304a56
763a4a8
14f99d3
b7f6037
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # Dependabot configuration — security-only for application ecosystems | ||
| # | ||
| # Application ecosystems (cargo, npm, pip, etc.) use open-pull-requests-limit: 0 | ||
| # to disable scheduled version-update PRs. Dependabot security alerts still | ||
| # create PRs for known vulnerabilities regardless of this limit. | ||
| # | ||
| # GitHub Actions is the exception: we allow version updates there because | ||
| # actions are build-time dependencies with minimal supply-chain risk. | ||
| version: 2 | ||
| updates: | ||
| - package-ecosystem: "cargo" | ||
| directory: "/" | ||
| schedule: | ||
| interval: "weekly" | ||
| # Security-only: limit 0 disables version PRs; security alerts still open PRs | ||
| open-pull-requests-limit: 0 | ||
| labels: | ||
| - "security" | ||
| - "dependencies" | ||
|
|
||
| - package-ecosystem: "github-actions" | ||
| directory: "/" | ||
| schedule: | ||
| interval: "weekly" | ||
| open-pull-requests-limit: 10 | ||
| labels: | ||
| - "security" | ||
| - "dependencies" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # Dependabot auto-merge workflow | ||
| # | ||
| # 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 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 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: | ||
| pull_request_target: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| dependabot: | ||
| runs-on: ubuntu-24.04 | ||
| 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: 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.eligible.outputs.eligible == 'true' | ||
| 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 enable auto-merge | ||
| if: steps.eligible.outputs.eligible == 'true' | ||
| run: | | ||
| gh pr review --approve "$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 }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,219 @@ | ||
| # Dependency vulnerability audit | ||
| # | ||
| # 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. | ||
| # | ||
| # Pinned tool versions (update deliberately): | ||
| # govulncheck v1.1.4 | cargo-audit 0.22.1 | pip-audit 2.9.0 | ||
| name: Dependency audit | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| push: | ||
| branches: [main] | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| detect: | ||
| name: Detect ecosystems | ||
| runs-on: ubuntu-24.04 | ||
| outputs: | ||
|
Comment on lines
+22
to
+25
|
||
| 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 }} | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||
|
|
||
| - name: Detect package ecosystems | ||
| id: check | ||
| run: | | ||
| # 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 | ||
|
|
||
| # 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" | ||
| else | ||
| echo "gomod=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| # 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 — 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" | ||
| fi | ||
|
|
||
| audit-npm: | ||
| name: npm audit | ||
| needs: detect | ||
| if: needs.detect.outputs.npm == 'true' | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||
|
|
||
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | ||
| with: | ||
| node-version: "lts/*" | ||
|
|
||
| - name: Audit npm dependencies | ||
| run: | | ||
| # Audit each package-lock.json found in the repo | ||
| status=0 | ||
| while IFS= read -r dir; do | ||
| echo "::group::npm audit $dir" | ||
| if ! (cd "$dir" && npm audit --audit-level=low); then | ||
| status=1 | ||
| fi | ||
| echo "::endgroup::" | ||
| 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-24.04 | ||
| 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 | ||
| if: needs.detect.outputs.gomod == 'true' | ||
| runs-on: ubuntu-24.04 | ||
| 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@v1.1.4 | ||
|
|
||
| - name: Audit Go dependencies | ||
| run: | | ||
| status=0 | ||
| while IFS= read -r dir; do | ||
| echo "::group::govulncheck $dir" | ||
| if ! (cd "$dir" && govulncheck ./...); then | ||
| status=1 | ||
| fi | ||
| echo "::endgroup::" | ||
| done < <(find . -name 'go.mod' -not -path '*/vendor/*' -exec dirname {} \;) | ||
| exit $status | ||
|
|
||
| audit-cargo: | ||
| name: cargo audit | ||
| needs: detect | ||
| if: needs.detect.outputs.cargo == 'true' | ||
| runs-on: ubuntu-24.04 | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||
|
|
||
| - uses: dtolnay/rust-toolchain@stable | ||
|
|
||
| - uses: Swatinem/rust-cache@v2 | ||
|
|
||
| - name: Install cargo-audit | ||
| run: cargo install cargo-audit@0.22.1 --locked | ||
|
|
||
| - name: Audit Cargo dependencies | ||
| 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 | ||
| needs: detect | ||
| if: needs.detect.outputs.pip == 'true' | ||
| runs-on: ubuntu-24.04 | ||
| 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==2.9.0 | ||
|
|
||
| - name: Audit Python dependencies | ||
| 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 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description says this change aligns the repo to “security-only dependency updates”, but this config enables scheduled weekly version updates for cargo and GitHub Actions (not security-only) and applies a
securitylabel to all of them. If the intent is truly security-only, remove/disable scheduled version updates (or addignorerules to exclude non-security updates) and avoid labeling non-security PRs assecurity.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed —
open-pull-requests-limit: 0was already set for cargo (the only app ecosystem configured). Added file-level and inline comments explaining the security-only strategy: limit 0 disables version-update PRs while Dependabot security alerts still create PRs for known vulnerabilities.