Add GitHub Action to detect overlapping PRs#76820
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Note: This PR currently uses Once we've verified it works, we need to:
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ap detection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Size Change: 0 B Total Size: 7.73 MB ℹ️ View Unchanged
|
| // Get files changed in this PR with their patches. | ||
| const changedFiles = new Map(); | ||
| for await ( const response of github.paginate.iterator( | ||
| github.rest.pulls.listFiles, |
There was a problem hiding this comment.
This workflow runs on every change to every PR, causing 2000+ API requests per workflow run (there are currently 2k open PRs), meaning that it can singlehandedly exceed the rate limit of 15k/hour that is shared across the repo.
Claude suggests a few ideas to improve the situation:
- Pre-filter with file names first before fetching full patches — skip PRs that don't share any file names entirely (you could use the Search API or a lighter endpoint).
- Cache results — most open PRs don't change between runs; consider storing/reusing prior results.
- Limit scope — only check PRs updated within the last N days, or limit to non-draft PRs for the expensive line-range analysis.
- Add a rate-limit guard — check x-ratelimit-remaining and bail early if running low.
| per_page: 100, | ||
| } | ||
| ); | ||
| const existing = comments.find( ( c ) => c.body.includes( marker ) ); |
There was a problem hiding this comment.
If the PR body is empty, this could throw. We should add a guard, something like
| const existing = comments.find( ( c ) => c.body.includes( marker ) ); | |
| const existing = comments.find( ( c ) => c.body && c.body.includes( marker ) ); |
| per_page: 100, | ||
| } | ||
| ); | ||
| const existing = comments.find( ( c ) => c.body.includes( marker ) ); |
| // Parse hunk headers from a patch string. | ||
| // Returns an array of { start, end } line ranges (base side). | ||
| function parseHunks( patch ) { | ||
| if ( ! patch ) { | ||
| return []; | ||
| } | ||
| const hunks = []; | ||
| const regex = /^@@ -(\d+)(?:,(\d+))? /gm; | ||
| let match; | ||
| while ( ( match = regex.exec( patch ) ) !== null ) { | ||
| const start = parseInt( match[ 1 ], 10 ); | ||
| const count = match[ 2 ] !== undefined ? parseInt( match[ 2 ], 10 ) : 1; | ||
| if ( count > 0 ) { | ||
| hunks.push( { start, end: start + count - 1 } ); | ||
| } | ||
| } | ||
| return hunks; | ||
| } |
There was a problem hiding this comment.
If I understand correctly, this function can highlight is two PRs touch the same region of the original file, but it may miss instances in which two or more PRs add code at the same insertion point but at different new-side offsets.
Probably fine since this is mostly a "heads-up" tool, but we should at least acknowledge the limitation
| // Files to ignore — these always overlap and conflicts are trivial. | ||
| const IGNORED_PATTERNS = [ | ||
| 'package-lock.json', | ||
| 'composer.lock', | ||
| '**/CHANGELOG.md', | ||
| ]; | ||
|
|
||
| function isIgnored( filename ) { | ||
| return IGNORED_PATTERNS.some( ( pattern ) => { | ||
| if ( pattern.startsWith( '**/' ) ) { | ||
| return filename.endsWith( pattern.slice( 2 ) ); | ||
| } | ||
| return filename === pattern; | ||
| } ); | ||
| } |
There was a problem hiding this comment.
This works well for the initial implementation, but it may not be sufficient to handle more complex patterns if/when the list grows. We should consider using a more complete tool (maybe the minimatch package or something equilvalent), or at least document the limitation with this initial implementation
There was a problem hiding this comment.
Good point. I've added a comment documenting exactly what the pattern matcher supports (exact match and **/suffix only) and noting that a glob library like minimatch should be considered if richer patterns are needed.
| name: Overlapping PRs | ||
|
|
||
| on: | ||
| pull_request: |
There was a problem hiding this comment.
Just confirming that pull_request_target should be the right trigger here (acknowledging that @scruffian already mentinoed it, too)
There was a problem hiding this comment.
Reminder to remove these test changes before merging 🧹
Thanks for this one @scruffian! Could you share a few examples where this would have helped prevent headaches? We have a lot of bot comments that can be left on PRs these days, and it causes a good amount of noise. I'm trying to understand how this helps beyond the standard conflict resolution tools and workflows that are native to Git. |
|
I'm also unsure about the usefulness of this info.
This is unavoidable on large and active projects like WP. Contributors need to know how to handle merge conflicts or let the AI resolve them for you. Duplicate work is harder to resolve, and working on the same files does not always = working on the same thing. This can lead to many false positives. I think we should try to improve this at the project management level. P.S. In the past, we blocked a couple of new bot suggestions due to increased noise in the PRs. |
…itation docs - Use GitHub Search API to find candidate PRs by filename before fetching patches, reducing API calls from 2000+ to only the relevant few - Add rate-limit guard that bails if remaining requests < 500 - Guard against null comment body in all .find() calls - Document the base-side line range limitation on parseHunks - Extract deleteStaleComment() helper to reduce duplication Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The intention for this PR isn't to avoid conflicts, as you say it's somewhat inevitable, and we have tools to resolve that for us. Our experience is that it can be really hard to know when other people are working in the same area as you. The aim of this PR is to raise flag as early as possible that others are working in the same area as you.
I agree that this is somewhat of a blunt tool to solve a product management tool. However having a robust process to solve this problem in an open source project of this size seems very difficult. Did you have any ideas in mind? |
I had a recent PR that went on for a few weeks, touching files that are being worked on very actively, and although I do know how to handle merge conflicts 😅 there were some very thorny ones that took a while to solve. AI helps somewhat, but I still have to manually verify that the resulting code is correct. While this action wouldn't have done anything to avoid the conflicts happening, it would have given me a heads up regarding incoming changes, and I might have e.g. delayed some changes until after another PR was merged to minimise conflicting files. Given my PR was open for a very long time though, it would have been useful to get comments after it was open regarding PRs that were subsequently opened. This was a bit of an outlier though and for PRs that aren't open for that long it might not be as useful 🤷 I don't have too strong an opinion on this tbh. |
|
Flaky tests detected in eb58731. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23674919588
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
What?
Adds a new GitHub Action workflow that automatically detects other open PRs touching the same files as the current PR.
Why?
When multiple contributors are working on the same files, merge conflicts and duplicated work are common. This bot surfaces overlapping PRs early so authors can coordinate.
How?
A new workflow (
.github/workflows/overlapping-prs.yml) triggers onpull_request_target(opened/synchronize). It:Testing Instructions
Use of AI Tools
This PR was authored with assistance from Claude (Anthropic AI).