Automatically approves and merges Dependabot Pull Requests for production dependencies.
- ✅ Automatic approval of Dependabot PRs
- ✅ Automatic merge with configurable method (squash, merge, rebase)
- ✅ Filter by dependency type (production, development, all)
- ✅ Add labels to approved PRs
- ✅ Support for auto-merge (requires branch protection rules)
- ✅ Safe PR author verification
- ✅ Supports pull_request_target workflows when secrets are required
name: Dependabot Auto Manage
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'app/dependabot'
steps:
- name: Dependabot auto-manage
uses: frequenz-floss/dependabot-auto-approve@v1Note: If you need to pass a PAT or GitHub App token from secrets, use the
pull_request_target event instead of pull_request. See
pull_request_target and secrets below.
name: Dependabot Auto Manage
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'app/dependabot'
steps:
- name: Dependabot auto-manage
uses: frequenz-floss/dependabot-auto-approve@v1
with:
github-token: ${{ secrets.PAT_TOKEN }} # Required for PR approval
dependency-type: 'direct:production' # or 'direct:development', 'all'
merge-method: 'squash' # or 'merge', 'rebase'
auto-merge: 'false' # 'true' for auto-merge (requires branch protection)
add-label: 'dependabot-approved' # label for approved PRs| Parameter | Description | Required | Default |
|---|---|---|---|
github-token |
GitHub token for API calls (use PAT for approval) | No | github.token |
dependency-type |
Type of dependencies to auto-merge | No | direct:production |
merge-method |
Merge method | No | squash |
auto-merge |
Enable auto-merge | No | false |
add-label |
Label for approved PRs | No | dependabot-approved |
ignore-regex-pr-title |
Regex patterns to ignore PRs (comma-separated) | No | |
pr-number |
PR number (for manual dispatch workflows) | No | |
pr-url |
PR URL (for manual dispatch workflows) | No |
direct:production- production dependencies onlydirect:development- development dependencies onlyall- all dependencies
squash- squash commits into onemerge- regular mergerebase- rebase and merge
You can specify one or more regex patterns (comma-separated) to skip auto-approval for certain PRs. If any pattern matches the PR title, the PR will be ignored.
Examples:
ignore-regex-pr-title: '.*security.*,.*major.*'- Skip PRs with "security" or "major" in the titleignore-regex-pr-title: '^Bump.*from.*to.*'- Skip PRs with specific version bump patternsignore-regex-pr-title: '.*breaking.*,.*deprecated.*'- Skip PRs with breaking changes or deprecations
The workflow must have the following permissions:
permissions:
contents: write
pull-requests: writeFor approval functionality, you need a Personal Access Token (PAT) because GITHUB_TOKEN cannot approve PRs:
- Create a PAT in GitHub Settings → Developer settings → Personal access tokens
- Grant
reposcope (for private repos) orpublic_reposcope (for public repos) - Add it as a secret in your repository: Settings → Secrets → Actions
- Use it in the workflow:
- uses: frequenz-floss/dependabot-auto-approve@v1
with:
github-token: ${{ secrets.PAT_TOKEN }} # Use your PAT secret nameNote: The action will still work without a PAT, but won't be able to approve PRs. It will add labels and attempt to merge (if no approval is required).
If you need to pass a PAT or GitHub App token (for approvals or auto-merge),
the workflow must be able to read secrets. The pull_request event does not
expose secrets for untrusted PRs, so use pull_request_target instead.
pull_request_target runs in the base repo context and has access to secrets.
Treat PR content as untrusted:
- Do not check out or execute code from the PR branch
- Avoid running dependency installs or scripts from the PR
- Pin all third-party actions by full commit SHA
More details: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
- Create a GitHub App with repository permissions for Contents and Pull requests (and Issues if you use labels).
- Install the app on the repository.
- Store the App ID and private key as secrets.
- Use actions/create-github-app-token to mint a token.
Example:
name: Auto-merge Dependabot PR
on:
# SECURITY WARNING: pull_request_target runs in the base repo context and
# can read secrets. Do not check out or execute code from the PR. Pin all
# third-party actions by SHA. See:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
pull_request_target:
permissions:
contents: read
pull-requests: write
jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-id: ${{ secrets.DEPENDABOT_APP_ID }}
private-key: ${{ secrets.DEPENDABOT_APP_PRIVATE_KEY }}
- name: Auto-merge Dependabot PR
uses: frequenz-floss/dependabot-auto-approve@<commit-sha> # pin to a release commit
with:
github-token: ${{ steps.app-token.outputs.token }}
dependency-type: 'all'
auto-merge: 'true'
merge-method: 'merge'
add-label: 'tool:auto-merged'To use auto-merge: 'true' you need to:
- Configure branch protection rules in Settings → Branches
- Enable "Allow auto-merge" for the repository
- Set up required status checks
- ✅ Verifies that PR is created by Dependabot
- ✅ Supports both
dependabot[bot]andapp/dependabotformats - ✅ Filters by dependency type
- ✅ Uses official
dependabot/fetch-metadataaction ⚠️ If you usepull_request_target, do not check out or execute PR code and pin all actions by SHA
This happens when using the default GITHUB_TOKEN. Solutions:
-
Use a Personal Access Token:
- uses: frequenz-floss/dependabot-auto-approve@v1 with: github-token: ${{ secrets.PAT_TOKEN }}
-
Or disable approval and rely on auto-merge (if branch protection allows):
- uses: frequenz-floss/dependabot-auto-approve@v1 with: auto-merge: 'true' # Requires branch protection rules
Common causes:
- Branch protection rules require approval
- Required status checks are failing
- Merge conflicts exist
- Repository doesn't allow auto-merge
Check that:
- PR is created by Dependabot (
dependabot[bot]orapp/dependabot) - Dependency type matches your filter (
direct:production,direct:development, orall) - Workflow has proper permissions (
contents: write,pull-requests: write)
name: Dependabot Auto Manage
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'app/dependabot'
steps:
- uses: frequenz-floss/dependabot-auto-approve@v1
with:
dependency-type: 'direct:production'
merge-method: 'squash'name: Dependabot Auto Manage
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'app/dependabot'
steps:
- uses: frequenz-floss/dependabot-auto-approve@v1
with:
dependency-type: 'all'
auto-merge: 'true'
add-label: 'auto-merged'name: Dependabot Auto Manage
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'app/dependabot'
steps:
- uses: frequenz-floss/dependabot-auto-approve@v1
with:
dependency-type: 'direct:production'
ignore-regex-pr-title: '.*security.*,.*major.*'
merge-method: 'squash'name: Dependabot Auto Manage
on:
# SECURITY WARNING: pull_request_target runs in the base repo context and
# can read secrets. Do not check out or execute code from the PR. Pin all
# third-party actions by SHA. See:
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
pull_request_target:
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to process'
required: true
type: number
dependency_type:
description: 'Dependency type to process'
required: false
default: 'direct:production'
type: choice
options:
- 'direct:production'
- 'direct:development'
- 'all'
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: |
(github.event_name == 'pull_request_target' && (github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'app/dependabot')) ||
(github.event_name == 'workflow_dispatch')
steps:
- name: Checkout (for manual dispatch)
if: github.event_name == 'workflow_dispatch'
uses: actions/checkout@v4
- name: Check PR author (for manual dispatch)
if: github.event_name == 'workflow_dispatch'
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER_INPUT: ${{ github.event.inputs.pr_number }}
REPO: ${{ github.repository }}
run: |
PR_AUTHOR=$(gh pr view "$PR_NUMBER_INPUT" --repo "$REPO" --json author --jq '.author.login')
if [[ "$PR_AUTHOR" != "dependabot[bot]" && "$PR_AUTHOR" != "app/dependabot" ]]; then
echo "❌ PR #$PR_NUMBER_INPUT is not from Dependabot (author: $PR_AUTHOR)"
exit 1
fi
echo "✅ PR #$PR_NUMBER_INPUT is from Dependabot"
- name: Get PR info for manual dispatch
if: github.event_name == 'workflow_dispatch'
id: pr_info
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER_INPUT: ${{ github.event.inputs.pr_number }}
REPO: ${{ github.repository }}
run: |
# Get PR details and set outputs
PR_DATA=$(gh pr view "$PR_NUMBER_INPUT" --repo "$REPO" --json number,url,author)
echo "pr_number=$(echo "$PR_DATA" | jq -r '.number')" >> $GITHUB_OUTPUT
echo "pr_url=$(echo "$PR_DATA" | jq -r '.url')" >> $GITHUB_OUTPUT
- uses: frequenz-floss/dependabot-auto-approve@v1
with:
dependency-type: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dependency_type || 'direct:production' }}
merge-method: 'squash'
add-label: ${{ github.event_name == 'workflow_dispatch' && 'manual-approval' || 'dependabot-approved' }}
pr-number: ${{ github.event_name == 'workflow_dispatch' && steps.pr_info.outputs.pr_number || '' }}
pr-url: ${{ github.event_name == 'workflow_dispatch' && steps.pr_info.outputs.pr_url || '' }}MIT License