Table of Contents
In the previous posts, we learned about SOPs and automation methods for efficiently handling Dependabot PRs.
- SOP(Standard Operating Procedure) for Handling Dependabot PRs
- Automation for Handling Dependabot PRs
In this post, we will look at the problems encountered while operating Dependabot in a Yarn Workspaces-based monorepo and how to solve them.
Background
While operating Dependabot in a Yarn Workspaces-based monorepo, two issues occurred simultaneously.
- Symptom 1:
@dependabot rebasefailure
Oh no! Something went wrong on our end. Please try again later.
If the problem persists, please contact GitHub support for assistance
- Symptom 2: Dependabot unable to update its own branch
Dependabot attempted to update this pull request, but because the branch
dependabot/github_actions/github-actions-946974bce4 is protected
it was unable to do so.
After investigating, we found that Branch Protection Rules and GitHub Actions lockfile update method were both involved.
Problem 1: Branch Protection Rule Protecting Dependabot Branches
Cause
The repository had a Branch Protection Rule with the **/** pattern. Since this wildcard pattern matches all branches, dependabot/... branches were also included in the protection scope.
# Existing Branch Protection Rules
**/** → All branches (including Dependabot) ← Root cause
develop → develop branch only
main → main branch only
When Dependabot branches are protected, Dependabot cannot push to its own branch, making rebase and updates impossible.
Solution: Split **/** into Specific Patterns
Branch Protection Rules do not support an exclude feature. Therefore, it is impossible to exclude only dependabot/** from **/**.
The solution is to delete the **/** rule and create individual rules for only the branch patterns that need protection. In our project, branch naming follows the {prefix}/{service}/{description} format, so we created rules for each prefix.
# Branch Protection Rules After Change
hotfix/** ← New
release/** ← New
review/** ← New
feature/** ← New
fix/** ← New
sub-feature/** ← New
merge/** ← New
develop ← Existing
main ← Existing
Since we don’t create a dependabot/** pattern, Dependabot branches are naturally excluded from protection.
Bulk Creation with GitHub GraphQL API
Creating 7 rules manually is tedious, so we used the GraphQL API for bulk creation.
# Get repository ID
REPO_ID=$(gh api graphql -f query='
{ repository(owner: "ORG_NAME", name: "REPO_NAME") { id } }
' --jq '.data.repository.id')
# Get bypass user Node IDs
gh api "users/USERNAME" --jq '.node_id'
# Bulk create 7 rules
for pattern in "hotfix/**" "release/**" "review/**" \
"feature/**" "fix/**" "sub-feature/**" "merge/**"; do
gh api graphql -f query='
mutation {
createBranchProtectionRule(input: {
repositoryId: "'"$REPO_ID"'"
pattern: "'"$pattern"'"
requiresApprovingReviews: true
requiredApprovingReviewCount: 2
requiresCodeOwnerReviews: true
dismissesStaleReviews: false
requiresConversationResolution: true
requiresStatusChecks: true
requiredStatusCheckContexts: []
allowsForcePushes: true
allowsDeletions: true
isAdminEnforced: false
bypassPullRequestActorIds: ["USER_NODE_ID_1", "USER_NODE_ID_2"]
}) {
branchProtectionRule { id pattern }
}
}'
done
After creating all new rules, delete the existing **/** rule.
# Get existing rule IDs
gh api graphql -f query='{
repository(owner: "ORG_NAME", name: "REPO_NAME") {
branchProtectionRules(first: 20) {
nodes { pattern id }
}
}
}'
# Delete
gh api graphql -f query='
mutation {
deleteBranchProtectionRule(input: {
branchProtectionRuleId: "BPR_XXXXXXXXX"
}) { clientMutationId }
}'
Alternative: Using Rulesets
GitHub’s new Rulesets feature allows you to specify exclude patterns. You can include ~ALL (all branches) and exclude refs/heads/dependabot/**/*.
However, Rulesets and Branch Protection Rules operate independently (additive). Even if you add Rulesets, existing Branch Protection Rules still apply, so you must delete the existing **/** rule.
Also note that the Rulesets Bypass list cannot add individual users directly - it only supports Repository Role, Team, and GitHub App units.
Verification
After the change, verify the protection status of Dependabot branches.
gh api "repos/ORG/REPO/branches/dependabot%2F..." --jq '.protected'
# false → Success
Problem 2: GitHub Actions Lockfile Update Blocking Dependabot Rebase
Even after resolving the Branch Protection Rule issue, @dependabot rebase still failed.
Looks like this PR has been edited by someone other than Dependabot.
That means Dependabot can't rebase it - sorry!
Cause
In a monorepo, Dependabot only updates each app’s package.json but cannot update the root yarn.lock. To compensate, the GitHub Actions workflow introduced in the previous post ran yarn install and committed the yarn.lock changes.
# dependabot_actions.yml
- name: Commit updated lockfile
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add yarn.lock
git diff --staged --quiet || git commit -m "chore: update yarn.lock"
git push
This results in the following commit history on the Dependabot branch:
| Commit | Author |
|---|---|
deps(pos): bump @types/node... | dependabot[bot] |
chore: update yarn.lock | github-actions[bot] |
Dependabot tracks the HEAD SHA it pushed on the server side. When the HEAD SHA changes due to additional commits, regardless of the commit author, it determines “edited by someone other than Dependabot” and refuses to rebase.
Solution: [dependabot skip] Commit Message
The GitHub official documentation provides a solution for this problem. By including [dependabot skip] in the commit message, Dependabot treats the commit as a “temporary commit” and overwrites it with a force-push during rebase.
# Before
git diff --staged --quiet || git commit -m "chore: update yarn.lock"
# After
git diff --staged --quiet || git commit -m "[dependabot skip] chore: update yarn.lock"
How It Works
1. Dependabot creates PR → Commit A
2. GitHub Action updates yarn.lock → Commit B [dependabot skip]
3. @dependabot rebase executed
4. Dependabot performs rebase → Commit A' (Commit B removed by force-push)
5. synchronize event triggered
6. GitHub Action runs again → Commit B' [dependabot skip]
The [dependabot skip] commit disappears during rebase, but since the workflow reacts to the synchronize event, it is automatically recreated.
Handling Existing PRs
Existing PRs that already have commits pushed without [dependabot skip] cannot use @dependabot rebase. In this case, you need to recreate the PR with @dependabot recreate.
Summary
| Problem | Cause | Solution |
|---|---|---|
| Dependabot unable to update branch | **/** Branch Protection Rule protecting Dependabot branches | Split into specific branch patterns to exclude Dependabot branches from protection |
@dependabot rebase failure | GitHub Actions lockfile update commit interfering with Dependabot’s HEAD SHA tracking | Add [dependabot skip] to commit message |
References
- GitHub Docs - Managing pull requests for dependency updates
- dependabot-core #2798 - Add commit on dependabot pull request
- dependabot-core #2267 - Ability to ignore CI-generated commits
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku.Deku created the applications with Flutter.If you have interested, please try to download them for free.