Skip to content

fix(ci): Dependabot auto-merge via GitHub App with ruleset bypass - #71

Merged
petry-projects-dependabot-automrg[bot] merged 5 commits into
mainfrom
fix/dependabot-automerge-ruleset-bypass
Mar 23, 2026
Merged

fix(ci): Dependabot auto-merge via GitHub App with ruleset bypass#71
petry-projects-dependabot-automrg[bot] merged 5 commits into
mainfrom
fix/dependabot-automerge-ruleset-bypass

Conversation

@don-petry

@don-petry don-petry commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

Dependabot PRs #68, #69, #70 had auto-merge enabled and all checks passing, yet remained in BLOCKED merge state indefinitely. Investigation revealed auto-merge has never worked — all past Dependabot PRs were merged manually.

Root cause

The protect-branches ruleset grants bypass only to RepositoryRole 5 (admin) and Integration 29110. The workflow used GITHUB_TOKEN, which runs as github-actions[bot] (Integration 15368) — not in the bypass list. GitHub's auto-merge executes as the token's actor, so it silently stalled against the ruleset.

Secondary bug

The immediate-merge fallback compared mergeable to "true", but gh pr view --json mergeable returns "MERGEABLE" — so the fallback never fired either.

Solution

Created an org-wide GitHub App (dependabot-automerge-petry, ID: 3167543) that:

  • Generates short-lived tokens via actions/create-github-app-token@v1
  • Approves the PR, then merges with --admin to bypass the ruleset
  • Is added to the ruleset bypass list for repos that have rulesets

Key finding during testing

--auto (GitHub's auto-merge) still respects ruleset rules even when the actor is in the bypass list. Only --admin (immediate admin merge) triggers the bypass. This means the workflow merges immediately after checks pass rather than waiting for auto-merge.

Changes

  • .github/workflows/dependabot-automerge.yml — replaced GITHUB_TOKEN + --auto with GitHub App token + --admin
  • scripts/setup-dependabot-app.sh — per-repo setup script for deploying to other org repos

Verified

PR Status
#68 (eslint 10.1.0) Merged by app/dependabot-automerge-petry
#69 (@typescript-eslint/eslint-plugin 8.57.1) Merged by app/dependabot-automerge-petry
#70 (@typescript-eslint/parser 8.57.1) Merge conflict (Dependabot will rebase)

🤖 Generated with Claude Code

The GITHUB_TOKEN runs as github-actions[bot] (integration 15368) which
is not in the repository ruleset bypass list. Auto-merge silently stalls
because the merge actor cannot bypass the protect-branches ruleset.

Switch to GH_ADMIN_PAT so merges execute as a repo admin with bypass
permissions, and add a PR approval step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 23, 2026 03:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Dependabot auto-merge GitHub Actions workflow to unblock merges that are currently stalled due to branch ruleset bypass restrictions when running as github-actions[bot].

Changes:

  • Switch gh authentication from secrets.GITHUB_TOKEN to an admin-scoped secrets.GH_ADMIN_PAT for auto-merge operations.
  • Add an explicit gh pr review --approve step before enabling auto-merge.
  • Remove the previous “immediate merge fallback” logic.

Comment on lines +34 to +36
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GH_ADMIN_PAT }}

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

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

GH_TOKEN: ${{ secrets.GH_ADMIN_PAT }} is used in a workflow triggered by on: pull_request from Dependabot. GitHub Actions does not provide repository secrets to workflows triggered by Dependabot on pull_request, so GH_ADMIN_PAT will be empty and the gh pr review/merge commands will fail to authenticate. Consider switching this workflow to pull_request_target (keeping the Dependabot actor guard) so the secret is available, or use a non-secret approach such as adding the GitHub Actions integration to the ruleset bypass list so GITHUB_TOKEN can merge without a PAT.

Copilot uses AI. Check for mistakes.
Don Petry and others added 3 commits March 22, 2026 22:49
The GITHUB_TOKEN runs as github-actions[bot] (integration 15368) which
is not in the repository ruleset bypass list. Auto-merge silently stalls
because the merge actor cannot bypass the protect-branches ruleset.

Create a dedicated GitHub App with contents:write and pull_requests:write
permissions. The workflow generates short-lived tokens via
actions/create-github-app-token, and the app is added to the ruleset
bypass list so auto-merge can execute.

Includes setup script: scripts/setup-dependabot-app.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The GitHub App manifest flow had HTML encoding issues, so the app was
created manually. Replace the setup script with a practical per-repo
version that stores secrets and updates the ruleset bypass list for any
repo in the org where the app is already installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ruleset bypass list grants the app admin-level merge permissions,
but --auto still respects ruleset rules. Use --admin to bypass the
ruleset directly, matching how the app's bypass_mode is configured.

Tested: PRs #68 and #69 merged successfully via app token + --admin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@don-petry don-petry changed the title fix(ci): use admin PAT for Dependabot auto-merge to bypass ruleset fix(ci): Dependabot auto-merge via GitHub App with ruleset bypass Mar 23, 2026
Dependabot-triggered pull_request events do not have access to
repository secrets. Switch to pull_request_target which runs in the
context of the base branch and can access APP_ID and APP_PRIVATE_KEY.

This is safe because the workflow only targets dependabot[bot] PRs
and does not checkout any PR code.

Addresses Copilot review comment on PR #71.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@petry-projects-dependabot-automrg
petry-projects-dependabot-automrg Bot merged commit 6637739 into main Mar 23, 2026
5 checks passed
@petry-projects-dependabot-automrg
petry-projects-dependabot-automrg Bot deleted the fix/dependabot-automerge-ruleset-bypass branch March 23, 2026 19:32
don-petry added a commit that referenced this pull request Mar 28, 2026
* fix(ci): use admin PAT for Dependabot auto-merge to bypass ruleset

The GITHUB_TOKEN runs as github-actions[bot] (integration 15368) which
is not in the repository ruleset bypass list. Auto-merge silently stalls
because the merge actor cannot bypass the protect-branches ruleset.

Switch to GH_ADMIN_PAT so merges execute as a repo admin with bypass
permissions, and add a PR approval step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): use GitHub App for Dependabot auto-merge to bypass ruleset

The GITHUB_TOKEN runs as github-actions[bot] (integration 15368) which
is not in the repository ruleset bypass list. Auto-merge silently stalls
because the merge actor cannot bypass the protect-branches ruleset.

Create a dedicated GitHub App with contents:write and pull_requests:write
permissions. The workflow generates short-lived tokens via
actions/create-github-app-token, and the app is added to the ruleset
bypass list so auto-merge can execute.

Includes setup script: scripts/setup-dependabot-app.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): replace manifest-flow script with per-repo setup script

The GitHub App manifest flow had HTML encoding issues, so the app was
created manually. Replace the setup script with a practical per-repo
version that stores secrets and updates the ruleset bypass list for any
repo in the org where the app is already installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): use --admin merge instead of --auto for ruleset bypass

The ruleset bypass list grants the app admin-level merge permissions,
but --auto still respects ruleset rules. Use --admin to bypass the
ruleset directly, matching how the app's bypass_mode is configured.

Tested: PRs #68 and #69 merged successfully via app token + --admin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): use pull_request_target for Dependabot secret access

Dependabot-triggered pull_request events do not have access to
repository secrets. Switch to pull_request_target which runs in the
context of the base branch and can access APP_ID and APP_PRIVATE_KEY.

This is safe because the workflow only targets dependabot[bot] PRs
and does not checkout any PR code.

Addresses Copilot review comment on PR #71.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(deploy): create Gmail labels from Step 3 Config UI

Allow users to create new Gmail labels directly from the configuration
form instead of switching to Gmail. Adds "+ New Label" button next to
both trigger and processed label dropdowns with inline input, API
creation via gmail.labels scope, automatic list refresh, and
auto-selection of the newly created label.

Closes #78

* chore(ci): apply prettier/eslint auto-fixes

* fix(deploy): surface sign-in error and remove redundant catch-rethrow

Address PR review feedback: throw a user-friendly error when accessToken
is missing instead of silently returning null, and remove the no-op
catch-rethrow wrapper.

* chore(ci): apply prettier/eslint auto-fixes

* fix(deploy): address PR review comments

- Fix JSDoc to match actual throw behavior (no longer returns null)
- Throw on missing labelName instead of returning null silently
- Escape IDs via escapeHtml() in inline onclick handlers for defense in depth
- Expose showNewLabelInput, hideNewLabelInput, handleCreateLabel on window
  for consistency with browseForFile and confirmSetupDone
- Consolidate createGmailLabel import to top of test file

* fix(deploy): show New Label button in text-input fallback mode

The + New Label button was only shown when Gmail labels were loaded
(select dropdown mode). Now it also appears in the text-input fallback
that renders when labels haven't loaded yet or when the user has no
existing labels. Also handles auto-filling text inputs after creation.

* chore(ci): apply prettier/eslint auto-fixes

* feat(deploy): replace inline label buttons with New Label modal

Redesign the label creation UX per user feedback:
- Single "New Label" button at the top of the Gmail to Drive config section
- Modal popup that creates both the trigger label and its -archived
  counterpart in one action
- Live preview showing both labels as user types
- Auto-selects both labels in the config dropdowns after creation
- Supports Enter key, Escape to close, and overlay click to dismiss

* chore(ci): apply prettier/eslint auto-fixes

* fix(deploy): address CodeRabbit review — modal close helper, idempotent label creation

- Remove escapeHtml from thrown error messages (rendered via textContent)
- Add shared closeModal helper with isCreating guard to prevent
  closing during label creation and fix leaked keydown listener
- Make two-label creation idempotent: treat 409/duplicate as success,
  add labels to userGmailLabels on each step, so retries after partial
  failure work correctly
- Surface isDuplicate and status on error objects for caller detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Don Petry <don.petry@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: DJ <dj@Rachels-Air.localdomain>
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.

2 participants