diff --git a/actions/setup/js/checkout_pr_branch.cjs b/actions/setup/js/checkout_pr_branch.cjs index dadf69ad85..a3310b3568 100644 --- a/actions/setup/js/checkout_pr_branch.cjs +++ b/actions/setup/js/checkout_pr_branch.cjs @@ -7,6 +7,8 @@ */ const { getErrorMessage } = require("./error_helpers.cjs"); +const { renderTemplate } = require("./messages_core.cjs"); +const fs = require("fs"); async function main() { const eventName = context.eventName; @@ -40,7 +42,17 @@ async function main() { core.info(`✅ Successfully checked out PR #${prNumber}`); } } catch (error) { - core.setFailed(`Failed to checkout PR branch: ${getErrorMessage(error)}`); + const errorMsg = getErrorMessage(error); + + // Load and render step summary template + const templatePath = "/opt/gh-aw/prompts/pr_checkout_failure.md"; + const template = fs.readFileSync(templatePath, "utf8"); + const summaryContent = renderTemplate(template, { + error_message: errorMsg, + }); + + await core.summary.addRaw(summaryContent).write(); + core.setFailed(`Failed to checkout PR branch: ${errorMsg}`); } } diff --git a/actions/setup/js/checkout_pr_branch.test.cjs b/actions/setup/js/checkout_pr_branch.test.cjs index af9958e4fc..c4deb67c05 100644 --- a/actions/setup/js/checkout_pr_branch.test.cjs +++ b/actions/setup/js/checkout_pr_branch.test.cjs @@ -10,6 +10,10 @@ describe("checkout_pr_branch.cjs", () => { mockCore = { info: vi.fn(), setFailed: vi.fn(), + summary: { + addRaw: vi.fn().mockReturnThis(), + write: vi.fn().mockResolvedValue(undefined), + }, }; // Mock exec @@ -58,6 +62,47 @@ describe("checkout_pr_branch.cjs", () => { if (module === "./error_helpers.cjs") { return { getErrorMessage: error => (error instanceof Error ? error.message : String(error)) }; } + if (module === "./messages_core.cjs") { + return { + renderTemplate: (template, context) => { + return template.replace(/\{(\w+)\}/g, (match, key) => { + const value = context[key]; + return value !== undefined && value !== null ? String(value) : match; + }); + }, + }; + } + if (module === "fs") { + return { + readFileSync: (path, encoding) => { + // Return mock template for pr_checkout_failure.md + if (path.includes("pr_checkout_failure.md")) { + return `## ❌ Failed to Checkout PR Branch + +**Error:** {error_message} + +### Possible Reasons + +This failure typically occurs when: +- The pull request has been closed or merged +- The branch has been deleted +- There are insufficient permissions to access the PR + +### What to Do + +If the pull request is closed, you may need to: +1. Reopen the pull request, or +2. Create a new pull request with the changes + +If the pull request is still open, verify that: +- The branch still exists in the repository +- You have the necessary permissions to access it +`; + } + throw new Error(`Unexpected file read: ${path}`); + }, + }; + } throw new Error(`Module ${module} not mocked in test`); }; @@ -92,6 +137,14 @@ describe("checkout_pr_branch.cjs", () => { await runScript(); + expect(mockCore.summary.addRaw).toHaveBeenCalled(); + expect(mockCore.summary.write).toHaveBeenCalled(); + + const summaryCall = mockCore.summary.addRaw.mock.calls[0][0]; + expect(summaryCall).toContain("Failed to Checkout PR Branch"); + expect(summaryCall).toContain("git fetch failed"); + expect(summaryCall).toContain("pull request has been closed"); + expect(mockCore.setFailed).toHaveBeenCalledWith("Failed to checkout PR branch: git fetch failed"); }); @@ -101,6 +154,13 @@ describe("checkout_pr_branch.cjs", () => { await runScript(); + expect(mockCore.summary.addRaw).toHaveBeenCalled(); + expect(mockCore.summary.write).toHaveBeenCalled(); + + const summaryCall = mockCore.summary.addRaw.mock.calls[0][0]; + expect(summaryCall).toContain("Failed to Checkout PR Branch"); + expect(summaryCall).toContain("git checkout failed"); + expect(mockCore.setFailed).toHaveBeenCalledWith("Failed to checkout PR branch: git checkout failed"); }); }); @@ -129,6 +189,14 @@ describe("checkout_pr_branch.cjs", () => { await runScript(); + expect(mockCore.summary.addRaw).toHaveBeenCalled(); + expect(mockCore.summary.write).toHaveBeenCalled(); + + const summaryCall = mockCore.summary.addRaw.mock.calls[0][0]; + expect(summaryCall).toContain("Failed to Checkout PR Branch"); + expect(summaryCall).toContain("gh pr checkout failed"); + expect(summaryCall).toContain("pull request has been closed"); + expect(mockCore.setFailed).toHaveBeenCalledWith("Failed to checkout PR branch: gh pr checkout failed"); }); diff --git a/actions/setup/md/pr_checkout_failure.md b/actions/setup/md/pr_checkout_failure.md new file mode 100644 index 0000000000..a0eb122f69 --- /dev/null +++ b/actions/setup/md/pr_checkout_failure.md @@ -0,0 +1,20 @@ +## ❌ Failed to Checkout PR Branch + +**Error:** {error_message} + +### Possible Reasons + +This failure typically occurs when: +- The pull request has been closed or merged +- The branch has been deleted +- There are insufficient permissions to access the PR + +### What to Do + +If the pull request is closed, you may need to: +1. Reopen the pull request, or +2. Create a new pull request with the changes + +If the pull request is still open, verify that: +- The branch still exists in the repository +- You have the necessary permissions to access it