Skip to content

Commit 76832dd

Browse files
committed
fix: auto-detect merge strategy in workflow templates
GitHub cannot auto-sign rebased commits, so repos with branch protection requiring signed commits block --rebase merges. Updated templates to auto-detect the allowed merge strategy (squash > merge > rebase) instead of hardcoding a specific strategy. Also added documentation about signed commit + rebase incompatibility and the auto-detection pattern to the auto-merge guide. Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
1 parent 2b486c9 commit 76832dd

3 files changed

Lines changed: 66 additions & 20 deletions

File tree

skills/github-project/assets/auto-merge-direct.yml.template

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
# Use this template when: Repository has no branch protection rules
44
# Note: --auto flag requires branch protection; this template uses direct merge
55
# Note: PRs that modify workflow files require manual merge (GITHUB_TOKEN limitation)
6-
# IMPORTANT: The merge method (--merge/--squash/--rebase) in the "Merge PR" step
7-
# MUST match the repository's allowed merge methods. Check Settings > General > Pull Requests.
6+
# Merge strategy is auto-detected from repo settings (squash > merge > rebase).
87
name: Auto-merge dependency PRs
98

109
on:
@@ -88,10 +87,20 @@ jobs:
8887

8988
- name: Merge PR
9089
if: steps.check-workflows.outputs.modifies_workflows != 'true'
91-
run: gh pr merge --rebase "$PR_URL"
9290
env:
9391
PR_URL: ${{ github.event.pull_request.html_url }}
9492
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
93+
run: |
94+
# Detect allowed merge strategy
95+
# Prefer squash (works with signed commit requirements, clean for single-commit PRs)
96+
# then merge (also works with signed commits), then rebase (cannot be auto-signed)
97+
STRATEGY=$(gh api "repos/${{ github.repository }}" --jq '
98+
if .allow_squash_merge then "--squash"
99+
elif .allow_merge_commit then "--merge"
100+
elif .allow_rebase_merge then "--rebase"
101+
else "--squash" end')
102+
echo "Using merge strategy: $STRATEGY"
103+
gh pr merge $STRATEGY "$PR_URL"
95104

96105
- name: Comment on workflow PR
97106
if: steps.check-workflows.outputs.modifies_workflows == 'true'
Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
# .github/workflows/auto-merge.yml
1+
# .github/workflows/auto-merge-deps.yml
22
# Auto-merge dependency updates from Dependabot and Renovate
33
# Requires: branch protection enabled (--auto flag needs it)
4-
# IMPORTANT: The merge method (--merge/--squash/--rebase) MUST match the
5-
# repository's allowed merge methods. Check Settings > General > Pull Requests.
6-
name: Auto-merge dependency updates
4+
# Merge strategy is auto-detected from repo settings (squash > merge > rebase)
5+
name: Auto-merge dependency PRs
76

87
on:
98
pull_request_target:
109
types: [opened, synchronize, reopened]
1110

1211
permissions:
13-
contents: write
14-
pull-requests: write
12+
contents: read
1513

1614
jobs:
1715
auto-merge:
@@ -23,28 +21,34 @@ jobs:
2321
github.event.pull_request.user.login == 'dependabot[bot]' ||
2422
github.event.pull_request.user.login == 'renovate[bot]'
2523

24+
permissions:
25+
contents: write
26+
pull-requests: write
27+
2628
steps:
2729
- name: Harden Runner
2830
uses: step-security/harden-runner@v2
2931
with:
3032
egress-policy: audit
3133

32-
- name: Dependabot metadata
33-
id: metadata
34-
if: github.event.pull_request.user.login == 'dependabot[bot]'
35-
uses: dependabot/fetch-metadata@v2
36-
with:
37-
github-token: "${{ secrets.GITHUB_TOKEN }}"
38-
39-
- name: Auto-approve PR
34+
- name: Approve PR
4035
run: gh pr review --approve "$PR_URL"
4136
env:
4237
PR_URL: ${{ github.event.pull_request.html_url }}
4338
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4439

4540
- name: Enable auto-merge
46-
# Change --squash to --merge or --rebase to match repo settings
47-
run: gh pr merge --auto --squash "$PR_URL"
4841
env:
4942
PR_URL: ${{ github.event.pull_request.html_url }}
5043
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
run: |
45+
# Detect allowed merge strategy
46+
# Prefer squash (works with signed commit requirements, clean for single-commit PRs)
47+
# then merge (also works with signed commits), then rebase (cannot be auto-signed)
48+
STRATEGY=$(gh api "repos/${{ github.repository }}" --jq '
49+
if .allow_squash_merge then "--squash"
50+
elif .allow_merge_commit then "--merge"
51+
elif .allow_rebase_merge then "--rebase"
52+
else "--squash" end')
53+
echo "Using merge strategy: $STRATEGY"
54+
gh pr merge --auto $STRATEGY "$PR_URL"

skills/github-project/references/auto-merge-guide.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ EOF
4444
| Renovate PR not using bypass | Workflow racing with Renovate | Only approve in workflow; let Renovate enable auto-merge via `platformAutomerge` |
4545
| CI can't push to main | Branch protection blocks direct push | Use Renovate `lockFileMaintenance` instead |
4646
| Workflow not triggering | Rapid merges skip push events | Add `workflow_dispatch` trigger, run manually |
47-
| "Merge method X not allowed" | Wrong merge strategy | Check `gh api repos/O/R --jq '{merge: .allow_merge_commit, squash: .allow_squash_merge, rebase: .allow_rebase_merge}'`; match workflow |
47+
| "Merge method X not allowed" | Wrong merge strategy | Use auto-detection (see below) or check `gh api repos/O/R --jq '{merge: .allow_merge_commit, squash: .allow_squash_merge, rebase: .allow_rebase_merge}'` |
48+
| "Rebase merges cannot be automatically signed" | Signed commits + rebase | Enable squash merge on the repo; rebase merges cannot be auto-signed by GitHub |
4849
| Bot detection misses reruns | `github.actor` changes on synchronize | Use `github.event.pull_request.user.login` instead of `github.actor` |
4950
| Gitleaks fails on bot PRs | `GITLEAKS_LICENSE` secret unavailable | Skip gitleaks for bot PRs or use `.gitleaks.toml` allowlist |
5051
| Old PRs not auto-merging | Opened before workflow existed | Comment `@dependabot rebase` / `@renovate rebase` to trigger `synchronize` |
@@ -138,6 +139,38 @@ When landing multiple dependent PRs, expect the dependent PRs to need rebasing a
138139
| `REVIEW_REQUIRED` after rebase | Stale review dismissal cleared approval | Re-run auto-approve workflow |
139140
| Unresolved threads block merge | Old threads survive rebase | Resolve via GraphQL `resolveReviewThread` |
140141

142+
## Signed Commits and Merge Strategy Compatibility
143+
144+
GitHub can only auto-sign **merge commits** and **squash merges**. It **cannot** auto-sign rebased commits. If branch protection requires signed commits and the workflow uses `--rebase`, merges fail with:
145+
146+
> `Base branch requires signed commits. Rebase merges cannot be automatically signed by GitHub.`
147+
148+
### Auto-detect Merge Strategy
149+
150+
Instead of hardcoding `--merge`, `--squash`, or `--rebase`, auto-detect from repo settings:
151+
152+
```bash
153+
STRATEGY=$(gh api "repos/${{ github.repository }}" --jq '
154+
if .allow_squash_merge then "--squash"
155+
elif .allow_merge_commit then "--merge"
156+
elif .allow_rebase_merge then "--rebase"
157+
else "--squash" end')
158+
gh pr merge --auto $STRATEGY "$PR_URL"
159+
```
160+
161+
**Priority order:** squash > merge > rebase. Squash is preferred because:
162+
1. Works with signed commit requirements (GitHub can sign squash merges)
163+
2. Clean history for single-commit dependency PRs
164+
3. Most universally compatible
165+
166+
### Enabling Squash Merge on Repos
167+
168+
If a repo only allows rebase merges and requires signed commits, enable squash:
169+
170+
```bash
171+
gh api repos/OWNER/REPO -X PATCH -f allow_squash_merge=true
172+
```
173+
141174
## Recommended Renovate Config for Auto-merge
142175

143176
```json

0 commit comments

Comments
 (0)