Auto Comment on Merge Conflict #485
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto Comment on Merge Conflict | |
| on: | |
| # Event-based triggers | |
| pull_request: | |
| types: [opened, reopened, synchronize] | |
| # Time-based trigger (every 6 hours) | |
| schedule: | |
| - cron: '0 */6 * * *' | |
| permissions: | |
| pull-requests: write | |
| jobs: | |
| comment-on-merge-conflict: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check for merge conflict on event and schedule, auto-comment | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| // Helper: Get all open PRs (for schedule), or just the triggered one (for PR event) | |
| let prs = []; | |
| if (context.eventName === "schedule") { | |
| prs = await github.paginate(github.rest.pulls.list, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open' | |
| }); | |
| } else if (context.payload.pull_request) { | |
| prs = [context.payload.pull_request]; | |
| } | |
| for (const pr of prs) { | |
| // Get latest PR details (for mergeable state, labels, etc) | |
| let tries = 0; | |
| let prDetails = null; | |
| while (tries < 3) { | |
| const resp = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr.number | |
| }); | |
| prDetails = resp.data; | |
| if (prDetails.mergeable !== null) break; | |
| await new Promise(r => setTimeout(r, 3000)); | |
| tries++; | |
| } | |
| // If merge conflict | |
| if (prDetails.mergeable === false) { | |
| // To avoid duplicate comments, check if already commented | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number | |
| }); | |
| const alreadyCommented = comments.data.some(c => | |
| c.body && c.body.includes("**Merge Conflict Detected!**") | |
| ); | |
| if (alreadyCommented) continue; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: pr.number, | |
| body: `⚠️ **Merge Conflict Detected!** | |
| Hi @${pr.user.login}, your pull request currently has a merge conflict with the base branch. Please resolve the conflict so your PR can be merged. | |
| --- | |
| ## **How to Resolve a Merge Conflict (Step-by-Step)** | |
| 1. **Checkout your PR branch:** | |
| \`\`\`bash | |
| git checkout ${pr.head.ref} | |
| \`\`\` | |
| 2. **Fetch the latest changes from the main branch:** | |
| \`\`\`bash | |
| git fetch origin | |
| git pull origin ${pr.base.ref} | |
| \`\`\` | |
| 3. **Git will show conflict markers in files with conflicts. Open those files, and manually edit them to resolve the differences. Conflict sections look like:** | |
| \`\`\` | |
| <<<<<<< HEAD | |
| Your changes | |
| ======= | |
| Changes from base branch | |
| >>>>>>> ${pr.base.ref} | |
| \`\`\` | |
| 4. **After resolving the conflicts, mark them as resolved:** | |
| \`\`\`bash | |
| git add <file(s)-you-resolved> | |
| \`\`\` | |
| 5. **Commit the resolution:** | |
| \`\`\`bash | |
| git commit -m "Resolve merge conflict" | |
| \`\`\` | |
| 6. **Push your updated branch:** | |
| \`\`\`bash | |
| git push origin ${pr.head.ref} | |
| \`\`\` | |
| --- | |
| 🔗 [GitHub Docs: Resolving merge conflicts](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/about-merge-conflicts) | |
| If you need any help, please ask your mentors by replying here! | |
| --- | |
| *This is an automated message to help you resolve merge conflicts and get your PR ready for review. Thank you!* | |
| ` | |
| }); | |
| } | |
| } |