diff --git a/actions/setup/js/generate_git_patch.cjs b/actions/setup/js/generate_git_patch.cjs index d485f8ecc59..73752c28356 100644 --- a/actions/setup/js/generate_git_patch.cjs +++ b/actions/setup/js/generate_git_patch.cjs @@ -6,6 +6,7 @@ const path = require("path"); const { getErrorMessage } = require("./error_helpers.cjs"); const { execGitSync } = require("./git_helpers.cjs"); +const { ERR_SYSTEM } = require("./error_codes.cjs"); /** * Debug logging helper - logs to stderr when DEBUG env var matches @@ -163,7 +164,7 @@ async function generateGitPatch(branchName, baseBranch, options = {}) { } else { // No remote refs available - fall through to Strategy 2 debugLog(`Strategy 1 (full): No remote refs available, falling through to Strategy 2`); - throw new Error("No remote refs available for merge-base calculation"); + throw new Error(`${ERR_SYSTEM}: No remote refs available for merge-base calculation`); } } } diff --git a/actions/setup/js/generate_git_patch.test.cjs b/actions/setup/js/generate_git_patch.test.cjs index 01f9b2af5c5..1dd690a024f 100644 --- a/actions/setup/js/generate_git_patch.test.cjs +++ b/actions/setup/js/generate_git_patch.test.cjs @@ -324,6 +324,44 @@ describe("sanitizeBranchNameForPatch", () => { }); }); +describe("generateGitPatch - standardized error codes", () => { + let originalEnv; + + beforeEach(() => { + originalEnv = { + GITHUB_SHA: process.env.GITHUB_SHA, + GITHUB_WORKSPACE: process.env.GITHUB_WORKSPACE, + }; + }); + + afterEach(() => { + Object.keys(originalEnv).forEach(key => { + if (originalEnv[key] !== undefined) { + process.env[key] = originalEnv[key]; + } else { + delete process.env[key]; + } + }); + }); + + it("should fail gracefully and return a non-empty error string when no commits can be found", async () => { + const { generateGitPatch } = await import("./generate_git_patch.cjs"); + + process.env.GITHUB_WORKSPACE = "/tmp/nonexistent-repo"; + process.env.GITHUB_SHA = "abc123"; + + const result = await generateGitPatch("feature-branch", "main"); + + expect(result.success).toBe(false); + expect(result).toHaveProperty("error"); + // Note: E005 is used as an internal control-flow signal in Strategy 1 (full mode) + // and is caught before reaching the final return value. The conformance check + // validates the E005 code at source level via check-safe-outputs-conformance.sh. + expect(typeof result.error).toBe("string"); + expect(result.error.length).toBeGreaterThan(0); + }); +}); + describe("getPatchPath", () => { it("should return correct path format", async () => { const { getPatchPath } = await import("./generate_git_patch.cjs");