From 81bf39a673e45dfe1e50ca0f8a3a94b168c2bfa4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 16:29:56 +0000 Subject: [PATCH 1/5] Initial plan From e5618d6688decb69daab031193a48fb8b701536f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 16:38:17 +0000 Subject: [PATCH 2/5] Changes before error encountered Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/create_discussion.cjs | 30 ++++++++++++++++++- actions/setup/js/create_project.cjs | 29 +++++++++++++++++- .../setup/js/create_project_status_update.cjs | 1 - 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/actions/setup/js/create_discussion.cjs b/actions/setup/js/create_discussion.cjs index d72b484832..558d5a44d5 100644 --- a/actions/setup/js/create_discussion.cjs +++ b/actions/setup/js/create_discussion.cjs @@ -10,7 +10,7 @@ const HANDLER_TYPE = "create_discussion"; const { getTrackerID } = require("./get_tracker_id.cjs"); const { sanitizeTitle, applyTitlePrefix } = require("./sanitize_title.cjs"); -const { replaceTemporaryIdReferences } = require("./temporary_id.cjs"); +const { generateTemporaryId, isTemporaryId, normalizeTemporaryId, replaceTemporaryIdReferences } = require("./temporary_id.cjs"); const { parseAllowedRepos, getDefaultTargetRepo, validateRepo, parseRepoSlug } = require("./repo_helpers.cjs"); const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); @@ -460,6 +460,34 @@ async function main(config = {}) { const categoryId = resolvedCategory.id; core.info(`Using category: ${resolvedCategory.name} (${resolvedCategory.matchType})`); + // Get or generate the temporary ID for this discussion + let temporaryId = generateTemporaryId(); + if (message.temporary_id !== undefined && message.temporary_id !== null) { + if (typeof message.temporary_id !== "string") { + const error = `temporary_id must be a string (got ${typeof message.temporary_id})`; + core.warning(`Skipping discussion: ${error}`); + return { + success: false, + error, + }; + } + + const rawTemporaryId = message.temporary_id.trim(); + const normalized = rawTemporaryId.startsWith("#") ? rawTemporaryId.substring(1).trim() : rawTemporaryId; + + if (!isTemporaryId(normalized)) { + const error = `Invalid temporary_id format: '${message.temporary_id}'. Temporary IDs must be in format 'aw_' followed by 3 to 8 alphanumeric characters (A-Za-z0-9). Example: 'aw_abc' or 'aw_Test123'`; + core.warning(`Skipping discussion: ${error}`); + return { + success: false, + error, + }; + } + + temporaryId = normalized.toLowerCase(); + } + core.info(`Processing create_discussion: title=${message.title}, bodyLength=${message.body?.length ?? 0}, temporaryId=${temporaryId}, repo=${qualifiedItemRepo}`); + // Build labels array (merge config labels with item-specific labels) const discussionLabels = [...labels, ...(Array.isArray(item.labels) ? item.labels : [])] .filter(Boolean) diff --git a/actions/setup/js/create_project.cjs b/actions/setup/js/create_project.cjs index ba2d9c11fd..0cb398f69d 100644 --- a/actions/setup/js/create_project.cjs +++ b/actions/setup/js/create_project.cjs @@ -3,7 +3,7 @@ const { loadAgentOutput } = require("./load_agent_output.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); -const { normalizeTemporaryId, isTemporaryId } = require("./temporary_id.cjs"); +const { normalizeTemporaryId, isTemporaryId, generateTemporaryId } = require("./temporary_id.cjs"); /** * Log detailed GraphQL error information @@ -343,6 +343,33 @@ async function main(config = {}, githubClient = null) { try { let { title, owner, owner_type, item_url } = message; + // Get or generate the temporary ID for this project + let temporaryId = generateTemporaryId(); + if (message.temporary_id !== undefined && message.temporary_id !== null) { + if (typeof message.temporary_id !== "string") { + const error = `temporary_id must be a string (got ${typeof message.temporary_id})`; + core.warning(`Skipping project: ${error}`); + return { + success: false, + error, + }; + } + + const rawTemporaryId = message.temporary_id.trim(); + const normalized = rawTemporaryId.startsWith("#") ? rawTemporaryId.substring(1).trim() : rawTemporaryId; + + if (!isTemporaryId(normalized)) { + const error = `Invalid temporary_id format: '${message.temporary_id}'. Temporary IDs must be in format 'aw_' followed by 3 to 8 alphanumeric characters (A-Za-z0-9). Example: 'aw_abc' or 'aw_Test123'`; + core.warning(`Skipping project: ${error}`); + return { + success: false, + error, + }; + } + + temporaryId = normalized.toLowerCase(); + } + // Resolve temporary ID in item_url if present if (item_url && typeof item_url === "string") { // Check if item_url contains a temporary ID (either as URL or plain ID) diff --git a/actions/setup/js/create_project_status_update.cjs b/actions/setup/js/create_project_status_update.cjs index f888a678c8..656b6fce7e 100644 --- a/actions/setup/js/create_project_status_update.cjs +++ b/actions/setup/js/create_project_status_update.cjs @@ -375,7 +375,6 @@ async function main(config = {}, githubClient = null) { previewInfo: { projectUrl: effectiveProjectUrl, status, - title, }, }; } From 3e6b5de39b168c0d1a3bbc93402422e73846f331 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 17:20:03 +0000 Subject: [PATCH 3/5] Refactor temporary ID validation into reusable helper function Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/create_discussion.cjs | 35 ++++++--------------- actions/setup/js/create_issue.cjs | 35 ++++++--------------- actions/setup/js/create_project.cjs | 35 ++++++--------------- actions/setup/js/temporary_id.cjs | 43 ++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 75 deletions(-) diff --git a/actions/setup/js/create_discussion.cjs b/actions/setup/js/create_discussion.cjs index 558d5a44d5..96ca571c69 100644 --- a/actions/setup/js/create_discussion.cjs +++ b/actions/setup/js/create_discussion.cjs @@ -10,7 +10,7 @@ const HANDLER_TYPE = "create_discussion"; const { getTrackerID } = require("./get_tracker_id.cjs"); const { sanitizeTitle, applyTitlePrefix } = require("./sanitize_title.cjs"); -const { generateTemporaryId, isTemporaryId, normalizeTemporaryId, replaceTemporaryIdReferences } = require("./temporary_id.cjs"); +const { generateTemporaryId, isTemporaryId, normalizeTemporaryId, getOrGenerateTemporaryId, replaceTemporaryIdReferences } = require("./temporary_id.cjs"); const { parseAllowedRepos, getDefaultTargetRepo, validateRepo, parseRepoSlug } = require("./repo_helpers.cjs"); const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); @@ -461,31 +461,16 @@ async function main(config = {}) { core.info(`Using category: ${resolvedCategory.name} (${resolvedCategory.matchType})`); // Get or generate the temporary ID for this discussion - let temporaryId = generateTemporaryId(); - if (message.temporary_id !== undefined && message.temporary_id !== null) { - if (typeof message.temporary_id !== "string") { - const error = `temporary_id must be a string (got ${typeof message.temporary_id})`; - core.warning(`Skipping discussion: ${error}`); - return { - success: false, - error, - }; - } - - const rawTemporaryId = message.temporary_id.trim(); - const normalized = rawTemporaryId.startsWith("#") ? rawTemporaryId.substring(1).trim() : rawTemporaryId; - - if (!isTemporaryId(normalized)) { - const error = `Invalid temporary_id format: '${message.temporary_id}'. Temporary IDs must be in format 'aw_' followed by 3 to 8 alphanumeric characters (A-Za-z0-9). Example: 'aw_abc' or 'aw_Test123'`; - core.warning(`Skipping discussion: ${error}`); - return { - success: false, - error, - }; - } - - temporaryId = normalized.toLowerCase(); + const tempIdResult = getOrGenerateTemporaryId(message, "discussion"); + if (tempIdResult.error) { + core.warning(`Skipping discussion: ${tempIdResult.error}`); + return { + success: false, + error: tempIdResult.error, + }; } + // At this point, temporaryId is guaranteed to be a string (not null) + const temporaryId = /** @type {string} */ tempIdResult.temporaryId; core.info(`Processing create_discussion: title=${message.title}, bodyLength=${message.body?.length ?? 0}, temporaryId=${temporaryId}, repo=${qualifiedItemRepo}`); // Build labels array (merge config labels with item-specific labels) diff --git a/actions/setup/js/create_issue.cjs b/actions/setup/js/create_issue.cjs index 677cf7cebd..eb5925f442 100644 --- a/actions/setup/js/create_issue.cjs +++ b/actions/setup/js/create_issue.cjs @@ -30,7 +30,7 @@ const { sanitizeTitle, applyTitlePrefix } = require("./sanitize_title.cjs"); const { generateFooterWithMessages } = require("./messages_footer.cjs"); const { generateWorkflowIdMarker } = require("./generate_footer.cjs"); const { getTrackerID } = require("./get_tracker_id.cjs"); -const { generateTemporaryId, isTemporaryId, normalizeTemporaryId, replaceTemporaryIdReferences } = require("./temporary_id.cjs"); +const { generateTemporaryId, isTemporaryId, normalizeTemporaryId, getOrGenerateTemporaryId, replaceTemporaryIdReferences } = require("./temporary_id.cjs"); const { parseAllowedRepos, getDefaultTargetRepo, validateRepo, parseRepoSlug } = require("./repo_helpers.cjs"); const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); @@ -309,31 +309,16 @@ async function main(config = {}) { } // Get or generate the temporary ID for this issue - let temporaryId = generateTemporaryId(); - if (message.temporary_id !== undefined && message.temporary_id !== null) { - if (typeof message.temporary_id !== "string") { - const error = `temporary_id must be a string (got ${typeof message.temporary_id})`; - core.warning(`Skipping issue: ${error}`); - return { - success: false, - error, - }; - } - - const rawTemporaryId = message.temporary_id.trim(); - const normalized = rawTemporaryId.startsWith("#") ? rawTemporaryId.substring(1).trim() : rawTemporaryId; - - if (!isTemporaryId(normalized)) { - const error = `Invalid temporary_id format: '${message.temporary_id}'. Temporary IDs must be in format 'aw_' followed by 3 to 8 alphanumeric characters (A-Za-z0-9). Example: 'aw_abc' or 'aw_Test123'`; - core.warning(`Skipping issue: ${error}`); - return { - success: false, - error, - }; - } - - temporaryId = normalized.toLowerCase(); + const tempIdResult = getOrGenerateTemporaryId(message, "issue"); + if (tempIdResult.error) { + core.warning(`Skipping issue: ${tempIdResult.error}`); + return { + success: false, + error: tempIdResult.error, + }; } + // At this point, temporaryId is guaranteed to be a string (not null) + const temporaryId = /** @type {string} */ tempIdResult.temporaryId; core.info(`Processing create_issue: title=${message.title}, bodyLength=${message.body?.length ?? 0}, temporaryId=${temporaryId}, repo=${qualifiedItemRepo}`); // Resolve parent: check if it's a temporary ID reference diff --git a/actions/setup/js/create_project.cjs b/actions/setup/js/create_project.cjs index 0cb398f69d..e3378c8cb7 100644 --- a/actions/setup/js/create_project.cjs +++ b/actions/setup/js/create_project.cjs @@ -3,7 +3,7 @@ const { loadAgentOutput } = require("./load_agent_output.cjs"); const { getErrorMessage } = require("./error_helpers.cjs"); -const { normalizeTemporaryId, isTemporaryId, generateTemporaryId } = require("./temporary_id.cjs"); +const { normalizeTemporaryId, isTemporaryId, generateTemporaryId, getOrGenerateTemporaryId } = require("./temporary_id.cjs"); /** * Log detailed GraphQL error information @@ -344,31 +344,16 @@ async function main(config = {}, githubClient = null) { let { title, owner, owner_type, item_url } = message; // Get or generate the temporary ID for this project - let temporaryId = generateTemporaryId(); - if (message.temporary_id !== undefined && message.temporary_id !== null) { - if (typeof message.temporary_id !== "string") { - const error = `temporary_id must be a string (got ${typeof message.temporary_id})`; - core.warning(`Skipping project: ${error}`); - return { - success: false, - error, - }; - } - - const rawTemporaryId = message.temporary_id.trim(); - const normalized = rawTemporaryId.startsWith("#") ? rawTemporaryId.substring(1).trim() : rawTemporaryId; - - if (!isTemporaryId(normalized)) { - const error = `Invalid temporary_id format: '${message.temporary_id}'. Temporary IDs must be in format 'aw_' followed by 3 to 8 alphanumeric characters (A-Za-z0-9). Example: 'aw_abc' or 'aw_Test123'`; - core.warning(`Skipping project: ${error}`); - return { - success: false, - error, - }; - } - - temporaryId = normalized.toLowerCase(); + const tempIdResult = getOrGenerateTemporaryId(message, "project"); + if (tempIdResult.error) { + core.warning(`Skipping project: ${tempIdResult.error}`); + return { + success: false, + error: tempIdResult.error, + }; } + // At this point, temporaryId is guaranteed to be a string (not null) + const temporaryId = /** @type {string} */ tempIdResult.temporaryId; // Resolve temporary ID in item_url if present if (item_url && typeof item_url === "string") { diff --git a/actions/setup/js/temporary_id.cjs b/actions/setup/js/temporary_id.cjs index 5c3b810d5a..35422cd713 100644 --- a/actions/setup/js/temporary_id.cjs +++ b/actions/setup/js/temporary_id.cjs @@ -96,6 +96,48 @@ function replaceTemporaryIdReferencesLegacy(text, tempIdMap) { }); } +/** + * Validate and process a temporary_id from a message + * Auto-generates a temporary ID if not provided, or validates and normalizes if provided + * + * @param {Object} message - The message object that may contain a temporary_id field + * @param {string} entityType - Type of entity (e.g., "issue", "discussion", "project") for error messages + * @returns {{temporaryId: string, error: null} | {temporaryId: null, error: string}} Result with temporaryId or error + */ +function getOrGenerateTemporaryId(message, entityType = "item") { + // Auto-generate if not provided + if (message.temporary_id === undefined || message.temporary_id === null) { + return { + temporaryId: generateTemporaryId(), + error: null, + }; + } + + // Validate type + if (typeof message.temporary_id !== "string") { + return { + temporaryId: null, + error: `temporary_id must be a string (got ${typeof message.temporary_id})`, + }; + } + + // Normalize and validate format + const rawTemporaryId = message.temporary_id.trim(); + const normalized = rawTemporaryId.startsWith("#") ? rawTemporaryId.substring(1).trim() : rawTemporaryId; + + if (!isTemporaryId(normalized)) { + return { + temporaryId: null, + error: `Invalid temporary_id format: '${message.temporary_id}'. Temporary IDs must be in format 'aw_' followed by 3 to 8 alphanumeric characters (A-Za-z0-9). Example: 'aw_abc' or 'aw_Test123'`, + }; + } + + return { + temporaryId: normalized.toLowerCase(), + error: null, + }; +} + /** * Load the temporary ID map from environment variable * Supports both old format (temporary_id -> number) and new format (temporary_id -> {repo, number}) @@ -470,6 +512,7 @@ module.exports = { generateTemporaryId, isTemporaryId, normalizeTemporaryId, + getOrGenerateTemporaryId, replaceTemporaryIdReferences, replaceTemporaryIdReferencesLegacy, loadTemporaryIdMap, From d0fdfb0f7e464b697b2889deac627a556496b68c Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 09:31:59 -0800 Subject: [PATCH 4/5] Fix TypeScript strict null check error in create_issue.cjs (#15721) * Initial plan * Fix TypeScript null check error in create_issue.cjs line 488 Wrap temporaryId with String() before passing to normalizeTemporaryId(). TypeScript's strict null checking was complaining that temporaryId could be null even though we checked for error earlier. The String() wrapper satisfies TypeScript's type system while maintaining the same runtime behavior (normalizeTemporaryId already does String() conversion internally). Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/create_issue.cjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/create_issue.cjs b/actions/setup/js/create_issue.cjs index eb5925f442..4c49a49b0f 100644 --- a/actions/setup/js/create_issue.cjs +++ b/actions/setup/js/create_issue.cjs @@ -485,7 +485,9 @@ async function main(config = {}) { createdIssues.push({ ...issue, _repo: qualifiedItemRepo }); // Store the mapping of temporary_id -> {repo, number} - temporaryIdMap.set(normalizeTemporaryId(temporaryId), { repo: qualifiedItemRepo, number: issue.number }); + // temporaryId is guaranteed to be non-null because we checked tempIdResult.error above + const normalizedTempId = normalizeTemporaryId(String(temporaryId)); + temporaryIdMap.set(normalizedTempId, { repo: qualifiedItemRepo, number: issue.number }); core.info(`Stored temporary ID mapping: ${temporaryId} -> ${qualifiedItemRepo}#${issue.number}`); // Track issue for copilot assignment if needed From d6c33dadf46aa01ba3663a4b75dc04afeaf34233 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 09:39:55 -0800 Subject: [PATCH 5/5] Fix failing GitHub Actions workflow for Integration: Workflow Misc Part 2 (#15722) * Initial plan * Fix docker_api_proxy_test expectations for LLM gateway support Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/docker_api_proxy_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/workflow/docker_api_proxy_test.go b/pkg/workflow/docker_api_proxy_test.go index 4f8f6c9283..d6c41e65ae 100644 --- a/pkg/workflow/docker_api_proxy_test.go +++ b/pkg/workflow/docker_api_proxy_test.go @@ -15,9 +15,9 @@ func TestCollectDockerImages_APIProxyForEnginesWithLLMGateway(t *testing.T) { expectAPIProxy bool }{ { - name: "Claude engine does not include api-proxy image (supportsLLMGateway: false)", + name: "Claude engine includes api-proxy image (supportsLLMGateway: 10000)", engine: "claude", - expectAPIProxy: false, + expectAPIProxy: true, }, { name: "Copilot engine does not include api-proxy image (supportsLLMGateway: false)", @@ -25,9 +25,9 @@ func TestCollectDockerImages_APIProxyForEnginesWithLLMGateway(t *testing.T) { expectAPIProxy: false, }, { - name: "Codex engine does not include api-proxy image (supportsLLMGateway: false)", + name: "Codex engine includes api-proxy image (supportsLLMGateway: 10001)", engine: "codex", - expectAPIProxy: false, + expectAPIProxy: true, }, }