Fix duplicate issue bot to respect 👎 reactions and not re-close reopened issues (#24203)

## Summary

Fixed two bugs in the auto-close-duplicates bot:

- **Respect 👎 reactions from ANY user**: Previously only the issue
author's thumbs down would prevent auto-closing. Now any user can
indicate disagreement with the duplicate detection.
- **Don't re-close reopened issues**: The bot now checks if an issue was
previously reopened and skips auto-closing to respect user intent.

## Changes

1. Modified `fetchAllReactions` call to check all reactions, not just
the author's
2. Changed `authorThumbsDown` logic to `hasThumbsDown` (checks any
user's reaction)
3. Added `wasIssueReopened()` function to query issue events timeline
4. Added check to skip issues with "reopened" events in their history

## Test plan

- [ ] Manually test the script doesn't close issues with 👎 reactions
from non-authors
- [ ] Verify reopened issues are not auto-closed again
- [ ] Check that legitimate duplicates without objections still get
closed properly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
robobun
2025-10-29 15:41:44 -07:00
committed by GitHub
parent 9d4a04cff9
commit 1de4448425

View File

@@ -26,6 +26,11 @@ interface GitHubReaction {
content: string;
}
interface GitHubEvent {
event: string;
created_at: string;
}
async function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
@@ -153,6 +158,13 @@ async function fetchAllReactions(
return allReactions;
}
async function wasIssueReopened(owner: string, repo: string, issueNumber: number, token: string): Promise<boolean> {
const events: GitHubEvent[] = await githubRequest(`/repos/${owner}/${repo}/issues/${issueNumber}/events`, token);
// Check if there's a "reopened" event in the issue's timeline
return events.some(event => event.event === "reopened");
}
function escapeRegExp(str: string): string {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
@@ -299,16 +311,23 @@ async function autoCloseDuplicates(): Promise<void> {
}
console.log(`[DEBUG] Issue #${issue.number} - checking reactions on duplicate comment...`);
const reactions = await fetchAllReactions(owner, repo, lastDupeComment.id, token, issue.user.id);
const reactions = await fetchAllReactions(owner, repo, lastDupeComment.id, token);
console.log(`[DEBUG] Issue #${issue.number} - duplicate comment has ${reactions.length} reactions`);
const authorThumbsDown = reactions.some(
reaction => reaction.user.id === issue.user.id && reaction.content === "-1",
);
console.log(`[DEBUG] Issue #${issue.number} - author thumbs down reaction: ${authorThumbsDown}`);
const hasThumbsDown = reactions.some(reaction => reaction.content === "-1");
console.log(`[DEBUG] Issue #${issue.number} - has thumbs down reaction: ${hasThumbsDown}`);
if (authorThumbsDown) {
console.log(`[DEBUG] Issue #${issue.number} - author disagreed with duplicate detection, skipping`);
if (hasThumbsDown) {
console.log(`[DEBUG] Issue #${issue.number} - someone disagreed with duplicate detection, skipping`);
continue;
}
console.log(`[DEBUG] Issue #${issue.number} - checking if issue was reopened...`);
const wasReopened = await wasIssueReopened(owner, repo, issue.number, token);
console.log(`[DEBUG] Issue #${issue.number} - was reopened: ${wasReopened}`);
if (wasReopened) {
console.log(`[DEBUG] Issue #${issue.number} - issue was previously reopened, skipping auto-close`);
continue;
}