From fff214afd6de3fb18e54b0775d545313165c79f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Jun 2026 04:00:02 +0000 Subject: [PATCH 1/3] Add API version header to failure issue create calls Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/handle_agent_failure.cjs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/actions/setup/js/handle_agent_failure.cjs b/actions/setup/js/handle_agent_failure.cjs index 2d3d8e2bbf5..0106126fae3 100644 --- a/actions/setup/js/handle_agent_failure.cjs +++ b/actions/setup/js/handle_agent_failure.cjs @@ -25,6 +25,7 @@ const FAILURE_ISSUE_DEDUP_WINDOW_HOURS = 24; const FAILURE_ISSUE_CATEGORY_DAILY_CAP = 50; const FAILURE_ISSUE_WINDOW_MS = FAILURE_ISSUE_DEDUP_WINDOW_HOURS * 60 * 60 * 1000; const DEFAULT_OTEL_JSONL_PATH = "/tmp/gh-aw/otel.jsonl"; +const GITHUB_API_VERSION = "2022-11-28"; const COPILOT_SESSION_STATE_DIR = path.join(os.tmpdir(), "gh-aw", "sandbox", "agent", "logs", "copilot-session-state"); // Engine-side 429/rate-limit signatures: // - HTTP 429 accompanied by "too many requests"/"rate limit" phrasing @@ -571,6 +572,7 @@ gh aw audit title: parentTitle, body: parentBody, labels: [parentLabel], + headers: { "X-GitHub-Api-Version": GITHUB_API_VERSION }, }); core.info(`✓ Created parent issue #${newIssue.data.number}: ${newIssue.data.html_url}`); @@ -2133,6 +2135,7 @@ async function findOrCreateDailyCapRollupIssue(owner, repo) { title: DAILY_CAP_ROLLUP_TITLE, body, labels: ["agentic-workflows", DAILY_CAP_ROLLUP_LABEL], + headers: { "X-GitHub-Api-Version": GITHUB_API_VERSION }, }); core.info(`✓ Created daily cap rollup issue #${newIssue.data.number}: ${newIssue.data.html_url}`); return { number: newIssue.data.number, html_url: newIssue.data.html_url }; @@ -2216,6 +2219,7 @@ async function detectAndHandleFailureCascade(owner, repo, triggeringIssueNumber) title: CASCADE_ROLLUP_TITLE, body: rollupBody, labels: ["agentic-workflows", CASCADE_ROLLUP_LABEL], + headers: { "X-GitHub-Api-Version": GITHUB_API_VERSION }, }); core.info(`✓ Created cascade rollup issue #${newRollup.data.number}: ${newRollup.data.html_url}`); } @@ -3051,6 +3055,7 @@ async function main() { title: issueTitle, body: issueBody, labels: ["agentic-workflows"], + headers: { "X-GitHub-Api-Version": GITHUB_API_VERSION }, }); core.info(`✓ Created new issue #${newIssue.data.number}: ${newIssue.data.html_url}`); From 15be720f90501b708da636bb658dc18fbbd6f153 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Jun 2026 04:00:41 +0000 Subject: [PATCH 2/3] Test API-version header on failure issue creation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/handle_agent_failure.test.cjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/actions/setup/js/handle_agent_failure.test.cjs b/actions/setup/js/handle_agent_failure.test.cjs index 017844c5f79..97b13fb790f 100644 --- a/actions/setup/js/handle_agent_failure.test.cjs +++ b/actions/setup/js/handle_agent_failure.test.cjs @@ -421,6 +421,11 @@ describe("handle_agent_failure", () => { expect(createCommentMock).not.toHaveBeenCalled(); expect(createIssueMock).toHaveBeenCalledOnce(); + expect(createIssueMock).toHaveBeenCalledWith( + expect.objectContaining({ + headers: { "X-GitHub-Api-Version": "2022-11-28" }, + }) + ); expect(searchMock).toHaveBeenCalledWith(expect.objectContaining({ q: expect.stringContaining('"gh-aw-agentic-workflow:"') })); expect(searchMock).toHaveBeenCalledWith(expect.objectContaining({ q: expect.stringContaining('"workflow_id: test-workflow" in:body') })); }); @@ -3160,6 +3165,7 @@ describe("handle_agent_failure", () => { expect(createCall.title).toBe(CASCADE_ROLLUP_TITLE); expect(createCall.labels).toContain(CASCADE_ROLLUP_LABEL); expect(createCall.labels).toContain("agentic-workflows"); + expect(createCall.headers).toEqual({ "X-GitHub-Api-Version": "2022-11-28" }); // All 10 issues labeled expect(addLabelsMock).toHaveBeenCalledTimes(10); From 6c00eee12350e397965b14f8890fbf86ac2793b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Jun 2026 05:08:52 +0000 Subject: [PATCH 3/3] Add full API version header coverage Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../setup/js/handle_agent_failure.test.cjs | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/actions/setup/js/handle_agent_failure.test.cjs b/actions/setup/js/handle_agent_failure.test.cjs index 97b13fb790f..c04da5e1917 100644 --- a/actions/setup/js/handle_agent_failure.test.cjs +++ b/actions/setup/js/handle_agent_failure.test.cjs @@ -37,6 +37,7 @@ describe("handle_agent_failure", () => { delete global.context; delete process.env.GITHUB_SHA; delete process.env.GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS; + delete process.env.GH_AW_GROUP_REPORTS; }); describe("getActionFailureIssueExpiresHours", () => { @@ -421,15 +422,53 @@ describe("handle_agent_failure", () => { expect(createCommentMock).not.toHaveBeenCalled(); expect(createIssueMock).toHaveBeenCalledOnce(); - expect(createIssueMock).toHaveBeenCalledWith( - expect.objectContaining({ - headers: { "X-GitHub-Api-Version": "2022-11-28" }, - }) - ); + const createCall = createIssueMock.mock.calls[0][0]; + expect(createCall.headers).toEqual({ "X-GitHub-Api-Version": "2022-11-28" }); expect(searchMock).toHaveBeenCalledWith(expect.objectContaining({ q: expect.stringContaining('"gh-aw-agentic-workflow:"') })); expect(searchMock).toHaveBeenCalledWith(expect.objectContaining({ q: expect.stringContaining('"workflow_id: test-workflow" in:body') })); }); + it("creates a parent issue with the API version header when group reports are enabled", async () => { + const createCommentMock = vi.fn(); + const createIssueMock = vi.fn(async ({ title }) => ({ + data: { + number: title === "[aw] Failed runs" ? 200 : 201, + html_url: `https://github.com/owner/repo/issues/${title === "[aw] Failed runs" ? 200 : 201}`, + node_id: title === "[aw] Failed runs" ? "I_parent" : "I_child", + }, + })); + const searchMock = vi.fn(async ({ q }) => { + if (q.includes("is:pr")) { + return { data: { total_count: 0, items: [] } }; + } + return { data: { total_count: 0, items: [] } }; + }); + + process.env.GH_AW_GROUP_REPORTS = "true"; + + global.github = { + rest: { + search: { + issuesAndPullRequests: searchMock, + }, + issues: { + create: createIssueMock, + createComment: createCommentMock, + }, + pulls: { get: vi.fn() }, + }, + graphql: vi.fn(), + }; + + await main(); + + const parentCreateCall = createIssueMock.mock.calls.map(([call]) => call).find(call => call.title === "[aw] Failed runs"); + expect(parentCreateCall).toBeDefined(); + expect(parentCreateCall.headers).toEqual({ "X-GitHub-Api-Version": "2022-11-28" }); + expect(createCommentMock).not.toHaveBeenCalled(); + expect(searchMock).toHaveBeenCalledWith(expect.objectContaining({ q: expect.stringContaining('"[aw] Failed runs"') })); + }); + it("escapes workflow IDs before searching for legacy XML marker matches", async () => { const createCommentMock = vi.fn(async () => ({ data: { id: 1001 } })); const createIssueMock = vi.fn(); @@ -791,7 +830,9 @@ describe("handle_agent_failure", () => { expect(global.core.warning).toHaveBeenCalledWith(expect.stringContaining("Daily per-category issue cap reached")); expect(global.core.info).toHaveBeenCalledWith(expect.stringContaining("Summarize-and-stop")); - expect(createIssueMock).toHaveBeenCalledWith(expect.objectContaining({ title: "[aw] Daily failure issue cap exceeded" })); + const createCall = createIssueMock.mock.calls[0][0]; + expect(createCall.title).toBe("[aw] Daily failure issue cap exceeded"); + expect(createCall.headers).toEqual({ "X-GitHub-Api-Version": "2022-11-28" }); expect(createCommentMock).toHaveBeenCalledOnce(); expect(createCommentMock).toHaveBeenCalledWith(expect.objectContaining({ issue_number: 999 })); expect(global.github.rest.search.issuesAndPullRequests).toHaveBeenCalledWith(expect.objectContaining({ q: expect.stringContaining("is:open") }));