From 453ded02e51f14255e3e18e842ef4abcc159188b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 07:46:41 +0000 Subject: [PATCH 1/2] Initial plan From 8c7517417169855863974c4156b19538af3632cb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 08:00:34 +0000 Subject: [PATCH 2/2] Fix dispatch_workflow single-target backward compatibility Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/collect_ndjson_output.cjs | 10 ++++++++++ .../setup/js/collect_ndjson_output.test.cjs | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/actions/setup/js/collect_ndjson_output.cjs b/actions/setup/js/collect_ndjson_output.cjs index 16ab413fcdd..164d94b8de6 100644 --- a/actions/setup/js/collect_ndjson_output.cjs +++ b/actions/setup/js/collect_ndjson_output.cjs @@ -326,6 +326,16 @@ async function main() { const typeConfig = expectedOutputTypes[itemType]; const normalizeIssueClosingKeywords = typeConfig !== null && typeof typeConfig === "object" && typeConfig.normalize_closing_keywords === true; + if (itemType === "dispatch_workflow") { + const hasWorkflowName = typeof item.workflow_name === "string" && item.workflow_name.trim().length > 0; + if (!hasWorkflowName && typeConfig !== null && typeof typeConfig === "object" && Array.isArray(typeConfig.workflows)) { + const configuredWorkflows = typeConfig.workflows.filter(name => typeof name === "string" && name.trim().length > 0); + if (configuredWorkflows.length === 1) { + item.workflow_name = configuredWorkflows[0].trim(); + core.info(`[INGESTION] Line ${i + 1}: Inferred dispatch_workflow workflow_name='${item.workflow_name}' from safe-outputs config`); + } + } + } // Use the validation engine to validate the item if (hasValidationConfig(itemType)) { diff --git a/actions/setup/js/collect_ndjson_output.test.cjs b/actions/setup/js/collect_ndjson_output.test.cjs index a774b468b83..ca4b9551575 100644 --- a/actions/setup/js/collect_ndjson_output.test.cjs +++ b/actions/setup/js/collect_ndjson_output.test.cjs @@ -119,6 +119,13 @@ describe("collect_ndjson_output.cjs", () => { defaultMax: 1, fields: { tag: { type: "string", sanitize: !0, maxLength: 256 }, operation: { required: !0, type: "string", enum: ["replace", "append", "prepend"] }, body: { required: !0, type: "string", sanitize: !0, maxLength: 65e3 } }, }, + dispatch_workflow: { + defaultMax: 1, + fields: { + workflow_name: { required: !0, type: "string", sanitize: !0, minLength: 1, maxLength: 256, pattern: ".*\\S.*", patternError: "must not be empty" }, + inputs: { type: "object" }, + }, + }, }) )); }), @@ -195,6 +202,19 @@ describe("collect_ndjson_output.cjs", () => { const parsedOutput = JSON.parse(outputCall[1]); (expect(parsedOutput.items).toHaveLength(2), expect(parsedOutput.items[0].type).toBe("create_issue"), expect(parsedOutput.items[1].type).toBe("add_comment"), expect(parsedOutput.errors).toHaveLength(0)); }), + it("should infer dispatch_workflow workflow_name when one workflow is configured", async () => { + const testFile = "/tmp/gh-aw/test-ndjson-output.txt", + ndjsonContent = '{"type": "dispatch_workflow", "inputs": {"message": "hello"}}'; + (fs.writeFileSync(testFile, ndjsonContent), (process.env.GH_AW_SAFE_OUTPUTS = testFile)); + const __config = '{"dispatch_workflow":{"workflows":["workflow-handler"]}}', + configPath = "/tmp/gh-aw/safeoutputs/config.json"; + (fs.mkdirSync("/tmp/gh-aw/safeoutputs", { recursive: !0 }), fs.writeFileSync(configPath, __config), await eval(`(async () => { ${collectScript}; await main(); })()`)); + const setOutputCalls = mockCore.setOutput.mock.calls, + outputCall = setOutputCalls.find(call => "output" === call[0]); + expect(outputCall).toBeDefined(); + const parsedOutput = JSON.parse(outputCall[1]); + (expect(parsedOutput.items).toHaveLength(1), expect(parsedOutput.items[0].type).toBe("dispatch_workflow"), expect(parsedOutput.items[0].workflow_name).toBe("workflow-handler"), expect(parsedOutput.errors).toHaveLength(0)); + }), it("should reject items with unexpected output types", async () => { const testFile = "/tmp/gh-aw/test-ndjson-output.txt", ndjsonContent = '{"type": "create_issue", "title": "Test Issue", "body": "Test body"}\n{"type": "unexpected-type", "data": "some data"}';