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

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
@@ -404,6 +404,7 @@ var renderStraysSection = (strays) => {
404
404
  };
405
405
  var asRecord = (u) => typeof u === "object" && u !== null && !Array.isArray(u) ? u : null;
406
406
  var errMsg = (e) => e instanceof Error ? e.message : String(e);
407
+ var annotationSafe = (msg) => msg.replaceAll(/[\r\n]+/g, " ");
407
408
  var tryParseJson = (text) => {
408
409
  try {
409
410
  return { ok: true, value: JSON.parse(text) };
@@ -972,16 +973,32 @@ var pad2 = (n) => String(n).padStart(2, "0");
972
973
  var formatUtc = (d) => `${String(d.getUTCFullYear())}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())} ${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())} UTC`;
973
974
 
974
975
  // src/notice.ts
975
- var isNoticeKind = (s) => s === "security-blocked" || s === "setup-failed" || s === "checkout-failed" || s === "no-output";
976
+ var NOTICE_KINDS = [
977
+ "security-blocked",
978
+ "triage-error",
979
+ "setup-failed",
980
+ "checkout-failed",
981
+ "no-output"
982
+ ];
983
+ var isNoticeKind = (s) => NOTICE_KINDS.some((k) => k === s);
976
984
  var blockquote = (text) => text.replaceAll("\n", "\n> ");
985
+ var reasoned = (lead, noReason, reasons) => typeof reasons === "string" && reasons.trim() !== "" ? `${lead}
986
+
987
+ > ${blockquote(reasons)}` : noReason;
977
988
  var noticeSummary = (kind, reasons) => {
978
989
  switch (kind) {
979
990
  case "security-blocked":
980
- return reasons !== void 0 && reasons.trim() !== "" ? `### \u{1F6D1} Code review skipped by the security gate
981
-
982
- The diff was flagged as unsafe to apply and execute:
983
-
984
- > ${blockquote(reasons)}` : "### \u{1F6D1} Code review skipped by the security gate\n\nThe security triage returned an unsafe verdict without a reason. See workflow logs.";
991
+ return reasoned(
992
+ "### \u{1F6D1} Code review skipped by the security gate\n\nThe diff was flagged as unsafe to apply and execute:",
993
+ "### \u{1F6D1} Code review skipped by the security gate\n\nThe security triage returned an unsafe verdict without a reason. See workflow logs.",
994
+ reasons
995
+ );
996
+ case "triage-error":
997
+ return reasoned(
998
+ "### \u{1F6E0}\uFE0F Security gate could not evaluate\n\nThe security triage could not produce a verdict (operational error), so the review failed closed \u2014 this is an infrastructure failure, not a finding about this diff. Re-run to retry a transient fault; a persistent one is a configuration issue (see the workflow logs). The triage step reported:",
999
+ "### \u{1F6E0}\uFE0F Security gate could not evaluate\n\nThe security triage could not produce a verdict (operational error), so the review failed closed \u2014 this is an infrastructure failure, not a finding about this diff. Re-run to retry a transient fault; a persistent one is a configuration issue (see the workflow logs).",
1000
+ reasons
1001
+ );
985
1002
  case "setup-failed":
986
1003
  return "### \u{1F6E0}\uFE0F Review did not run\n\nThe review job failed before the security triage could run (e.g. dependency install or environment setup). See the workflow logs \u2014 this is an infrastructure failure, not a security verdict.";
987
1004
  case "checkout-failed":
@@ -990,15 +1007,21 @@ The diff was flagged as unsafe to apply and execute:
990
1007
  return "### \u26A0\uFE0F Review did not complete\n\nThe diff passed triage but the review produced no output. See workflow logs.";
991
1008
  }
992
1009
  };
993
- var buildNoticeEnvelope = (kind, reasons) => ({
1010
+ var noticeEnvelope = (summary) => ({
994
1011
  schema_version: DEFAULT_SCHEMA_VERSION,
995
- findings: noticeFindings(noticeSummary(kind, reasons)),
1012
+ findings: noticeFindings(summary),
996
1013
  models: [],
997
1014
  turns: 0,
998
1015
  duration_ms: 0,
999
1016
  vendor_cost_usd: null,
1000
1017
  incomplete: true
1001
1018
  });
1019
+ var buildNoticeEnvelope = (kind, reasons) => noticeEnvelope(noticeSummary(kind, reasons));
1020
+ var buildUnknownNoticeEnvelope = (kind) => noticeEnvelope(
1021
+ `### \u26A0\uFE0F Review could not be rendered
1022
+
1023
+ The workflow asked for an unrecognized notice kind (\`${kind}\`) \u2014 the pinned code-review CLI is older than the workflow calling it (check that its version matches). Failing closed. See the workflow logs.`
1024
+ );
1002
1025
  var identity = (decoded) => decoded;
1003
1026
  var findingsTable = [
1004
1027
  {
@@ -1082,6 +1105,7 @@ var resolvers = {
1082
1105
  prices: (raw) => resolveSingleVersion("prices", raw)
1083
1106
  };
1084
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)";
1085
1109
  var runGhApi = (args, stdin, env) => new Promise((resolve3, reject) => {
1086
1110
  const child = execFile(
1087
1111
  "gh",
@@ -1091,7 +1115,7 @@ var runGhApi = (args, stdin, env) => new Promise((resolve3, reject) => {
1091
1115
  if (err) {
1092
1116
  const stderrStr = typeof stderr === "string" && stderr.trim() ? stderr.trim() : "";
1093
1117
  const errStr = err instanceof Error ? err.message : "unknown error";
1094
- reject(new Error(`gh api failed: ${stderrStr || errStr}`));
1118
+ reject(new Error(`gh api ${describeEndpoint(args)} failed: ${stderrStr || errStr}`));
1095
1119
  } else {
1096
1120
  resolve3(stdout);
1097
1121
  }
@@ -1105,10 +1129,17 @@ var runGhApi = (args, stdin, env) => new Promise((resolve3, reject) => {
1105
1129
  // src/pr.ts
1106
1130
  var CANDIDATE_JQ = ".[] | {number: .number, state: .state, headRef: .head.ref, headSha: .head.sha}";
1107
1131
  var parseCandidates = (stdout) => parseJsonl(stdout);
1132
+ var fetchDirectCandidates = async (repo, headSha, ghApi) => {
1133
+ try {
1134
+ return parseCandidates(
1135
+ await ghApi([`repos/${repo}/commits/${headSha}/pulls`, "--jq", CANDIDATE_JQ])
1136
+ );
1137
+ } catch {
1138
+ return [];
1139
+ }
1140
+ };
1108
1141
  var fetchPrCandidates = async (repo, headSha, ghApi) => {
1109
- const direct = parseCandidates(
1110
- await ghApi([`repos/${repo}/commits/${headSha}/pulls`, "--jq", CANDIDATE_JQ])
1111
- );
1142
+ const direct = await fetchDirectCandidates(repo, headSha, ghApi);
1112
1143
  if (direct.length > 0) return direct;
1113
1144
  const open = parseCandidates(
1114
1145
  await ghApi([
@@ -3240,25 +3271,36 @@ var adaptCmd = defineCommand({
3240
3271
  var noticeCmd = defineCommand({
3241
3272
  meta: {
3242
3273
  name: "notice",
3243
- description: "Emit an abstract envelope for a run that produced no completed review (security block, setup failure, unapplied diff, or empty run) \u2014 flagged incomplete so the commenter renders it honestly and won't bury a real review"
3274
+ description: "Emit an abstract envelope for a run that produced no completed review (security block, triage error, setup failure, checkout failure, or empty run) \u2014 flagged incomplete so the commenter renders it honestly and won't bury a real review"
3244
3275
  },
3245
3276
  args: {
3246
3277
  kind: {
3247
3278
  type: "positional",
3248
- description: "One of: security-blocked, setup-failed, checkout-failed, no-output",
3279
+ description: `One of: ${NOTICE_KINDS.join(", ")} (an unrecognized kind renders a generic incomplete notice rather than failing \u2014 the pinned CLI is older than the workflow)`,
3249
3280
  required: true
3250
3281
  },
3251
3282
  reasons: {
3252
3283
  type: "string",
3253
- description: "security-blocked only: the triage's fail-closed reason string (empty/omitted \u21D2 the no-reason wording)"
3284
+ description: "security-blocked / triage-error only: the triage's fail-closed reason string (empty/omitted \u21D2 the no-reason wording)"
3254
3285
  }
3255
3286
  },
3287
+ // An unrecognized kind degrades to a generic incomplete notice instead of exiting non-zero: a
3288
+ // `notice <kind>` call under the workflow's `set -euo pipefail` must never crash the assemble
3289
+ // step into posting nothing, and an unknown kind almost always means version skew, not a typo.
3256
3290
  run: ({ args }) => {
3257
- const kind = isNoticeKind(args.kind) ? args.kind : fail(
3258
- `Unknown notice kind "${args.kind}" \u2014 expected one of: security-blocked, setup-failed, checkout-failed, no-output`
3259
- );
3260
- process.stdout.write(`${JSON.stringify(buildNoticeEnvelope(kind, args.reasons), null, 2)}
3291
+ if (!isNoticeKind(args.kind)) {
3292
+ 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
3294
+ `
3295
+ );
3296
+ process.stdout.write(`${JSON.stringify(buildUnknownNoticeEnvelope(args.kind), null, 2)}
3261
3297
  `);
3298
+ return;
3299
+ }
3300
+ process.stdout.write(
3301
+ `${JSON.stringify(buildNoticeEnvelope(args.kind, args.reasons), null, 2)}
3302
+ `
3303
+ );
3262
3304
  }
3263
3305
  });
3264
3306
  var isExtractSchemaKind = (s) => s === "findings" || s === "triage";
@@ -3685,9 +3727,13 @@ var announceCmd = defineCommand({
3685
3727
  runUrl: args["run-url"],
3686
3728
  headBranch: args["head-branch"]
3687
3729
  }).catch(
3688
- (err) => process.stderr.write(
3689
- `code-review announce: could not post the in-progress sticky (${errMsg(err)}) \u2014 continuing (cosmetic)
3730
+ (err) => (
3731
+ // `::warning::` so a persistently broken announce shows up in the run's annotations, not only
3732
+ // buried in the step log — `announce` otherwise reports success while having posted nothing.
3733
+ process.stderr.write(
3734
+ `::warning::code-review announce: could not post the in-progress sticky (${annotationSafe(errMsg(err))}) \u2014 continuing (cosmetic)
3690
3735
  `
3736
+ )
3691
3737
  )
3692
3738
  );
3693
3739
  }