From 339bb7e4f9cbed9174e4891a2e26f6935806e3f4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:07:44 +0000 Subject: [PATCH 1/3] Add generated footer to status comment rendering in notify_comment_error.cjs Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/notify_comment_error.cjs | 19 +++++++++++++++++++ .../setup/js/notify_comment_error.test.cjs | 15 +++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/actions/setup/js/notify_comment_error.cjs b/actions/setup/js/notify_comment_error.cjs index 17f6fe0f062..20cb668da9a 100644 --- a/actions/setup/js/notify_comment_error.cjs +++ b/actions/setup/js/notify_comment_error.cjs @@ -13,6 +13,7 @@ const { sanitizeContent } = require("./sanitize_content.cjs"); const { ERR_VALIDATION } = require("./error_codes.cjs"); const { parseBoolTemplatable } = require("./templatable.cjs"); const { resolveTopLevelDiscussionCommentId } = require("./github_api_helpers.cjs"); +const { assembleMarkdownBodyParts } = require("./markdown_body_helpers.cjs"); /** * Collect generated asset URLs from safe output jobs @@ -258,6 +259,24 @@ async function main() { }); } + // Append the generated footer (attribution + XML marker) + const workflowSource = process.env.GH_AW_WORKFLOW_SOURCE ?? ""; + const workflowSourceURL = process.env.GH_AW_WORKFLOW_SOURCE_URL ?? ""; + const triggeringIssueNumber = context.payload?.issue?.number; + const triggeringPRNumber = context.payload?.pull_request?.number; + const triggeringDiscussionNumber = context.payload?.discussion?.number; + const markdownParts = assembleMarkdownBodyParts({ + includeFooter: true, + workflowName, + runUrl, + workflowSource, + workflowSourceURL, + triggeringIssueNumber, + triggeringPRNumber, + triggeringDiscussionNumber, + }); + message += "\n\n" + markdownParts.footer; + // Add "needs-review" label when detection produced a warning if (detectionConclusion === "warning") { await tryAddNeedsReviewLabel(commentRepo); diff --git a/actions/setup/js/notify_comment_error.test.cjs b/actions/setup/js/notify_comment_error.test.cjs index 3d376e43671..b5f0664721a 100644 --- a/actions/setup/js/notify_comment_error.test.cjs +++ b/actions/setup/js/notify_comment_error.test.cjs @@ -331,7 +331,7 @@ const mockCore = { (process.env.GH_AW_SAFE_OUTPUT_JOBS = JSON.stringify({ create_issue: "issue_url" })), await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); const callArgs = mockGithub.request.mock.calls[0][1]; - expect(callArgs.body).toMatch(/completed successfully!$/); + expect(callArgs.body).toContain("completed successfully!"); }), it("should handle empty safe output jobs gracefully", async () => { ((process.env.GH_AW_COMMENT_ID = "123456"), @@ -340,7 +340,7 @@ const mockCore = { (process.env.GH_AW_AGENT_CONCLUSION = "success"), await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); const callArgs = mockGithub.request.mock.calls[0][1]; - expect(callArgs.body).toMatch(/completed successfully!$/); + expect(callArgs.body).toContain("completed successfully!"); })); }), describe("when safe_outputs job fails", () => { @@ -373,5 +373,16 @@ const mockCore = { await eval(`(async () => { ${notifyCommentScript}; await main(); })()`), expect(mockGithub.request).toHaveBeenCalledWith("PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}", expect.objectContaining({ body: expect.stringContaining("completed successfully!") }))); })); + }), + describe("footer in status comment", () => { + it("should include the generated footer in the updated comment body", async () => { + ((process.env.GH_AW_COMMENT_ID = "123456"), + (process.env.GH_AW_RUN_URL = "https://github.com/owner/repo/actions/runs/123"), + (process.env.GH_AW_WORKFLOW_NAME = "test-workflow"), + (process.env.GH_AW_AGENT_CONCLUSION = "success"), + await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); + const callArgs = mockGithub.request.mock.calls[0][1]; + expect(callArgs.body).toMatch(/Generated by \[test-workflow\]/); + }); })); })); From bdb4d42e90a1befc5569bfd882e1ad9afb1cfc7c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:08:36 +0000 Subject: [PATCH 2/3] Add footer test for failure conclusion path Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/notify_comment_error.test.cjs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/notify_comment_error.test.cjs b/actions/setup/js/notify_comment_error.test.cjs index b5f0664721a..99d9e727e6b 100644 --- a/actions/setup/js/notify_comment_error.test.cjs +++ b/actions/setup/js/notify_comment_error.test.cjs @@ -383,6 +383,15 @@ const mockCore = { await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); const callArgs = mockGithub.request.mock.calls[0][1]; expect(callArgs.body).toMatch(/Generated by \[test-workflow\]/); - }); + }), + it("should include the generated footer even when agent fails", async () => { + ((process.env.GH_AW_COMMENT_ID = "123456"), + (process.env.GH_AW_RUN_URL = "https://github.com/owner/repo/actions/runs/123"), + (process.env.GH_AW_WORKFLOW_NAME = "test-workflow"), + (process.env.GH_AW_AGENT_CONCLUSION = "failure"), + await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); + const callArgs = mockGithub.request.mock.calls[0][1]; + expect(callArgs.body).toMatch(/Generated by \[test-workflow\]/); + }); })); })); From 4dd56753206cfad4ef411f65cb7ecc745e2479ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:46:23 +0000 Subject: [PATCH 3/3] fix: append footer after sanitizeContent to preserve XML traceability marker Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- actions/setup/js/notify_comment_error.cjs | 11 ++++++----- actions/setup/js/notify_comment_error.test.cjs | 6 ++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/actions/setup/js/notify_comment_error.cjs b/actions/setup/js/notify_comment_error.cjs index 20cb668da9a..02fcf63bf38 100644 --- a/actions/setup/js/notify_comment_error.cjs +++ b/actions/setup/js/notify_comment_error.cjs @@ -259,7 +259,8 @@ async function main() { }); } - // Append the generated footer (attribution + XML marker) + // Build the generated footer (attribution + XML marker). Appended after sanitization + // so that the XML traceability marker is not stripped by sanitizeContent. const workflowSource = process.env.GH_AW_WORKFLOW_SOURCE ?? ""; const workflowSourceURL = process.env.GH_AW_WORKFLOW_SOURCE_URL ?? ""; const triggeringIssueNumber = context.payload?.issue?.number; @@ -275,7 +276,7 @@ async function main() { triggeringPRNumber, triggeringDiscussionNumber, }); - message += "\n\n" + markdownParts.footer; + const footer = markdownParts.footer; // Add "needs-review" label when detection produced a warning if (detectionConclusion === "warning") { @@ -328,7 +329,7 @@ async function main() { } }`; - const sanitizedMessage = sanitizeContent(message); + const sanitizedMessage = sanitizeContent(message) + "\n\n" + footer; const variables = replyToId ? { dId: discussionId, body: sanitizedMessage, replyToId } : { dId: discussionId, body: sanitizedMessage }; const result = await github.graphql(mutation, variables); const created = result?.addDiscussionComment?.comment; @@ -345,7 +346,7 @@ async function main() { return; } - const sanitizedMessage = sanitizeContent(message); + const sanitizedMessage = sanitizeContent(message) + "\n\n" + footer; const response = await github.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", { owner: repoOwner, repo: repoName, @@ -383,7 +384,7 @@ async function main() { // Check if this is a discussion comment (GraphQL node ID format) const isDiscussionComment = commentId.startsWith("DC_"); - const sanitizedMessage = sanitizeContent(message); + const sanitizedMessage = sanitizeContent(message) + "\n\n" + footer; try { if (isDiscussionComment) { diff --git a/actions/setup/js/notify_comment_error.test.cjs b/actions/setup/js/notify_comment_error.test.cjs index 99d9e727e6b..e9eb3a2b7c0 100644 --- a/actions/setup/js/notify_comment_error.test.cjs +++ b/actions/setup/js/notify_comment_error.test.cjs @@ -375,7 +375,7 @@ const mockCore = { })); }), describe("footer in status comment", () => { - it("should include the generated footer in the updated comment body", async () => { + (it("should include the generated footer in the updated comment body", async () => { ((process.env.GH_AW_COMMENT_ID = "123456"), (process.env.GH_AW_RUN_URL = "https://github.com/owner/repo/actions/runs/123"), (process.env.GH_AW_WORKFLOW_NAME = "test-workflow"), @@ -383,6 +383,7 @@ const mockCore = { await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); const callArgs = mockGithub.request.mock.calls[0][1]; expect(callArgs.body).toMatch(/Generated by \[test-workflow\]/); + expect(callArgs.body).toMatch(/gh-aw-agentic-workflow/); }), it("should include the generated footer even when agent fails", async () => { ((process.env.GH_AW_COMMENT_ID = "123456"), @@ -392,6 +393,7 @@ const mockCore = { await eval(`(async () => { ${notifyCommentScript}; await main(); })()`)); const callArgs = mockGithub.request.mock.calls[0][1]; expect(callArgs.body).toMatch(/Generated by \[test-workflow\]/); - }); + expect(callArgs.body).toMatch(/gh-aw-agentic-workflow/); + })); })); }));