Skip to content

Comments

Extract shared handler for expired entity cleanup to eliminate duplication#16521

Closed
Copilot wants to merge 2 commits intomainfrom
copilot/refactor-expired-entity-cleanup
Closed

Extract shared handler for expired entity cleanup to eliminate duplication#16521
Copilot wants to merge 2 commits intomainfrom
copilot/refactor-expired-entity-cleanup

Conversation

Copy link
Contributor

Copilot AI commented Feb 18, 2026

The expired entity cleanup logic (comment + close + return record) was duplicated across close_expired_issues.cjs, close_expired_pull_requests.cjs, and close_expired_discussions.cjs, differing only in entity-specific API calls.

Changes

New shared handler module (expired_entity_handlers.cjs)

  • createExpiredEntityProcessor() encapsulates common flow
  • Accepts entity-specific hooks via configuration:
    • addComment(entity, message) - Entity-specific comment function
    • closeEntity(entity) - Entity-specific close function
    • buildClosingMessage() - Custom message builder
    • preCheck(entity) - Optional pre-check (e.g., discussion duplicate detection)

Refactored entry points

  • Issues: -2 lines (15 lines of duplicate logic removed)
  • Pull Requests: -1 line (15 lines of duplicate logic removed)
  • Discussions: -31 lines (54 lines of duplicate logic removed)

Example

Before (duplicated in each file):

processEntity: async issue => {
  const closingMessage = `This issue was automatically closed because it expired on ${issue.expirationDate.toISOString()}.` + generateExpiredEntityFooter(workflowName, runUrl, workflowId);
  
  await addIssueComment(github, owner, repo, issue.number, closingMessage);
  core.info(`  ✓ Comment added successfully`);
  
  await closeIssue(github, owner, repo, issue.number);
  core.info(`  ✓ Issue closed successfully`);
  
  return { status: "closed", record: { number: issue.number, url: issue.url, title: issue.title } };
}

After (single source of truth):

const processEntity = createExpiredEntityProcessor(workflowName, runUrl, workflowId, {
  entityType: "issue",
  addComment: async (issue, message) => await addIssueComment(github, owner, repo, issue.number, message),
  closeEntity: async issue => await closeIssue(github, owner, repo, issue.number),
  buildClosingMessage: (issue, workflowName, runUrl, workflowId) => 
    `This issue was automatically closed because it expired on ${issue.expirationDate.toISOString()}.` + 
    generateExpiredEntityFooter(workflowName, runUrl, workflowId),
});

Impact

  • Single source of truth for cleanup flow
  • Entity types cannot diverge in behavior
  • Future changes require single location update
  • Net -34 lines of duplicate code
Original prompt

This section details on the original issue you should resolve

<issue_title>Duplicate Code: Expired Entity Cleanup Flows (Issues/PRs/Discussions)</issue_title>
<issue_description># 🔍 Duplicate Code Detected: Expired Entity Cleanup Flows

Analysis of commit 67fe116

Assignee: @copilot

Summary

The expired-entity cleanup logic is implemented separately for issues, pull requests, and discussions. The main flow (comment + close + return record) repeats across three entrypoints with only entity-specific REST/GraphQL calls and labels differing, creating a maintenance burden for future changes.

Duplication Details

Pattern: Repeated executeExpiredEntityCleanup setup + processEntity flow

  • Severity: Medium
  • Occurrences: 3
  • Locations:
    • actions/setup/js/close_expired_issues.cjs:9
    • actions/setup/js/close_expired_pull_requests.cjs:9
    • actions/setup/js/close_expired_discussions.cjs:9
  • Code Sample:
await executeExpiredEntityCleanup(github, owner, repo, {
  entityType: "issues",
  graphqlField: "issues",
  resultKey: "issues",
  entityLabel: "Issue",
  summaryHeading: "Expired Issues Cleanup",
  processEntity: async issue => {
    const closingMessage = `This issue was automatically closed because it expired on \$\{issue.expirationDate.toISOString()}.` + generateExpiredEntityFooter(workflowName, runUrl, workflowId);
    await addIssueComment(github, owner, repo, issue.number, closingMessage);
    await closeIssue(github, owner, repo, issue.number);
    return { status: "closed", record: { number: issue.number, url: issue.url, title: issue.title } };
  },
});

Impact Analysis

  • Maintainability: Any changes to expiration messaging, comment/close sequencing, or record formatting must be duplicated across three files.
  • Bug Risk: Inconsistent behavior can slip in if one workflow updates while others don’t.
  • Code Bloat: Repeated boilerplate across entrypoints increases surface area.

Refactoring Recommendations

  1. Extract a shared expired-entity handler

    • Extract common flow to actions/setup/js/expired_entity_handlers.cjs (or extend expired_entity_main_flow.cjs).
    • Pass entity-specific hooks: addComment, closeEntity, buildClosingMessage, and optional pre-checks (e.g., discussion dedupe).
    • Estimated effort: Medium (2-4 hours)
    • Benefits: Single source of truth for cleanup flow, simplified additions for new entity types.
  2. Standardize return record assembly

    • Provide a common record builder to keep output consistent across entity types.
    • Estimated effort: Low (1 hour)
    • Benefits: Prevents subtle differences in report formatting.

Implementation Checklist

  • Review duplication findings
  • Prioritize refactoring tasks
  • Create refactoring plan
  • Implement changes
  • Update tests
  • Verify no functionality broken

Analysis Metadata

  • Analyzed Files: 3
  • Detection Method: Serena semantic code analysis
  • Commit: 67fe116
  • Analysis Date: 2026-02-18

Generated by Duplicate Code Detector

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor expired entity cleanup flows to reduce duplication Extract shared handler for expired entity cleanup to eliminate duplication Feb 18, 2026
Copilot AI requested a review from pelikhan February 18, 2026 05:22
@pelikhan pelikhan closed this Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate Code: Expired Entity Cleanup Flows (Issues/PRs/Discussions)

2 participants