Skip to content

Instantly share code, notes, and snippets.

@xHeaven
Created December 15, 2025 14:39
Show Gist options
  • Select an option

  • Save xHeaven/a7563255be823a29f1b72a72ccdf864d to your computer and use it in GitHub Desktop.

Select an option

Save xHeaven/a7563255be823a29f1b72a72ccdf864d to your computer and use it in GitHub Desktop.
name: Duplicate PR Detection
on:
pull_request:
types: [opened]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
detect-duplicates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Ensure labels exist
run: |
gh label create "duplicate" --color "cfd3d7" --description "This PR duplicates another" 2>/dev/null || true
gh label create "potential-duplicate" --color "FBCA04" --description "PR may duplicate another open PR" 2>/dev/null || true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: anthropics/claude-code-action@v1
with:
track_progress: true
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
You are a duplicate PR detector. Analyze if PR #${{ github.event.pull_request.number }} duplicates any existing open PRs.
**CRITICAL RULE:** Always flag/close the PR that was opened LATER. Never flag or close the PR that came in earlier. Use the `createdAt` timestamp to determine which PR is older.
## Step 1: Get the current PR's details including creation time
```bash
gh pr view ${{ github.event.pull_request.number }} --json number,files,createdAt --jq '{number: .number, createdAt: .createdAt, files: [.files[].path]}'
```
## Step 2: Get all other open PRs with creation times
```bash
gh pr list --state open --json number,title,author,files,createdAt --jq '.[] | select(.number != ${{ github.event.pull_request.number }})'
```
## Step 3: Filter to PRs with overlapping files
From the list above, identify PRs that modify ANY of the same files as the current PR.
If no PRs touch overlapping files, skip to Step 6 (no duplicates).
## Step 4: Deep comparison
For each PR with overlapping files, get its diff:
```bash
gh pr diff <PR_NUMBER>
```
Compare against the current PR's diff:
```bash
gh pr diff ${{ github.event.pull_request.number }}
```
## Step 5: Evaluate similarity
**BE STRICT:** If a later PR solves the same problem as an earlier PR, it is a copycat regardless of implementation differences. The first PR has priority.
**DUPLICATE (auto-close)** - ANY of these:
- Changes are logically equivalent (same fix/feature)
- Same problem being solved, even if implementation differs
- The newer PR is clearly a copycat (solves what the older PR already solves)
- No meaningful NEW functionality beyond what the older PR provides
**POTENTIAL DUPLICATE (label + comment)** - If unsure, DEFAULT TO THIS:
- Similar changes but uncertain if truly equivalent
- Same problem, different approach (flag it - let maintainers decide)
- One PR is a subset of the other
- Any doubt about whether this is a copycat
- Overlapping intent even if code looks different
**NOT DUPLICATE (requires high confidence):**
- Genuinely different features that happen to touch same files
- The newer PR adds substantial NEW functionality not in the older PR
- Completely unrelated logical changes despite file overlap
## Step 6: Take action
**IMPORTANT:** Compare `createdAt` timestamps to determine which PR is newer. Always act on the NEWER PR (the one created later).
**If DUPLICATE (high confidence):**
If current PR #${{ github.event.pull_request.number }} is NEWER (created after the other PR):
```bash
gh pr close ${{ github.event.pull_request.number }} --comment "Closing as duplicate of #<OTHER_PR>.
**Reason:** <brief explanation of why this is a duplicate>
The existing PR #<OTHER_PR> was opened earlier and addresses the same issue. Please review that PR instead, or reopen this one if you believe it offers a meaningfully different approach."
gh pr edit ${{ github.event.pull_request.number }} --add-label "duplicate"
```
If current PR #${{ github.event.pull_request.number }} is OLDER (created before the other PR):
```bash
gh pr close <OTHER_PR_NUMBER> --comment "Closing as duplicate of #${{ github.event.pull_request.number }}.
**Reason:** <brief explanation of why this is a duplicate>
PR #${{ github.event.pull_request.number }} was opened earlier and addresses the same issue. Please review that PR instead, or reopen this one if you believe it offers a meaningfully different approach."
gh pr edit <OTHER_PR_NUMBER> --add-label "duplicate"
```
**If POTENTIAL DUPLICATE (medium/low confidence):**
If current PR #${{ github.event.pull_request.number }} is NEWER:
```bash
gh pr edit ${{ github.event.pull_request.number }} --add-label "potential-duplicate"
gh pr comment ${{ github.event.pull_request.number }} --body "**Potential Duplicate Detected**
This PR may duplicate #<OTHER_PR> (opened earlier).
**Similarity:** <percentage>%
**Reason:** <brief explanation>
Please review the existing PR and clarify if this PR offers a different approach or additional changes."
```
If current PR #${{ github.event.pull_request.number }} is OLDER:
```bash
gh pr edit <OTHER_PR_NUMBER> --add-label "potential-duplicate"
gh pr comment <OTHER_PR_NUMBER> --body "**Potential Duplicate Detected**
This PR may duplicate #${{ github.event.pull_request.number }} (opened earlier).
**Similarity:** <percentage>%
**Reason:** <brief explanation>
Please review the existing PR and clarify if this PR offers a different approach or additional changes."
```
**If NO DUPLICATES:**
No action needed. Do not comment.
claude_args: |
--allowedTools "Bash(gh pr diff:*),Bash(gh pr list:*),Bash(gh pr edit:*),Bash(gh pr comment:*),Bash(gh pr view:*),Bash(gh pr close:*)"
--model opus
github_token: ${{ secrets.GITHUB_TOKEN }}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment