From 4b4528d3fc460dcd80e6758236787783aa9096e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 21:16:53 +0000 Subject: [PATCH 1/2] Initial plan From 8d45a51f9f095e0c73e9fffde0b96bd7ecb612d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 21:23:02 +0000 Subject: [PATCH 2/2] Extract duplicate logic to safe output helper functions - Add resolveIssueNumber() helper in safe_output_helpers.cjs - Add extractAssignees() helper in safe_output_helpers.cjs - Update assign_to_user.cjs to use new helper functions - Update unassign_from_user.cjs to use new helper functions - Reduces 108 lines of duplicate code to 52 lines of reusable helpers - Net reduction: 56 lines (58 lines removed, 2 lines added for imports) - All tests passing Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/assign_to_user.cjs | 41 ++++++------------- actions/setup/js/safe_output_helpers.cjs | 52 ++++++++++++++++++++++++ actions/setup/js/unassign_from_user.cjs | 41 ++++++------------- 3 files changed, 76 insertions(+), 58 deletions(-) diff --git a/actions/setup/js/assign_to_user.cjs b/actions/setup/js/assign_to_user.cjs index 0a7226137e..28bc6c8a3b 100644 --- a/actions/setup/js/assign_to_user.cjs +++ b/actions/setup/js/assign_to_user.cjs @@ -8,6 +8,7 @@ const { processItems } = require("./safe_output_processor.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs"); +const { resolveIssueNumber, extractAssignees } = require("./safe_output_helpers.cjs"); /** @type {string} Safe output type handled by this module */ const HANDLER_TYPE = "assign_to_user"; @@ -67,37 +68,19 @@ async function main(config = {}) { const assignItem = message; - // Determine issue number - let issueNumber; - if (assignItem.issue_number !== undefined) { - issueNumber = parseInt(String(assignItem.issue_number), 10); - if (isNaN(issueNumber)) { - core.warning(`Invalid issue_number: ${assignItem.issue_number}`); - return { - success: false, - error: `Invalid issue_number: ${assignItem.issue_number}`, - }; - } - } else { - // Use context issue if available - const contextIssue = context.payload?.issue?.number; - if (!contextIssue) { - core.warning("No issue_number provided and not in issue context"); - return { - success: false, - error: "No issue number available", - }; - } - issueNumber = contextIssue; + // Determine issue number using shared helper + const issueResult = resolveIssueNumber(assignItem); + if (!issueResult.success) { + core.warning(`Skipping assign_to_user: ${issueResult.error}`); + return { + success: false, + error: issueResult.error, + }; } + const issueNumber = issueResult.issueNumber; - // Support both singular "assignee" and plural "assignees" for flexibility - let requestedAssignees = []; - if (assignItem.assignees && Array.isArray(assignItem.assignees)) { - requestedAssignees = assignItem.assignees; - } else if (assignItem.assignee) { - requestedAssignees = [assignItem.assignee]; - } + // Extract assignees using shared helper + const requestedAssignees = extractAssignees(assignItem); core.info(`Requested assignees: ${JSON.stringify(requestedAssignees)}`); diff --git a/actions/setup/js/safe_output_helpers.cjs b/actions/setup/js/safe_output_helpers.cjs index 2a925df020..a2d865d2d4 100644 --- a/actions/setup/js/safe_output_helpers.cjs +++ b/actions/setup/js/safe_output_helpers.cjs @@ -257,9 +257,61 @@ function loadCustomSafeOutputJobTypes() { } } +/** + * Determine issue number from message or context + * @param {Object} message - Message object that may contain issue_number + * @returns {{success: true, issueNumber: number} | {success: false, error: string}} + */ +function resolveIssueNumber(message) { + // Determine issue number + let issueNumber; + if (message.issue_number !== undefined) { + issueNumber = parseInt(String(message.issue_number), 10); + if (isNaN(issueNumber)) { + return { + success: false, + error: `Invalid issue_number: ${message.issue_number}`, + }; + } + } else { + // Use context issue if available + const contextIssue = context.payload?.issue?.number; + if (!contextIssue) { + return { + success: false, + error: "No issue number available", + }; + } + issueNumber = contextIssue; + } + + return { + success: true, + issueNumber: issueNumber, + }; +} + +/** + * Extract assignees from message supporting both singular and plural forms + * @param {Object} message - Message object that may contain assignee or assignees + * @returns {string[]} Array of assignee usernames + */ +function extractAssignees(message) { + // Support both singular "assignee" and plural "assignees" for flexibility + let requestedAssignees = []; + if (message.assignees && Array.isArray(message.assignees)) { + requestedAssignees = message.assignees; + } else if (message.assignee) { + requestedAssignees = [message.assignee]; + } + return requestedAssignees; +} + module.exports = { parseAllowedItems, parseMaxCount, resolveTarget, loadCustomSafeOutputJobTypes, + resolveIssueNumber, + extractAssignees, }; diff --git a/actions/setup/js/unassign_from_user.cjs b/actions/setup/js/unassign_from_user.cjs index 02eb7be45e..396e7dbdf5 100644 --- a/actions/setup/js/unassign_from_user.cjs +++ b/actions/setup/js/unassign_from_user.cjs @@ -8,6 +8,7 @@ const { processItems } = require("./safe_output_processor.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs"); +const { resolveIssueNumber, extractAssignees } = require("./safe_output_helpers.cjs"); /** @type {string} Safe output type handled by this module */ const HANDLER_TYPE = "unassign_from_user"; @@ -57,37 +58,19 @@ async function main(config = {}) { const unassignItem = message; - // Determine issue number - let issueNumber; - if (unassignItem.issue_number !== undefined) { - issueNumber = parseInt(String(unassignItem.issue_number), 10); - if (isNaN(issueNumber)) { - core.warning(`Invalid issue_number: ${unassignItem.issue_number}`); - return { - success: false, - error: `Invalid issue_number: ${unassignItem.issue_number}`, - }; - } - } else { - // Use context issue if available - const contextIssue = context.payload?.issue?.number; - if (!contextIssue) { - core.warning("No issue_number provided and not in issue context"); - return { - success: false, - error: "No issue number available", - }; - } - issueNumber = contextIssue; + // Determine issue number using shared helper + const issueResult = resolveIssueNumber(unassignItem); + if (!issueResult.success) { + core.warning(`Skipping unassign_from_user: ${issueResult.error}`); + return { + success: false, + error: issueResult.error, + }; } + const issueNumber = issueResult.issueNumber; - // Support both singular "assignee" and plural "assignees" for flexibility - let requestedAssignees = []; - if (unassignItem.assignees && Array.isArray(unassignItem.assignees)) { - requestedAssignees = unassignItem.assignees; - } else if (unassignItem.assignee) { - requestedAssignees = [unassignItem.assignee]; - } + // Extract assignees using shared helper + const requestedAssignees = extractAssignees(unassignItem); core.info(`Requested assignees to unassign: ${JSON.stringify(requestedAssignees)}`);