Skip to content

Extract duplicate resolve/format patterns from update handlers into factory functions#16748

Merged
pelikhan merged 2 commits intomainfrom
copilot/refactor-update-handler-pattern
Feb 19, 2026
Merged

Extract duplicate resolve/format patterns from update handlers into factory functions#16748
pelikhan merged 2 commits intomainfrom
copilot/refactor-update-handler-pattern

Conversation

Copy link
Contributor

Copilot AI commented Feb 19, 2026

Update handlers (update_issue, update_pull_request, update_discussion) duplicated ~56 lines of resolve/format logic across 3 files.

Changes

Added factory functions in update_handler_factory.cjs:

  • createStandardResolveNumber(config) - generates resolve functions for issue/PR handlers that use resolveTarget helper
  • createStandardFormatResult(fieldMapping) - generates format functions with configurable field names

Refactored handlers:

  • update_issue.cjs: uses both factories (-36 lines)
  • update_pull_request.cjs: uses both factories (-36 lines)
  • update_discussion.cjs: uses format factory only (-14 lines, preserves custom GraphQL resolution logic)

Example

Before:

function resolvePRNumber(item, updateTarget, context) {
  const targetResult = resolveTarget({
    targetConfig: updateTarget,
    item: { ...item, item_number: item.pull_request_number },
    context: context,
    itemType: "update_pull_request",
    supportsPR: false,
    supportsIssue: false,
  });
  if (!targetResult.success) {
    return { success: false, error: targetResult.error };
  }
  return { success: true, number: targetResult.number };
}

After:

const resolvePRNumber = createStandardResolveNumber({
  itemType: "update_pull_request",
  itemNumberField: "pull_request_number",
  supportsPR: false,
  supportsIssue: false,
});

Net: -77 lines, +6 test cases covering all factory variations.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/github/gh-aw/contents/.github%2Fworkflows%2Faudit-workflows.md
    • Triggering command: /opt/hostedtoolcache/node/24.13.0/x64/bin/node /opt/hostedtoolcache/node/24.13.0/x64/bin/node --conditions node --conditions development --experimental-import-meta-resolve --require /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vitest/suppress-warnings.cjs /home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/vitest/dist/workers/forks.js ota=5% yHigh=170M (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Duplicate Code: Update Handler Pattern Across update_issue/update_pull_request/update_discussion</issue_title>
<issue_description># 🔍 Duplicate Code Detected: Update Handler Pattern Across Safe Outputs

Analysis of commit 8859937

Assignee: @copilot

Summary

The update_* safe-output handlers share a repeated structure for resolving target numbers, building update payloads, formatting success results, and wiring the handler factory. The pattern appears in at least three files and spans >10 lines each, indicating a clear refactoring opportunity into a shared helper/factory layer.

Duplication Details

Pattern: Update handler skeleton (resolve/build/format + factory wiring)

  • Severity: Medium

  • Occurrences: 3

  • Locations:

  • actions/setup/js/update_issue.cjs:93

  • actions/setup/js/update_pull_request.cjs:70

  • actions/setup/js/update_discussion.cjs:70

  • Code Sample:

function resolveXNumber(item, updateTarget, context) {
  const targetResult = resolveTarget({
    targetConfig: updateTarget,
    item: { ...item, item_number: item.issue_number },
    context: context,
    itemType: "update_issue",
    supportsPR: false,
    supportsIssue: true,
  });
  if (!targetResult.success) {
    return { success: false, error: targetResult.error };
  }
  return { success: true, number: targetResult.number };
}

Impact Analysis

  • Maintainability: Changes to update handler behavior (validation, result formatting, or configuration defaults) must be applied manually across multiple files.
  • Bug Risk: Inconsistent updates can introduce subtle behavior drift between issue/PR/discussion updates.
  • Code Bloat: Repeated scaffolding adds noise and makes future modifications harder to review.

Refactoring Recommendations

  1. Extract a shared update-handler scaffold
  • Extract common resolve/build/format/factory wiring into a createStandardUpdateHandler helper in actions/setup/js/update_handler_factory.cjs.
  • Estimated effort: Medium (2-4 hours)
  • Benefits: One place to evolve defaults, validation, and structured responses.
  1. Introduce per-type configuration hooks
  • Use a per-type config object for item-specific differences (issue vs PR vs discussion), while the shared scaffold handles wiring and defaults.
  • Estimated effort: Low to Medium (1-3 hours)
  • Benefits: Removes repeated setup while preserving the custom per-type logic.

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: 8859937
  • Analysis Date: 2026-02-19

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.

Extract common patterns from update_issue, update_pull_request, and update_discussion handlers:

1. Added createStandardResolveNumber() factory for issue/PR handlers
   - Eliminates 16 lines of duplicate code (2 occurrences)
   - Centralizes resolveTarget helper usage

2. Added createStandardFormatResult() factory for all handlers
   - Eliminates 24 lines of duplicate code (3 occurrences)
   - Provides consistent success result formatting

3. Updated all three handlers to use new helpers
   - update_issue: Uses both helpers (-19 lines)
   - update_pull_request: Uses both helpers (-19 lines)
   - update_discussion: Uses format helper only (-8 lines)
   - Discussion keeps custom resolve logic (too different to share)

4. Added comprehensive tests for new factory functions
   - 6 new test cases covering all helper variations
   - Validates issue, PR, and discussion patterns

Results:
- Net reduction: 77 lines of code
- Improved maintainability: Changes to resolve/format logic now in one place
- No functional changes: All existing tests pass
- Better consistency: Uniform behavior across handlers

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate code in update handlers Extract duplicate resolve/format patterns from update handlers into factory functions Feb 19, 2026
@pelikhan pelikhan marked this pull request as ready for review February 19, 2026 05:07
Copilot AI review requested due to automatic review settings February 19, 2026 05:07
@pelikhan pelikhan merged commit ad74dd3 into main Feb 19, 2026
160 checks passed
@pelikhan pelikhan deleted the copilot/refactor-update-handler-pattern branch February 19, 2026 05:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR successfully refactors duplicate resolve/format patterns from three update handler files (update_issue, update_pull_request, update_discussion) into reusable factory functions, eliminating approximately 77 lines of duplicate code while adding comprehensive test coverage.

Changes:

  • Added two factory functions (createStandardResolveNumber and createStandardFormatResult) to eliminate duplicate patterns across update handlers
  • Refactored update_issue.cjs and update_pull_request.cjs to use both factory functions
  • Refactored update_discussion.cjs to use the format factory (preserving custom GraphQL resolution logic)

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
actions/setup/js/update_handler_factory.cjs Added createStandardResolveNumber and createStandardFormatResult factory functions with comprehensive JSDoc documentation
actions/setup/js/update_pull_request.cjs Replaced ~20 lines of resolve/format code with factory-generated functions
actions/setup/js/update_issue.cjs Replaced ~20 lines of resolve/format code with factory-generated functions
actions/setup/js/update_discussion.cjs Replaced ~10 lines of format code with factory-generated function (kept custom resolve logic)
actions/setup/js/update_handler_factory.test.cjs Added 6 comprehensive test cases covering all factory variations and edge cases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -10,7 +10,7 @@ const HANDLER_TYPE = "update_pull_request";

const { updateBody } = require("./update_pr_description_helpers.cjs");
const { resolveTarget } = require("./safe_output_helpers.cjs");
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resolveTarget import is no longer used in this file since the createStandardResolveNumber factory now handles the target resolution internally. This unused import should be removed.

Suggested change
const { resolveTarget } = require("./safe_output_helpers.cjs");

Copilot uses AI. Check for mistakes.
@@ -9,7 +9,7 @@
const HANDLER_TYPE = "update_issue";

const { resolveTarget } = require("./safe_output_helpers.cjs");
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resolveTarget import is no longer used in this file since the createStandardResolveNumber factory now handles the target resolution internally. This unused import should be removed.

Suggested change
const { resolveTarget } = require("./safe_output_helpers.cjs");

Copilot uses AI. Check for mistakes.
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: Update Handler Pattern Across update_issue/update_pull_request/update_discussion

3 participants