Skip to content

Auto-merge workflow - #6

Merged
greenc-FNAL merged 1 commit into
mainfrom
maintenance/dependabot-auto-merge
Jun 16, 2026
Merged

greenc-FNAL merged 1 commit into
mainfrom
maintenance/dependabot-auto-merge

Conversation

@greenc-FNAL

@greenc-FNAL greenc-FNAL commented Jun 16, 2026 •

Copy link
Copy Markdown
Contributor

CI/Automation

  • Added new GitHub Actions workflow for automatic merging of Dependabot pull requests targeting the main branch
  • Triggers on three event types: pull_request_target (opened, reopened, synchronize), pull_request_review (submitted), and check_suite (completed)
  • Conditionally executes only for Dependabot PRs against main branch, with additional check for check_suite events whose head branch starts with dependabot/

Security

  • Uses pull_request_target event with elevated permissions (contents:write, pull-requests:write) instead of pull_request for secure Dependabot integration
  • Includes explicit safety documentation: verifies PR author is dependabot[bot], does not check out or run code from the PR, relies on branch protection for safety
  • Authenticates merge operations using WORKFLOW_PAT secret rather than default GITHUB_TOKEN

External API Integration

  • Uses GitHub CLI (gh) for all repository interactions: PR viewing, merging, API patching, and commenting
  • Parses GitHub event payloads with jq to extract PR metadata (author, base_ref, number)
  • For check_suite events, queries PR details via gh pr view since this event type doesn't include full PR metadata
  • Executes gh pr merge --auto --rebase to enable auto-merge functionality

Error Handling & Robustness

  • Gracefully handles non-critical failure scenarios: auto-merge already enabled, unmet required status checks, or pending required approvals
  • Detects and remediates disabled repository-level "Allow auto-merge" setting by patching the repository configuration and retrying the merge operation once
  • Detects concurrent merge race condition ("Base branch was modified") and requests a Dependabot rebase via @dependabot rebase comment, allowing the workflow to re-trigger automatically via check_suite event when rebased branch passes checks; supports N concurrent Dependabot PRs converging in N-1 rounds
  • Reports unexpected errors with full diagnostic output before failing the workflow

@coderabbitai

coderabbitai Bot commented Jun 16, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new GitHub Actions workflow file is added that auto-merges Dependabot PRs into main using rebase strategy. It triggers on PR, review, and check-suite events, resolves PR metadata via gh CLI and jq, and handles edge cases including disabled repo auto-merge settings, concurrent base-branch races, and unmet branch protection requirements.

Changes

Dependabot Auto-Merge Workflow

Layer / File(s) Summary
Workflow triggers, permissions, and job gate
.github/workflows/dependabot-auto-merge.yaml
Registers pull_request_target, pull_request_review, and check_suite completion triggers with write permissions for contents and pull-requests; job-level if condition restricts execution to Dependabot actors targeting main (with special handling for check_suite head-branch naming).
PR detail resolution
.github/workflows/dependabot-auto-merge.yaml
"Get PR details" step emits author, base_ref, and number to $GITHUB_OUTPUT by branching on event type: gh pr view + jq for check_suite, direct payload field reads for PR events.
Auto-merge enablement and error branching
.github/workflows/dependabot-auto-merge.yaml
"Enable auto-merge" step runs gh pr merge --auto --rebase, then inspects captured output to classify outcomes: clean exit for success/already-enabled/unmet-requirements, repo-level allow_auto_merge patch + one retry when disallowed, @dependabot rebase comment on base-branch race, and hard failure for anything unexpected.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title "Auto-merge workflow" is vague and overly generic, lacking specificity about what the workflow actually does or which tool it integrates with. Consider a more descriptive title like "Add Dependabot auto-merge workflow" or "Enable auto-merge for Dependabot PRs" to clarify the specific change.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch maintenance/dependabot-auto-merge

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/dependabot-auto-merge.yaml:
- Around line 15-17: Add inline comments above each permission in the
permissions block to document their purpose. For the contents: write permission,
explain that it is required for the gh pr merge command and patching the
repository allow_auto_merge setting. For the pull-requests: write permission,
explain that it is required for enabling auto-merge and posting `@dependabot`
rebase comments. These comments should precede each permission on the line above
to clarify the rationale without requiring readers to trace through the workflow
steps.
- Around line 64-66: The `WORKFLOW_PAT` secret used in the workflow environment
needs to be verified to have the appropriate scopes and permissions to enable
auto-merge functionality. Ensure that the `WORKFLOW_PAT` secret configured in
the repository settings has the `repo` scope (or at minimum `public_repo` for
public repositories) and admin access to the repository, which is required for
the auto-merge PATCH operation to succeed. Consider adding a comment above the
env section in the dependabot-auto-merge.yaml workflow to document why a custom
PAT is needed instead of the default GITHUB_TOKEN, to help future maintainers
understand the setup requirements.
- Around line 1-13: Add a concurrency group to the dependabot-auto-merge
workflow to prevent race conditions when multiple runs execute concurrently. Add
a concurrency section at the workflow level (after the "on" trigger definition)
with a group key that uses the pull request number for pull_request events and
falls back to the check_suite head_branch for check_suite events, and set
cancel-in-progress to false to ensure each run completes fully rather than being
canceled mid-flight, preventing partial state changes.
- Around line 19-21: The dependabot job in the workflow is missing a descriptive
name field, making it harder to identify in the GitHub Actions UI. Add a `name`
field to the dependabot job with a clear, descriptive value (such as "Auto-merge
Dependabot PRs") positioned after the job key and before the `runs-on` field to
improve visibility and clarity when monitoring or debugging workflow execution.
- Around line 108-113: The `gh pr comment` command on line 110 silently fails
due to the `|| true` clause, which means if posting the `@dependabot rebase`
comment fails (rate limit, network issue, permissions), the workflow exits
successfully without logging the failure, leaving the PR stuck without
visibility. Add logging to capture and display the error when the comment
command fails, while keeping the `|| true` to prevent the workflow from exiting
with a failure status. This way, the workflow continues (since the comment isn't
strictly required for forward progress), but failures are visible in the logs
for debugging purposes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7f2c5a75-6c72-4cf5-aa04-ac3c9cc0ad7c

📥 Commits

Reviewing files that changed from the base of the PR and between 24944d0 and 7395c2b.

📒 Files selected for processing (1)
  • .github/workflows/dependabot-auto-merge.yaml
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: codeql
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/dependabot-auto-merge.yaml

[error] 16-16: overly broad permissions (excessive-permissions): contents: write is overly broad at the workflow level

(excessive-permissions)


[error] 17-17: overly broad permissions (excessive-permissions): pull-requests: write is overly broad at the workflow level

(excessive-permissions)


[error] 2-13: use of fundamentally insecure workflow trigger (dangerous-triggers): pull_request_target is almost always used insecurely

(dangerous-triggers)


[warning] 16-16: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)


[info] 20-20: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)


[warning] 2-13: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🔇 Additional comments (1)
.github/workflows/dependabot-auto-merge.yaml (1)

29-59: LGTM!

Comment on lines +1 to +13
name: Dependabot auto-merge
"on":
# Use pull_request_target instead of pull_request to get elevated permissions
# This is safe for Dependabot PRs because:
# 1. We verify the PR author is dependabot[bot]
# 2. We don't check out or run code from the PR
# 3. We only enable auto-merge, which requires branch protection to pass
pull_request_target:
types: [opened, reopened, synchronize]
pull_request_review:
types: [submitted]
check_suite:
types: [completed]

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 | ⚡ Quick win

Add a concurrency group to prevent race conditions.

Without a concurrency limit, multiple workflow runs triggered by concurrent Dependabot PRs or rapid event sequences can step on each other—especially when toggling allow_auto_merge or racing through the "Base branch was modified" path. This could leave you in a weird state where one run's retry collides with another run's attempt.

A simple group keyed on PR number (with check_suite falling back to branch) should serialize runs for the same PR:

concurrency:
  group: dependabot-auto-merge-${{ github.event.pull_request.number || github.event.check_suite.head_branch }}
  cancel-in-progress: false

Using cancel-in-progress: false lets each run complete rather than canceling mid-flight (which could leave things half-done).

🧰 Tools
🪛 zizmor (1.25.2)

[error] 2-13: use of fundamentally insecure workflow trigger (dangerous-triggers): pull_request_target is almost always used insecurely

(dangerous-triggers)


[warning] 2-13: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dependabot-auto-merge.yaml around lines 1 - 13, Add a
concurrency group to the dependabot-auto-merge workflow to prevent race
conditions when multiple runs execute concurrently. Add a concurrency section at
the workflow level (after the "on" trigger definition) with a group key that
uses the pull request number for pull_request events and falls back to the
check_suite head_branch for check_suite events, and set cancel-in-progress to
false to ensure each run completes fully rather than being canceled mid-flight,
preventing partial state changes.

Source: Linters/SAST tools

Comment on lines +15 to +17
permissions:
contents: write
pull-requests: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Document why these permissions are needed.

Zizmor flags these as undocumented. While both permissions are legitimately required here (contents: write for the repo settings PATCH and merge operation, pull-requests: write for merge and commenting), adding brief comments helps future you (or anyone else) understand the rationale without spelunking through the steps:

permissions:
  # Required for gh pr merge and patching repository allow_auto_merge setting
  contents: write
  # Required for enabling auto-merge and posting `@dependabot` rebase comments
  pull-requests: write

You could also scope these to the job level for marginally tighter blast radius, though with a single job it's mostly ceremonial.

🧰 Tools
🪛 zizmor (1.25.2)

[error] 16-16: overly broad permissions (excessive-permissions): contents: write is overly broad at the workflow level

(excessive-permissions)


[error] 17-17: overly broad permissions (excessive-permissions): pull-requests: write is overly broad at the workflow level

(excessive-permissions)


[warning] 16-16: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dependabot-auto-merge.yaml around lines 15 - 17, Add
inline comments above each permission in the permissions block to document their
purpose. For the contents: write permission, explain that it is required for the
gh pr merge command and patching the repository allow_auto_merge setting. For
the pull-requests: write permission, explain that it is required for enabling
auto-merge and posting `@dependabot` rebase comments. These comments should
precede each permission on the line above to clarify the rationale without
requiring readers to trace through the workflow steps.

Source: Linters/SAST tools

Comment on lines +19 to +21
jobs:
dependabot:
runs-on: ubuntu-latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider adding a descriptive job name.

The job is currently anonymous. Adding a name field improves readability in the GitHub Actions UI and makes it clearer what's happening when you're debugging a stuck merge:

 jobs:
   dependabot:
+    name: Enable auto-merge for Dependabot PRs
     runs-on: ubuntu-latest

Purely cosmetic, but your future self debugging at 11pm will thank you.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jobs:
dependabot:
runs-on: ubuntu-latest
jobs:
dependabot:
name: Enable auto-merge for Dependabot PRs
runs-on: ubuntu-latest
🧰 Tools
🪛 zizmor (1.25.2)

[info] 20-20: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dependabot-auto-merge.yaml around lines 19 - 21, The
dependabot job in the workflow is missing a descriptive name field, making it
harder to identify in the GitHub Actions UI. Add a `name` field to the
dependabot job with a clear, descriptive value (such as "Auto-merge Dependabot
PRs") positioned after the job key and before the `runs-on` field to improve
visibility and clarity when monitoring or debugging workflow execution.

Source: Linters/SAST tools

Comment on lines +64 to +66
env:
PR_NUMBER: ${{ steps.pr.outputs.number }}
GH_TOKEN: ${{ secrets.WORKFLOW_PAT }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Quick note: WORKFLOW_PAT needs appropriate scopes.

You're using a separate PAT rather than GITHUB_TOKEN here—presumably because the default token can't enable auto-merge or patch repo settings in all scenarios. Just confirming that WORKFLOW_PAT needs:

  • repo scope (or at minimum public_repo for public repos)
  • For the allow_auto_merge PATCH, admin access to the repository

If this secret isn't configured or has insufficient scopes, the workflow will fail somewhat opaquely. Might be worth a brief comment or a check that the secret exists (though GitHub will fail fast if it doesn't).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dependabot-auto-merge.yaml around lines 64 - 66, The
`WORKFLOW_PAT` secret used in the workflow environment needs to be verified to
have the appropriate scopes and permissions to enable auto-merge functionality.
Ensure that the `WORKFLOW_PAT` secret configured in the repository settings has
the `repo` scope (or at minimum `public_repo` for public repositories) and admin
access to the repository, which is required for the auto-merge PATCH operation
to succeed. Consider adding a comment above the env section in the
dependabot-auto-merge.yaml workflow to document why a custom PAT is needed
instead of the default GITHUB_TOKEN, to help future maintainers understand the
setup requirements.

Comment on lines +108 to +113
if grep -qF "Base branch was modified" /tmp/gh-output.txt; then
echo "Base branch was modified by a concurrent merge. Requesting Dependabot rebase..."
gh pr comment "${PR_NUMBER}" --repo "$GITHUB_REPOSITORY" --body "@dependabot rebase" || true
echo "Rebase requested; workflow will re-trigger when the rebased branch passes checks."
exit 0
fi

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 | ⚡ Quick win

Silent comment failure could leave PR stuck without visibility.

The || true on line 110 means if posting the @dependabot rebase comment fails (rate limit, network blip, permissions issue), the workflow exits successfully but Dependabot never gets the message. The PR just... sits there waiting for a rebase that was never requested.

Consider at least logging when this fails so it's visible in the workflow logs:

-            gh pr comment "${PR_NUMBER}" --repo "$GITHUB_REPOSITORY" --body "`@dependabot` rebase" || true
+            if ! gh pr comment "${PR_NUMBER}" --repo "$GITHUB_REPOSITORY" --body "`@dependabot` rebase"; then
+              echo "::warning::Failed to post `@dependabot` rebase comment. PR may need manual attention."
+            fi

This keeps the workflow from failing hard (since the comment isn't strictly required for forward progress—Dependabot might pick it up via other triggers), but gives you breadcrumbs when debugging why a PR went stale.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dependabot-auto-merge.yaml around lines 108 - 113, The `gh
pr comment` command on line 110 silently fails due to the `|| true` clause,
which means if posting the `@dependabot rebase` comment fails (rate limit,
network issue, permissions), the workflow exits successfully without logging the
failure, leaving the PR stuck without visibility. Add logging to capture and
display the error when the comment command fails, while keeping the `|| true` to
prevent the workflow from exiting with a failure status. This way, the workflow
continues (since the comment isn't strictly required for forward progress), but
failures are visible in the logs for debugging purposes.

@greenc-FNAL
greenc-FNAL merged commit 8cea618 into main Jun 16, 2026
8 checks passed
@greenc-FNAL

Copy link
Copy Markdown
Contributor Author

@dependabot recreate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant