Overview
A large number of actions/setup/js/*.cjs handlers duplicate the same control-flow scaffold (max-limit gate, processedCount state, repeated skip/error response shape, and per-item wrapper structure) instead of sharing one composable factory. This is significant duplication and increases maintenance cost when behavior changes are needed.
Critical Information
- Severity: Medium
- Duplication type: Structural duplication (copy-paste with small variations)
- Scope: 25+ handler modules with near-identical scaffolding
- Commit analyzed:
0ce475302c05891ae61787204d3d755470a5551b
Examples of repeated pattern
Common repeated block (or near-equivalent) appears in many files:
let processedCount = 0;
if (processedCount >= maxCount) { ... error: \Max count of ${maxCount} reached` }`
processedCount++;
- handler-specific logic thereafter
Concrete examples:
actions/setup/js/add_labels.cjs lines 39-57
actions/setup/js/remove_labels.cjs lines 48-67
actions/setup/js/assign_to_user.cjs lines 49-68
actions/setup/js/unassign_from_user.cjs lines 49-68
actions/setup/js/close_issue.cjs lines 110-124
actions/setup/js/create_issue.cjs lines 295-324
actions/setup/js/create_pull_request.cjs lines 377-403
actions/setup/js/dispatch_workflow.cjs lines 78 and 134-138
actions/setup/js/report_incomplete_handler.cjs lines 29 and 39-44
Repository-wide pattern search also found the same structure in many additional handlers (add_comment, add_reviewer, assign_milestone, create_discussion, create_project, hide_comment, link_sub_issue, resolve_pr_review_thread, set_issue_type, submit_pr_review, etc.).
Impact Analysis
- Maintainability: Any change to limit behavior or skip-result schema requires N-file edits.
- Bug risk: Inconsistent behavior is likely as some handlers evolve and others lag.
- Code bloat: Repeated boilerplate obscures handler-specific logic.
Refactoring Recommendations
- Introduce a shared higher-order handler wrapper for count gating
- Candidate location:
actions/setup/js/handler_factory.cjs (or extend existing factories)
- Inputs:
handlerType, maxCount, handleItem callback, optional onSkip override
- Output: standardized
success/error/skipped/deferred result envelope
- Migrate handlers incrementally in cohorts
- Start with low-risk pair(s):
add_labels + remove_labels, assign_to_user + unassign_from_user
- Then migrate remaining CRUD-like handlers
- Keep behavior snapshots via current tests before each cohort migration
- Reuse existing abstraction points
actions/setup/js/update_handler_factory.cjs already centralizes similar concerns for update handlers
actions/setup/js/missing_issue_helpers.cjs already uses shared flow; align remaining handlers to similar pattern
Implementation Checklist
Analysis Metadata
- Analyzed files: non-test
.go and .cjs files in current commit scope (snapshot-style commit)
- Detection method: Serena semantic/pattern analysis + targeted code inspection
- Trigger:
@pelikhan
- Workflow run: §24188961842
Generated by Duplicate Code Detector · ◷
Overview
A large number of
actions/setup/js/*.cjshandlers duplicate the same control-flow scaffold (max-limit gate,processedCountstate, repeated skip/error response shape, and per-item wrapper structure) instead of sharing one composable factory. This is significant duplication and increases maintenance cost when behavior changes are needed.Critical Information
0ce475302c05891ae61787204d3d755470a5551bExamples of repeated pattern
Common repeated block (or near-equivalent) appears in many files:
let processedCount = 0;if (processedCount >= maxCount) { ... error: \Max count of ${maxCount} reached` }`processedCount++;Concrete examples:
actions/setup/js/add_labels.cjslines 39-57actions/setup/js/remove_labels.cjslines 48-67actions/setup/js/assign_to_user.cjslines 49-68actions/setup/js/unassign_from_user.cjslines 49-68actions/setup/js/close_issue.cjslines 110-124actions/setup/js/create_issue.cjslines 295-324actions/setup/js/create_pull_request.cjslines 377-403actions/setup/js/dispatch_workflow.cjslines 78 and 134-138actions/setup/js/report_incomplete_handler.cjslines 29 and 39-44Repository-wide pattern search also found the same structure in many additional handlers (
add_comment,add_reviewer,assign_milestone,create_discussion,create_project,hide_comment,link_sub_issue,resolve_pr_review_thread,set_issue_type,submit_pr_review, etc.).Impact Analysis
Refactoring Recommendations
actions/setup/js/handler_factory.cjs(or extend existing factories)handlerType,maxCount,handleItemcallback, optionalonSkipoverridesuccess/error/skipped/deferredresult envelopeadd_labels+remove_labels,assign_to_user+unassign_from_useractions/setup/js/update_handler_factory.cjsalready centralizes similar concerns for update handlersactions/setup/js/missing_issue_helpers.cjsalready uses shared flow; align remaining handlers to similar patternImplementation Checklist
add_labels,remove_labels)assign_to_user,unassign_from_user)Analysis Metadata
.goand.cjsfiles in current commit scope (snapshot-style commit)@pelikhan