Skip to content

Commit 085979c

Browse files
committed
ci: Add action to creatae issue on gitflow merge conflicts
1 parent 850d4cc commit 085979c

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: 'Gitflow: Merge Conflict Issue'
2+
3+
on:
4+
pull_request:
5+
types: [opened]
6+
branches:
7+
- develop
8+
9+
jobs:
10+
check-merge-conflicts:
11+
name: Detect merge conflicts in gitflow PRs
12+
runs-on: ubuntu-24.04
13+
if: |
14+
${{ contains(github.event.pull_request.labels.*.name, 'Dev: Gitflow') }}
15+
permissions:
16+
issues: write
17+
steps:
18+
- name: Check for merge conflicts with retry
19+
uses: actions/github-script@v8
20+
with:
21+
script: |
22+
const retryInterval = 30_000;
23+
const maxRetries = 10; // (30 seconds * 10 retries) = 5 minutes
24+
25+
async function isMergeable() {
26+
const { data: pr } = await github.rest.pulls.get({
27+
owner: context.repo.owner,
28+
repo: context.repo.repo,
29+
pull_number: context.payload.pull_request.number
30+
});
31+
32+
return pr.mergeable;
33+
}
34+
35+
async function sleep(ms) {
36+
return new Promise(resolve => setTimeout(resolve, ms));
37+
}
38+
39+
let attempt = 0;
40+
let mergeable = null;
41+
42+
while (attempt < maxRetries) {
43+
attempt++;
44+
console.log(`Attempt ${attempt}/${maxRetries}: Checking if PR is mergeable...`);
45+
46+
mergeable = await isMergeable();
47+
console.log(`Mergeable: ${mergeable}`);
48+
49+
// If mergeable is not null, GitHub has finished computing merge state
50+
if (mergeable !== null) {
51+
break;
52+
}
53+
54+
if (attempt < maxRetries) {
55+
console.log(`Waiting ${retryInterval/1000} seconds before retry...`);
56+
await sleep(retryInterval);
57+
}
58+
}
59+
60+
// Check if we have merge conflicts
61+
if (mergeable === false) {
62+
const issueTitle = '[Gitflow] Merge Conflict';
63+
64+
// Check for existing open issues with the same title
65+
const { data: existingIssues } = await github.rest.issues.listForRepo({
66+
owner: context.repo.owner,
67+
repo: context.repo.repo,
68+
state: 'open',
69+
labels: 'Dev: Gitflow'
70+
});
71+
72+
const existingOpenIssue = existingIssues.find(issue =>
73+
issue.title === issueTitle && !issue.pull_request
74+
);
75+
76+
if (!existingOpenIssue) {
77+
const issueBody = [
78+
'## Gitflow Merge Conflict Detected',
79+
'',
80+
`The automated gitflow PR #${context.payload.pull_request.number} has merge conflicts and cannot be merged automatically.`,
81+
'',
82+
'### How to resolve',
83+
'',
84+
`Follow the steps documented in [docs/gitflow.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/develop/docs/gitflow.md#what-to-do-if-there-is-a-merge-conflict):`,
85+
'',
86+
`1. Close the automated PR #${context.payload.pull_request.number}`,
87+
'2. Create a new branch on top of `master` (e.g., `manual-develop-sync`)',
88+
'3. Merge `develop` into this branch with a **merge commit** (fix any merge conflicts)',
89+
'4. Create a PR against `develop` from your branch',
90+
'5. Merge that PR with a **merge commit**'
91+
].join('\n');
92+
93+
await github.rest.issues.create({
94+
owner: context.repo.owner,
95+
repo: context.repo.repo,
96+
title: issueTitle,
97+
body: issueBody,
98+
labels: ['Dev: Gitflow']
99+
});
100+
101+
console.log('Created new issue for merge conflict');
102+
}
103+
} else if (mergeable === null) {
104+
console.log('Could not determine mergeable state after maximum retries');
105+
} else {
106+
console.log('No merge conflicts detected - PR can be merged');
107+
}

0 commit comments

Comments
 (0)