Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion actions/setup/js/add_reviewer.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const { createAuthenticatedGitHubClient } = require("./handler_auth.cjs");
const { attachExecutionState, extractReviewStateFromData, fetchPullRequestReviewState } = require("./safe_output_execution_metadata.cjs");
const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs");
const { COPILOT_REVIEWER_BOT, COPILOT_REVIEWER_BOT_ID } = require("./constants.cjs");
const { ERR_API } = require("./error_codes.cjs");

/**
* Main handler factory for add_reviewer
Expand Down Expand Up @@ -213,7 +214,7 @@ async function main(config = {}) {
});
const pullRequestId = pullRequestResponse?.repository?.pullRequest?.id;
if (!pullRequestId) {
throw new Error(`Could not resolve pull request node ID for ${repoParts.owner}/${repoParts.repo}#${prNumber}`);
throw new Error(`${ERR_API}: Could not resolve pull request node ID for ${repoParts.owner}/${repoParts.repo}#${prNumber}`);
}

const requestReviewsMutation = `
Expand Down
21 changes: 11 additions & 10 deletions actions/setup/js/apply_samples.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const fs = require("fs");
const path = require("path");
const os = require("os");
const { getErrorMessage } = require("./error_helpers.cjs");
const { ERR_VALIDATION, ERR_PARSE, ERR_SYSTEM, ERR_API, ERR_CONFIG } = require("./error_codes.cjs");

const DEFAULT_BASE_BRANCH = process.env.GH_AW_CUSTOM_BASE_BRANCH || process.env.GITHUB_BASE_REF || process.env.GITHUB_REF_NAME || "main";
const PATCH_SIDECAR_TOOLS = new Set(["create_pull_request", "push_to_pull_request_branch"]);
Expand All @@ -59,7 +60,7 @@ function loadSamples() {
try {
parsed = JSON.parse(raw);
} catch (err) {
throw new Error(`apply_samples: failed to parse GH_AW_SAMPLES as JSON: ${getErrorMessage(err)}`);
throw new Error(`${ERR_PARSE}: apply_samples: failed to parse GH_AW_SAMPLES as JSON: ${getErrorMessage(err)}`);
}
// Tolerate a literal JSON `null` payload (older compiler emitted it for
// workflows with --use-samples but no `samples:` entries). Treat as empty.
Expand All @@ -68,14 +69,14 @@ function loadSamples() {
return [];
}
if (!Array.isArray(parsed)) {
throw new Error("apply_samples: GH_AW_SAMPLES must be a JSON array");
throw new Error(`${ERR_VALIDATION}: apply_samples: GH_AW_SAMPLES must be a JSON array`);
}
for (const [i, entry] of parsed.entries()) {
if (!entry || typeof entry !== "object" || typeof entry.tool !== "string") {
throw new Error(`apply_samples: entry ${i} is missing a string "tool" field`);
throw new Error(`${ERR_VALIDATION}: apply_samples: entry ${i} is missing a string "tool" field`);
}
if (!entry.arguments || typeof entry.arguments !== "object") {
throw new Error(`apply_samples: entry ${i} (tool=${entry.tool}) is missing an "arguments" object`);
throw new Error(`${ERR_VALIDATION}: apply_samples: entry ${i} (tool=${entry.tool}) is missing an "arguments" object`);
}
}
return parsed;
Expand All @@ -91,7 +92,7 @@ function runGit(args, cwd) {
const { spawnSync } = require("child_process");
const result = spawnSync("git", args, { cwd, encoding: "utf8" });
if (result.status !== 0) {
throw new Error(`git ${args.join(" ")} failed (exit ${result.status}): ${result.stderr || result.stdout}`);
throw new Error(`${ERR_SYSTEM}: git ${args.join(" ")} failed (exit ${result.status}): ${result.stderr || result.stdout}`);
}
return result.stdout;
}
Expand Down Expand Up @@ -174,7 +175,7 @@ async function sendJsonRpc(child, stdin, request, responseIterator) {
while (true) {
const { value, done } = await responseIterator.next();
if (done) {
throw new Error(`apply_samples: MCP server closed stdout before responding to request id=${request.id}`);
throw new Error(`${ERR_API}: apply_samples: MCP server closed stdout before responding to request id=${request.id}`);
}
const line = typeof value === "string" ? value.trim() : "";
if (!line) {
Expand All @@ -187,7 +188,7 @@ async function sendJsonRpc(child, stdin, request, responseIterator) {
try {
return JSON.parse(line);
} catch (err) {
throw new Error(`apply_samples: failed to parse MCP JSON-RPC response for request id=${request.id}: ${getErrorMessage(err)} (line: ${line})`);
throw new Error(`${ERR_PARSE}: apply_samples: failed to parse MCP JSON-RPC response for request id=${request.id}: ${getErrorMessage(err)} (line: ${line})`);
}
}
}
Expand Down Expand Up @@ -231,7 +232,7 @@ function resolveMcpServerPath() {
return candidate;
}
}
throw new Error(`apply_samples: could not locate safe_outputs_mcp_server.cjs. Looked in: ${candidates.join(", ")}`);
throw new Error(`${ERR_CONFIG}: apply_samples: could not locate safe_outputs_mcp_server.cjs. Looked in: ${candidates.join(", ")}`);
}

/**
Expand Down Expand Up @@ -309,7 +310,7 @@ async function main() {
stdoutIter
);
if (initRsp.error) {
throw new Error(`MCP initialize failed: ${JSON.stringify(initRsp.error)}`);
throw new Error(`${ERR_API}: MCP initialize failed: ${JSON.stringify(initRsp.error)}`);
}

// Send one tools/call per sample.
Expand Down Expand Up @@ -363,7 +364,7 @@ async function main() {
writeSyntheticStdioLog(logPath, samples.length);

if (failures.length > 0) {
throw new Error(`apply_samples: ${failures.length} sample(s) failed:\n - ${failures.join("\n - ")}`);
throw new Error(`${ERR_API}: apply_samples: ${failures.length} sample(s) failed:\n - ${failures.join("\n - ")}`);
}
core.info(`apply_samples: ${samples.length} sample(s) replayed successfully.`);
}
Expand Down
9 changes: 5 additions & 4 deletions actions/setup/js/hide_comment.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const { getErrorMessage } = require("./error_helpers.cjs");
const { logStagedPreviewInfo } = require("./staged_preview.cjs");
const { isStagedMode } = require("./safe_output_helpers.cjs");
const { createAuthenticatedGitHubClient } = require("./handler_auth.cjs");
const { ERR_VALIDATION, ERR_API } = require("./error_codes.cjs");

/**
* Type constant for handler identification
Expand Down Expand Up @@ -53,7 +54,7 @@ async function resolveCommentNodeId(github, repoContext, commentId) {
if (typeof commentId === "string") {
const trimmed = commentId.trim();
if (!trimmed) {
throw new Error("comment_id is required");
throw new Error(`${ERR_VALIDATION}: comment_id is required`);
}

// GraphQL node IDs (e.g., IC_kwDOABCD123456) can be used directly.
Expand All @@ -65,11 +66,11 @@ async function resolveCommentNodeId(github, repoContext, commentId) {
}

if (!Number.isInteger(commentId) || commentId <= 0) {
throw new Error("comment_id must be a GraphQL node ID string or a positive numeric REST comment ID");
throw new Error(`${ERR_VALIDATION}: comment_id must be a GraphQL node ID string or a positive numeric REST comment ID`);
}

if (!repoContext || !repoContext.owner || !repoContext.repo) {
throw new Error("Unable to resolve numeric comment_id: repository context (owner/repo) is not available");
throw new Error(`${ERR_VALIDATION}: Unable to resolve numeric comment_id: repository context (owner/repo) is not available`);
}

const comment = await github.rest.issues.getComment({
Expand All @@ -80,7 +81,7 @@ async function resolveCommentNodeId(github, repoContext, commentId) {

const nodeId = comment && comment.data ? comment.data.node_id : null;
if (!nodeId || typeof nodeId !== "string") {
throw new Error(`Failed to resolve GraphQL node ID for comment_id ${commentId}: comment not found or node_id unavailable`);
throw new Error(`${ERR_API}: Failed to resolve GraphQL node ID for comment_id ${commentId}: comment not found or node_id unavailable`);
}

return nodeId;
Expand Down
2 changes: 1 addition & 1 deletion actions/setup/js/hide_comment.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ describe("hide_comment.cjs", () => {
const result = await handler({ comment_id: 0, reason: "SPAM" }, {});

expect(result.success).toBe(false);
expect(result.error).toBe("comment_id must be a GraphQL node ID string or a positive numeric REST comment ID");
expect(result.error).toBe("ERR_VALIDATION: comment_id must be a GraphQL node ID string or a positive numeric REST comment ID");
expect(mockGithub.graphql).not.toHaveBeenCalled();
});

Expand Down
5 changes: 3 additions & 2 deletions actions/setup/js/safeoutputs_cli.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

const childProcess = require("child_process");
const fs = require("fs");
const { ERR_VALIDATION, ERR_API } = require("./error_codes.cjs");
Comment thread
Copilot marked this conversation as resolved.
Outdated

/**
* @typedef {(toolName: string, args: Record<string, string>) => void} RunSafeOutputsCLILike
Expand All @@ -31,7 +32,7 @@ function runSafeOutputsCLI(toolName, args) {
for (const [key, value] of Object.entries(args)) {
if (typeof value !== "string" || value.length === 0) continue;
if (!/^[a-zA-Z0-9_-]+$/.test(key)) {
throw new Error(`invalid safeoutputs argument key: ${key}`);
throw new Error(`${ERR_VALIDATION}: invalid safeoutputs argument key: ${key}`);
}
commandArgs.push(`--${key}`);
commandArgs.push(value);
Expand All @@ -43,7 +44,7 @@ function runSafeOutputsCLI(toolName, args) {
const stderr = typeof err.stderr === "string" ? err.stderr.trim() : Buffer.isBuffer(err.stderr) ? err.stderr.toString("utf8").trim() : "";
const message = typeof err.message === "string" ? err.message : String(error);
const keysSummary = Object.keys(args).join(", ");
throw new Error(stderr ? `safeoutputs ${toolName}(${keysSummary}) failed: ${message}: ${stderr}` : `safeoutputs ${toolName}(${keysSummary}) failed: ${message}`);
throw new Error(stderr ? `${ERR_API}: safeoutputs ${toolName}(${keysSummary}) failed: ${message}: ${stderr}` : `${ERR_API}: safeoutputs ${toolName}(${keysSummary}) failed: ${message}`);
Comment thread
Copilot marked this conversation as resolved.
Outdated
}
}

Expand Down
Loading