@jphutchins/code-review 0.1.0-alpha.31 → 0.1.0-alpha.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1105,27 +1105,61 @@ var resolvers = {
1105
1105
  prices: (raw) => resolveSingleVersion("prices", raw)
1106
1106
  };
1107
1107
  var resolve = (kind, raw) => resolvers[kind](raw);
1108
- var describeEndpoint = (args) => args.find((a) => a === "graphql" || a.includes("/") && !a.startsWith("-")) ?? args[0] ?? "(no endpoint)";
1109
- var runGhApi = (args, stdin, env) => new Promise((resolve3, reject) => {
1108
+ var MAX_BUFFER = 100 * 1024 * 1024;
1109
+ var MAX_TIMEOUT_MS = 2147483647;
1110
+ var parseTimeoutMs = (raw, fallback) => {
1111
+ if (raw === void 0 || !/^\d+$/.test(raw)) return fallback;
1112
+ const parsed = Number(raw);
1113
+ return parsed > 0 && parsed <= MAX_TIMEOUT_MS ? parsed : fallback;
1114
+ };
1115
+ var SUBPROCESS_TIMEOUT_ENV = "CODE_REVIEW_SUBPROCESS_TIMEOUT_MS";
1116
+ var DEFAULT_SUBPROCESS_TIMEOUT_MS = 12e4;
1117
+ var subprocessTimeoutMs = () => parseTimeoutMs(process.env[SUBPROCESS_TIMEOUT_ENV], DEFAULT_SUBPROCESS_TIMEOUT_MS);
1118
+ var classifyExecError = (err, stderr, timeoutMs) => {
1119
+ const e = err;
1120
+ const stderrStr = stderr.trim();
1121
+ if (e.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER")
1122
+ return `output exceeded ${String(MAX_BUFFER)} bytes (killed)`;
1123
+ if (e.killed === true)
1124
+ return `no response within ${String(timeoutMs)}ms (killed a hung child)${stderrStr ? `: ${stderrStr}` : ""}`;
1125
+ return stderrStr || errMsg(err);
1126
+ };
1127
+ var execFileWithTimeout = (spec) => new Promise((resolve3, reject) => {
1110
1128
  const child = execFile(
1111
- "gh",
1112
- ["api", ...args],
1113
- { env: { ...process.env, ...env }, encoding: "utf-8", maxBuffer: 100 * 1024 * 1024 },
1129
+ spec.command,
1130
+ [...spec.args],
1131
+ {
1132
+ ...spec.env ? { env: { ...process.env, ...spec.env } } : {},
1133
+ encoding: "utf-8",
1134
+ maxBuffer: MAX_BUFFER,
1135
+ timeout: spec.timeoutMs,
1136
+ killSignal: "SIGKILL"
1137
+ },
1114
1138
  (err, stdout, stderr) => {
1115
- if (err) {
1116
- const stderrStr = typeof stderr === "string" && stderr.trim() ? stderr.trim() : "";
1117
- const errStr = err instanceof Error ? err.message : "unknown error";
1118
- reject(new Error(`gh api ${describeEndpoint(args)} failed: ${stderrStr || errStr}`));
1119
- } else {
1120
- resolve3(stdout);
1121
- }
1139
+ if (err)
1140
+ reject(
1141
+ new Error(`${spec.label} failed: ${classifyExecError(err, stderr, spec.timeoutMs)}`)
1142
+ );
1143
+ else resolve3(stdout);
1122
1144
  }
1123
1145
  );
1124
- if (stdin !== void 0) {
1125
- child.stdin?.end(stdin);
1146
+ if (spec.stdin !== void 0) {
1147
+ child.stdin?.on("error", () => void 0);
1148
+ child.stdin?.end(spec.stdin);
1126
1149
  }
1127
1150
  });
1128
1151
 
1152
+ // src/gh.ts
1153
+ var describeEndpoint = (args) => args.find((a) => a === "graphql" || a.includes("/") && !a.startsWith("-")) ?? args[0] ?? "(no endpoint)";
1154
+ var runGhApi = (args, stdin, env) => execFileWithTimeout({
1155
+ command: "gh",
1156
+ args: ["api", ...args],
1157
+ label: `gh api ${describeEndpoint(args)}`,
1158
+ timeoutMs: subprocessTimeoutMs(),
1159
+ env,
1160
+ stdin
1161
+ });
1162
+
1129
1163
  // src/pr.ts
1130
1164
  var CANDIDATE_JQ = ".[] | {number: .number, state: .state, headRef: .head.ref, headSha: .head.sha}";
1131
1165
  var parseCandidates = (stdout) => parseJsonl(stdout);
@@ -1988,21 +2022,11 @@ stacked=${String(result.stacked)}
1988
2022
  `;
1989
2023
  }
1990
2024
  };
1991
- var runGit = (args) => new Promise((resolve3, reject) => {
1992
- execFile(
1993
- "git",
1994
- [...args],
1995
- { encoding: "utf-8", maxBuffer: 100 * 1024 * 1024 },
1996
- (err, stdout, stderr) => {
1997
- if (err) {
1998
- const stderrStr = typeof stderr === "string" && stderr.trim() ? stderr.trim() : "";
1999
- const errStr = err instanceof Error ? err.message : "unknown error";
2000
- reject(new Error(`git ${args.join(" ")} failed: ${stderrStr || errStr}`));
2001
- } else {
2002
- resolve3(stdout);
2003
- }
2004
- }
2005
- );
2025
+ var runGit = (args) => execFileWithTimeout({
2026
+ command: "git",
2027
+ args,
2028
+ label: `git ${args.join(" ")}`,
2029
+ timeoutMs: subprocessTimeoutMs()
2006
2030
  });
2007
2031
  var PrMetaCodec = t.type({
2008
2032
  changed_files: t.number,
@@ -3290,7 +3314,7 @@ var noticeCmd = defineCommand({
3290
3314
  run: ({ args }) => {
3291
3315
  if (!isNoticeKind(args.kind)) {
3292
3316
  process.stderr.write(
3293
- `::warning::code-review notice: unrecognized kind "${args.kind}" \u2014 the pinned CLI is older than the workflow calling it; rendering a generic incomplete notice
3317
+ `::warning::code-review notice: unrecognized kind "${annotationSafe(args.kind)}" \u2014 the pinned CLI is older than the workflow calling it; rendering a generic incomplete notice
3294
3318
  `
3295
3319
  );
3296
3320
  process.stdout.write(`${JSON.stringify(buildUnknownNoticeEnvelope(args.kind), null, 2)}