Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
152 changes: 152 additions & 0 deletions standards/dependabot-policy.md
Original file line number Diff line number Diff line change
@@ -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.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
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.
Comment on lines +11 to +22

Copilot AI Apr 3, 2026

Copy link

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.

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

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

standards/workflows/dependency-audit.yml is a copy-paste workflow template, not a reusable workflow invoked via workflow_call. Consider changing the wording here to avoid confusion (or convert it to a reusable workflow if that’s the intent).

Suggested change
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

Copilot uses AI. Check for mistakes.
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` |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

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

23 changes: 23 additions & 0 deletions standards/dependabot/backend-go.yml
Original file line number Diff line number Diff line change
@@ -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"

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

This template states “security updates only,” but a scheduled updates: entry for gomod will run Dependabot version updates on that schedule 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"
23 changes: 23 additions & 0 deletions standards/dependabot/backend-python.yml
Original file line number Diff line number Diff line change
@@ -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"

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

This template states “security updates only,” but a scheduled updates: entry for the pip ecosystem 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"
23 changes: 23 additions & 0 deletions standards/dependabot/backend-rust.yml
Original file line number Diff line number Diff line change
@@ -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"

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

This template states “security updates only,” but a scheduled updates: entry for cargo 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"
23 changes: 23 additions & 0 deletions standards/dependabot/frontend.yml
Original file line number Diff line number Diff line change
@@ -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"

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

This file/comment says “security updates only,” but a scheduled updates: entry for the npm ecosystem will generate regular version update PRs (not just security advisories) unless additional configuration/Dependabot alerts settings are used to suppress version updates. Clarify the template (or add the necessary config) so it matches the stated security-only standard.

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"
48 changes: 48 additions & 0 deletions standards/dependabot/fullstack.yml
Original file line number Diff line number Diff line change
@@ -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"
Comment on lines +12 to +41

Copilot AI Apr 3, 2026

Copy link

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.
23 changes: 23 additions & 0 deletions standards/dependabot/infra-terraform.yml
Original file line number Diff line number Diff line change
@@ -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"

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

This template states “security updates only,” but a scheduled updates: entry for Terraform will run regular version updates for providers/modules 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"
57 changes: 57 additions & 0 deletions standards/workflows/dependabot-automerge.yml
Original file line number Diff line number Diff line change
@@ -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'

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

The merge/approve gating currently checks only semver update type (patch/minor) or indirect deps, not whether the PR is a security update. If a repo enables regular version updates for app dependencies, this workflow will auto-merge non-security bumps, which contradicts the security-only policy. Add a security-specific condition (e.g., require a security label or Dependabot metadata indicating a security update).

Copilot uses AI. Check for mistakes.

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 | 🟠 Major

Implementation doesn't match policy: auto-merges all patch/minor, not just security updates.

The policy document states auto-merge applies to "patch and minor security updates", but this workflow auto-merges any patch/minor/indirect update regardless of whether it's security-related.

To align with the stated policy, the workflow should also check for the security label (which Dependabot security updates automatically apply) or verify the update is from a security advisory:

🔧 Proposed fix to restrict to security updates
      - name: Generate app token
        if: >-
+         contains(github.event.pull_request.labels.*.name, 'security') &&
+         (
          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

Apply the same change to the "Approve and auto-merge" step's if condition.

Alternatively, if the intent is to auto-merge all non-major updates (not just security), update the policy documentation to reflect this.

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

In `@standards/workflows/dependabot-automerge.yml` around lines 37 - 51, The
workflow currently auto-merges any semver-patch/semver-minor or indirect update;
update both conditional expressions (the one before the "app-token" step with id
"app-token" and the one for the "Approve and auto-merge" step) to also require
that the PR is a Dependabot security update by adding a check for the security
label (e.g. add && contains(join(github.event.pull_request.labels.*.name, ','),
'security') or equivalent contains(...) test on
github.event.pull_request.labels) so only patch/minor security updates are
auto-merged; if instead you intend to auto-merge all non-major updates, update
the policy docs accordingly.

run: |
gh pr review --approve "$PR_URL"
gh pr merge --squash --admin "$PR_URL"

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

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

gh pr merge --admin can bypass branch protection requirements and merge even if required status checks aren’t passing. This conflicts with “after CI passes”; remove the admin bypass and use an approach that waits for required checks (e.g., auto-merge) so merges only occur once checks succeed.

Suggested change
gh pr merge --squash --admin "$PR_URL"
gh pr merge --auto --squash "$PR_URL"

Copilot uses AI. Check for mistakes.
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
Loading
Loading