Overview
Per db-cfg (opens in new window), Dependabot opens PRs (or issues, for security-only updates) when a new version is available for a declared dependency, configured via .github/dependabot.yml at the repo root.
This is a reference skill - it defines the config surface; it doesn't run scans (that's snyk-test or osv-scanner). Dependabot complements SCA tools by automating the upgrade PR.
When to use
For non-GitHub repos, see renovate-config.
Step 1 - Top-level structure
Per db-cfg (opens in new window):
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"Required top-level keys:
| Key | Use |
|---|---|
version | Always 2 (only supported version) |
updates | Array of per-ecosystem update configurations |
Step 2 - Per-update required fields
Per db-cfg (opens in new window):
| Field | Use |
|---|---|
package-ecosystem | Package manager: npm, bundler, cargo, composer, docker, github-actions, gitsubmodule, gomod, gradle, maven, mix, nuget, pip, pub, swift, terraform |
directory (or directories) | Manifest location relative to repo root |
schedule.interval | Frequency: daily / weekly / monthly / quarterly / semiannually / yearly / cron (with cron expression) |
directories (plural) supports an array for monorepos:
- package-ecosystem: "npm"
directories:
- "/services/api"
- "/services/worker"
- "/packages/shared"Step 3 - Common optional fields
Per db-cfg (opens in new window):
ignore
"Ignore updates for dependencies with matching names, optionally using
*to match zero or" more characters.
ignore:
- dependency-name: "lodash"
versions: [">=5.0.0"] # don't update past v5
- dependency-name: "*-internal-*"
update-types: ["version-update:semver-major"]groups
"Combines multiple dependency updates into single pull requests using pattern matching and dependency type filters."
groups:
dev-deps:
dependency-type: "development"
update-types: ["minor", "patch"]
production-deps:
dependency-type: "production"
exclude-patterns: ["express*", "fastify*"]Grouped PRs reduce review noise - instead of 30 individual PRs for dev-deps, get one consolidated PR.
allow
"Restricts updates to explicitly listed dependencies only."
allow:
- dependency-name: "react*"
- dependency-type: "direct"Use carefully - overly-narrow allow lists silently drop coverage of newly-added deps.
Other common fields
| Field | Use |
|---|---|
labels | Custom PR labels (overrides default dependencies) |
milestone | Numeric milestone ID for created PRs |
open-pull-requests-limit | Max concurrent version PRs (default 5; security-only PRs not counted) |
target-branch | Update target branch (security PRs always go to default branch) |
vendor | Maintain vendored deps (Bundler, Go modules) |
versioning-strategy | auto / strict / increase-if-necessary / widen-ranges |
assignees | GitHub usernames for assignment |
commit-message | Customize prefix + scope |
Step 4 - Realistic multi-ecosystem example
One updates entry per ecosystem, each with its own schedule and labels (reuse the groups / ignore blocks from Step 3 as needed):
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
groups:
dev-deps:
dependency-type: "development"
labels: ["dependencies", "javascript"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
- package-ecosystem: "docker"
directory: "/Dockerfile"
schedule:
interval: "weekly"Full config with per-ecosystem groups, ignore rules, assignees, and commit-message customization: references/dependabot-advanced.md.
Verify: after committing .github/dependabot.yml, open the repo's Dependabot view (Insights -> Dependency graph -> Dependabot) and confirm GitHub reports no dependabot.yml parse error and lists every configured package-ecosystem; if it flags a parse error, fix the reported key and re-push before relying on the config. Use the view's Check for updates control to force a run instead of waiting for the schedule.
Step 5 - Security updates (always-on)
Dependabot security updates are enabled separately in repo settings (Security → Code security and analysis → Dependabot security updates). Security PRs:
Step 6 - False-positive triage analogue
Dependabot doesn't produce findings to triage - it produces upgrade PRs. The "FP triage" analogue is suppressing unwanted update PRs:
| Mechanism | Use |
|---|---|
ignore.dependency-name + versions range | Pin a dep to a major version (avoid breaking changes) |
ignore.update-types | Block all major-version PRs for a dep |
| Repo Settings → Security → Disable Dependabot for a specific package | Categorical disable (last resort) |
Justification template (mandatory in dependabot.yml comments):
ignore:
# Reason: react v19 + react-router v7 incompatibility blocks upgrade
# Approved-by: alice@example.com
# Re-review-date: 2026-09-15 (re-evaluate when react-router v8 ships)
- dependency-name: "react"
update-types: ["version-update:semver-major"]Cadence: every quarter, audit ignore: entries; expired re-review dates removed.
Step 7 - Auto-merge integration
Dependabot creates PRs but doesn't auto-merge. For auto-merge, pair with GitHub Auto-merge or a workflow that reads dependabot/fetch-metadata and gates the merge to version-update:semver-patch only (after CI passes; patch-only is safer than minor / major). Full workflow: references/dependabot-advanced.md.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
interval: "daily" everywhere | PR storm overwhelms reviewers | weekly for non-critical; daily only for security-sensitive deps |
No groups: for dev deps | Each dev-dep update is a separate PR | Group by dependency-type (Step 3) |
ignore without expiration comment | Permanent debt | Mandatory Re-review-date: (Step 6) |
| Skip security-only updates feature (or disable in Settings) | Critical CVEs reach prod | Keep enabled; never disable wholesale |
| Auto-merge minor/major automatically | Breaking changes ship without review | Auto-merge patch only (Step 7) |
Limitations
References
Deep-dive material moved out of the SKILL.md spine: the full multi-ecosystem .github/dependabot.yml, and the patch-only auto-merge workflow. All keys are documented in the official configuration reference (docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file).
Full multi-ecosystem example
Every field here is optional except package-ecosystem, directory, and schedule.interval (see SKILL.md Step 2). This expands the consolidated Step 4 example with per-ecosystem groups, ignore, assignees, and commit-message customization.
version: 2
updates:
# Application dependencies
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "UTC"
open-pull-requests-limit: 10
groups:
dev-deps:
dependency-type: "development"
update-types: ["minor", "patch"]
production-minor-patch:
dependency-type: "production"
update-types: ["minor", "patch"]
ignore:
- dependency-name: "react"
update-types: ["version-update:semver-major"]
labels: ["dependencies", "javascript"]
assignees: ["alice"]
commit-message:
prefix: "deps"
include: "scope"
# CI workflow updates
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
groups:
gha:
patterns: ["*"]
labels: ["dependencies", "ci"]
# Docker base image updates
- package-ecosystem: "docker"
directory: "/Dockerfile"
schedule:
interval: "weekly"
labels: ["dependencies", "docker"]Patch-only auto-merge workflow
Dependabot creates PRs but doesn't auto-merge. Pair it with a workflow that reads update metadata via dependabot/fetch-metadata and enables auto-merge only for version-update:semver-patch (auto-merge still waits for required CI to pass). Patch-only is safer than minor / major.
# .github/workflows/dependabot-automerge.yml
name: Dependabot auto-merge
on: pull_request
permissions:
pull-requests: write
contents: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- uses: dependabot/fetch-metadata@v2
id: meta
- if: steps.meta.outputs.update-type == 'version-update:semver-patch'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}