From 2cb0650f9de9d94c284b6f9fd30ab3ad8f737996 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Aug 2026 04:13:12 +0000 Subject: [PATCH] [jsweep] Clean run_validate_workflows.cjs Extract duplicated output truncation/sanitization logic into a shared prepareValidationOutput() helper, used for both the new-issue and existing-issue-comment code paths. Remove unused generateFooterWithMessages import. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- actions/setup/js/run_validate_workflows.cjs | 23 +++++++++++----- .../setup/js/run_validate_workflows.test.cjs | 26 +++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/actions/setup/js/run_validate_workflows.cjs b/actions/setup/js/run_validate_workflows.cjs index ff0d3be0cec..5a8073c465d 100644 --- a/actions/setup/js/run_validate_workflows.cjs +++ b/actions/setup/js/run_validate_workflows.cjs @@ -2,10 +2,23 @@ /// const { getErrorMessage } = require("./error_helpers.cjs"); -const { generateFooterWithMessages, generateXMLMarker } = require("./messages_footer.cjs"); +const { generateXMLMarker } = require("./messages_footer.cjs"); const { buildWorkflowRunUrl } = require("./workflow_metadata_helpers.cjs"); const { sanitizeContent } = require("./sanitize_content.cjs"); +const MAX_VALIDATION_OUTPUT_LENGTH = 50000; + +/** + * Truncate and sanitize validation output for safe inclusion in an issue or comment body. + * @param {string} output - Raw combined stdout/stderr output + * @param {number} [maxLength] - Maximum length before truncation + * @returns {string} Sanitized, possibly truncated output + */ +function prepareValidationOutput(output, maxLength = MAX_VALIDATION_OUTPUT_LENGTH) { + const truncated = output.substring(0, maxLength) + (output.length > maxLength ? "\n\n... (output truncated)" : ""); + return sanitizeContent(truncated); +} + /** * Run full workflow validation using gh-aw compile --validate and all known * checkers (zizmor, actionlint, poutine). If any errors or warnings are found, @@ -89,8 +102,7 @@ async function main() { const existingIssue = searchResult.data.items[0]; core.info(`Found existing issue #${existingIssue.number}: ${existingIssue.html_url}`); - const truncatedOutput = combinedOutput.substring(0, 50000) + (combinedOutput.length > 50000 ? "\n\n... (output truncated)" : ""); - const sanitizedOutput = sanitizeContent(truncatedOutput); + const sanitizedOutput = prepareValidationOutput(combinedOutput); const xmlMarker = generateXMLMarker(workflowName, runUrl); const commentBody = `Validation still has findings (exit code: ${exitCode}). @@ -131,8 +143,7 @@ ${xmlMarker}`; // No existing issue found, create a new one core.info("No existing issue found, creating a new issue with validation findings"); - const truncatedOutput = combinedOutput.substring(0, 50000) + (combinedOutput.length > 50000 ? "\n\n... (output truncated)" : ""); - const sanitizedOutput = sanitizeContent(truncatedOutput); + const sanitizedOutput = prepareValidationOutput(combinedOutput); const xmlMarker = generateXMLMarker(workflowName, runUrl); const issueBody = `## Problem @@ -198,4 +209,4 @@ ${xmlMarker} } } -module.exports = { main }; +module.exports = { main, prepareValidationOutput }; diff --git a/actions/setup/js/run_validate_workflows.test.cjs b/actions/setup/js/run_validate_workflows.test.cjs index e2efcaa25a9..df29e54b4fe 100644 --- a/actions/setup/js/run_validate_workflows.test.cjs +++ b/actions/setup/js/run_validate_workflows.test.cjs @@ -255,6 +255,32 @@ describe("run_validate_workflows", () => { expect(createCall.body).not.toMatch(/@malicious-user(?!`)/); }); + it("prepareValidationOutput returns output unchanged when under the length limit", async () => { + const { prepareValidationOutput } = await import("./run_validate_workflows.cjs"); + const result = prepareValidationOutput("short output"); + expect(result).toBe("short output"); + }); + + it("prepareValidationOutput truncates output over the default length limit", async () => { + const { prepareValidationOutput } = await import("./run_validate_workflows.cjs"); + const longOutput = "y".repeat(60000); + const result = prepareValidationOutput(longOutput); + expect(result).toContain("... (output truncated)"); + expect(result.length).toBeLessThan(longOutput.length); + }); + + it("prepareValidationOutput respects a custom max length", async () => { + const { prepareValidationOutput } = await import("./run_validate_workflows.cjs"); + const result = prepareValidationOutput("abcdefghij", 5); + expect(result).toBe("abcde\n\n... (output truncated)"); + }); + + it("prepareValidationOutput sanitizes @mentions", async () => { + const { prepareValidationOutput } = await import("./run_validate_workflows.cjs"); + const result = prepareValidationOutput("Error: @malicious-user triggered a warning"); + expect(result).not.toMatch(/@malicious-user(?!`)/); + }); + it("should sanitize output containing @mentions in comment body", async () => { mockExec.exec.mockImplementation(async (_cmd, _args, options) => { if (options?.listeners?.stderr) {