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
176 changes: 176 additions & 0 deletions standards/dependabot-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# 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.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
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 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.
Comment on lines +11 to +22
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The policy states application dependencies should be “security updates only,” but the provided templates include scheduled updates: entries for npm/gomod/pip/cargo/terraform, which will generate regular version update PRs on that schedule. If the intent is truly security-only, clarify that Dependabot security updates (alerts) must be enabled and either omit version-update entries for app ecosystems or configure them to avoid non-security PRs (leaving weekly updates only for github-actions).

Copilot uses AI. Check for mistakes.

## 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:

| 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.

**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
schedule:
interval: "weekly"
open-pull-requests-limit: 10 # allow version updates for CI actions
labels:
- "security"
- "dependencies"
```

### Frontend (npm)

For repos with `package.json` at root or in subdirectories.

- Ecosystem: `npm`
- Directory: `/` (or path to each `package.json`)

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** 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 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=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` |

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. 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
don't already exist.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
6. Add `dependency-audit` as a required status check in branch protection rules.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locating dependency-audit workflow..."
fd -i '^dependency-audit\.yml$' | while read -r f; do
  echo "== $f =="
  echo "-- top-level workflow name --"
  rg -n '^name:' "$f"
  echo "-- job keys --"
  rg -n '^[[:space:]]{2}[A-Za-z0-9_-]+:' "$f"
done

echo
echo "Expected result: document the exact check name shown in GitHub branch protection UI (workflow/job check run), not just the file name."

Repository: petry-projects/.github

Length of output: 504


🏁 Script executed:

cat -n standards/dependabot-policy.md | sed -n '165,185p'

Repository: petry-projects/.github

Length of output: 728


🏁 Script executed:

cat -n standards/workflows/dependency-audit.yml | head -80

Repository: petry-projects/.github

Length of output: 3418


Use the exact check-run name Dependency audit / detect in branch protection instructions.

dependency-audit is the filename, not the check-run name. GitHub branch protection requires the actual check-run produced by the workflow, which follows the format {workflow-name} / {job-key}. Since the audit jobs are conditional (only run if the ecosystem is detected), use Dependency audit / detect which always runs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@standards/dependabot-policy.md` at line 176, Update item 6 to use the actual
check-run name produced by the workflow: replace the filename token
`dependency-audit` with the check-run string "Dependency audit / detect" so
branch protection requires the real check-run `{workflow-name} / {job-key}` used
by the audit workflow.

26 changes: 26 additions & 0 deletions standards/dependabot/backend-go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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 (limit 0 suppresses version updates)
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
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"
26 changes: 26 additions & 0 deletions standards/dependabot/backend-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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 (limit 0 suppresses version updates)
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
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"
26 changes: 26 additions & 0 deletions standards/dependabot/backend-rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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 (limit 0 suppresses version updates)
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
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"
26 changes: 26 additions & 0 deletions standards/dependabot/frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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 (limit 0 suppresses version updates)
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
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"
51 changes: 51 additions & 0 deletions standards/dependabot/fullstack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 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 (limit 0 suppresses version updates)
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
labels:
- "security"
- "dependencies"

# Go modules — security updates only (limit 0 suppresses version updates)
- package-ecosystem: "gomod"
directory: "/apps/api"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
labels:
- "security"
- "dependencies"

# Terraform — security updates only (limit 0 suppresses version updates)
- package-ecosystem: "terraform"
directory: "/infra/terraform"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
labels:
- "security"
- "dependencies"
Comment on lines +12 to +41
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This template labels npm/gomod/terraform entries as “security updates only,” but these scheduled updates: entries will generate regular version update PRs unless version updates are explicitly suppressed. Update the template or wording to align with the security-only policy.

Copilot uses AI. Check for mistakes.

# GitHub Actions — version updates (keep actions current)
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
labels:
- "security"
- "dependencies"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
26 changes: 26 additions & 0 deletions standards/dependabot/infra-terraform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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 (limit 0 suppresses version updates)
- package-ecosystem: "terraform"
directory: "/infra/terraform"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
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"
Loading
Loading