Skip to content

PR Conflict Check

PR Conflict Check #110

name: PR Conflict Check
on:
push:
branches: [main]
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
permissions:
pull-requests: read
statuses: write
jobs:
check-conflicts:
runs-on: ubuntu-latest
steps:
- name: Flag conflicting PRs
uses: actions/github-script@v7
with:
script: |
const { data: prList } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
});
for (const pr of prList) {
const { data: detail } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
});
// GitHub may need time to compute mergeability after a push
for (let attempt = 0; attempt < 5 && detail.mergeable === null; attempt++) {
await new Promise(r => setTimeout(r, 5000));
const { data: retry } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
});
detail.mergeable = retry.mergeable;
detail.mergeable_state = retry.mergeable_state;
}
if (detail.mergeable === null) {
core.info(`PR #${pr.number}: mergeability unknown, skipping`);
continue;
}
const state = detail.mergeable ? 'success' : 'failure';
const description = detail.mergeable
? 'No merge conflicts'
: 'Has merge conflicts — rebase on main';
core.info(`PR #${pr.number}: mergeable=${detail.mergeable} (${detail.mergeable_state}) → ${state}`);
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: pr.head.sha,
state,
description,
context: 'conflict-check',
});
}