🔍 Duplicate Code Detected: expired cleanup handlers duplicate comment and close flow
Analysis of commit 2f44bfd
Assignee: @copilot
Summary
The expired-entity cleanup handlers all call the same shared driver, executeExpiredEntityCleanup, but still duplicate the per-entity comment helper, close helper, footer assembly, and processEntity orchestration. The issue and pull request variants are almost the same file with renamed nouns, and the discussion variant keeps the same closing pipeline with an extra dedupe pre-check.
Duplication Details
Pattern: expired cleanup handlers repeat the same close-and-comment pipeline
- Severity: Medium
- Occurrences: 3
- Locations:
actions/setup/js/close_expired_issues.cjs (lines 20-84)
actions/setup/js/close_expired_pull_requests.cjs (lines 20-83)
actions/setup/js/close_expired_discussions.cjs (lines 18-163)
- Code Sample:
await executeExpiredEntityCleanup(github, owner, repo, {
entityType: "...",
graphqlField: "...",
resultKey: "...",
entityLabel: "...",
summaryHeading: "...",
processEntity: async entity => {
const cautionAlert = getExpiredEntityCautionAlert(workflowName, runUrl);
const expirationText = `This ... was automatically closed because it expired on ${...}.`;
const closingMessage = (cautionAlert ? cautionAlert + "\n\n" : "") + expirationText + generateExpiredEntityFooter(workflowName, runUrl, workflowId);
await add...Comment(..., closingMessage);
await close...(...);
return { status: "closed", record: { number: entity.number, url: entity.url, title: entity.title } };
},
});
Impact Analysis
- Maintainability: Changes to the expiration footer, status reporting, or close sequencing must be replicated across three files.
- Bug Risk: The issue and pull-request scripts are already effectively copy-paste siblings; future fixes can easily land in one and miss the other.
- Code Bloat: The duplicated per-entity cleanup scaffolding is much larger than the true behavioral delta, especially between issue and pull-request cleanup.
Refactoring Recommendations
-
Add an expired-cleanup handler factory on top of executeExpiredEntityCleanup
- Extract common functionality to:
actions/setup/js/expired_entity_handler_factory.cjs
- Estimated effort: 3-5 hours
- Benefits: Makes entity differences declarative and keeps common footer/comment/close sequencing in one place.
-
Model discussion-specific dedupe as an optional pre-close hook
- Extract common functionality to:
actions/setup/js/expired_entity_handler_factory.cjs
- Estimated effort: 2-3 hours
- Benefits: Preserves the discussion-only guard while sharing the rest of the lifecycle with issues and pull requests.
Implementation Checklist
Analysis Metadata
- Analyzed Files: 1572 (
1186 non-test .go, 386 non-test .cjs in the current shallow snapshot)
- Detection Method: Serena semantic code analysis plus targeted structural diffing
- Commit:
2f44bfd83f0685ea8d534e0081234474f7ac5e1a
- Analysis Date: 2026-08-06 UTC
Generated by 🔍 Duplicate Code Detector · gpt54 · 89.9 AIC · ⊞ 12.8K · ◷
🔍 Duplicate Code Detected: expired cleanup handlers duplicate comment and close flow
Analysis of commit 2f44bfd
Assignee:
@copilotSummary
The expired-entity cleanup handlers all call the same shared driver,
executeExpiredEntityCleanup, but still duplicate the per-entity comment helper, close helper, footer assembly, andprocessEntityorchestration. The issue and pull request variants are almost the same file with renamed nouns, and the discussion variant keeps the same closing pipeline with an extra dedupe pre-check.Duplication Details
Pattern: expired cleanup handlers repeat the same close-and-comment pipeline
actions/setup/js/close_expired_issues.cjs(lines 20-84)actions/setup/js/close_expired_pull_requests.cjs(lines 20-83)actions/setup/js/close_expired_discussions.cjs(lines 18-163)Impact Analysis
Refactoring Recommendations
Add an expired-cleanup handler factory on top of
executeExpiredEntityCleanupactions/setup/js/expired_entity_handler_factory.cjsModel discussion-specific dedupe as an optional pre-close hook
actions/setup/js/expired_entity_handler_factory.cjsImplementation Checklist
Analysis Metadata
1186non-test.go,386non-test.cjsin the current shallow snapshot)2f44bfd83f0685ea8d534e0081234474f7ac5e1a