@jphutchins/code-review 0.1.0-alpha.27 → 0.1.0-alpha.28

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
@@ -9,6 +9,7 @@ import { Ajv2020 } from 'ajv/dist/2020.js';
9
9
  import _addFormats from 'ajv-formats';
10
10
  import * as t from 'io-ts';
11
11
  import { execFile } from 'child_process';
12
+ import { performance } from 'perf_hooks';
12
13
  import { PathReporter } from 'io-ts/lib/PathReporter.js';
13
14
 
14
15
  // src/cost.ts
@@ -1829,15 +1830,21 @@ var RunCodec = t.type({
1829
1830
  conclusion: t.union([t.string, t.null]),
1830
1831
  run_number: t.number
1831
1832
  });
1832
- var RunsCodec = t.type({ workflow_runs: t.array(RunCodec) });
1833
+ var RUN_JQ = ".workflow_runs[] | {id: .id, name: .name, status: .status, conclusion: .conclusion, run_number: .run_number}";
1833
1834
  var resolveCiRun = async (repo, headSha, workflowName, ghApi) => {
1834
- const stdout = await ghApi([`repos/${repo}/actions/runs?head_sha=${headSha}&per_page=100`]);
1835
- const decoded = RunsCodec.decode(JSON.parse(stdout));
1836
- if (decoded._tag === "Left")
1837
- throw new Error(
1838
- `workflow runs for ${headSha} did not match the expected shape: ${PathReporter.report(decoded).join("; ")}`
1835
+ const endpoint = `repos/${repo}/actions/runs?head_sha=${headSha}&per_page=100`;
1836
+ const rows = parseJsonl(await ghApi([endpoint, "--paginate", "--jq", RUN_JQ]));
1837
+ const decoded = rows.map((row) => RunCodec.decode(row));
1838
+ const runs = decoded.flatMap((d) => d._tag === "Right" ? [d.right] : []);
1839
+ const dropped = decoded.length - runs.length;
1840
+ if (dropped > 0) {
1841
+ const firstDrift = decoded.find((d) => d._tag === "Left");
1842
+ const detail = firstDrift === void 0 ? "" : ` (${PathReporter.report(firstDrift).join("; ")})`;
1843
+ process.stderr.write(
1844
+ `Warning: ${String(dropped)} of ${String(rows.length)} workflow-run row(s) from ${endpoint} failed to decode${detail} \u2014 excluded from the lookup
1845
+ `
1839
1846
  );
1840
- const runs = decoded.right.workflow_runs;
1847
+ }
1841
1848
  const latest = runs.filter((r) => r.name === workflowName).reduce(
1842
1849
  (best, r) => best === null || r.run_number > best.run_number ? r : best,
1843
1850
  null
@@ -1848,21 +1855,34 @@ var resolveCiRun = async (repo, headSha, workflowName, ghApi) => {
1848
1855
  };
1849
1856
  };
1850
1857
  var awaitCiConclusion = async (repo, headSha, options, deps = { ghApi: runGhApi, sleep: defaultSleep, elapsedMs: monotonicElapsed() }) => {
1851
- const poll = async () => {
1852
- const { run, seenNames } = await resolveCiRun(repo, headSha, options.workflowName, deps.ghApi);
1853
- if (run !== null && run.status === "completed")
1854
- return { kind: "concluded", conclusion: run.conclusion ?? "unknown", runId: run.id };
1858
+ const safeResolve = async () => {
1859
+ try {
1860
+ return await resolveCiRun(repo, headSha, options.workflowName, deps.ghApi);
1861
+ } catch (err) {
1862
+ process.stderr.write(
1863
+ `Warning: CI-run lookup for ${headSha} failed (${errMsg(err)}) \u2014 retrying until the timeout
1864
+ `
1865
+ );
1866
+ return { run: null, seenNames: [] };
1867
+ }
1868
+ };
1869
+ const poll = async (lastSeenNames, lastRunId) => {
1870
+ const { run, seenNames } = await safeResolve();
1871
+ if (run !== null && run.status === "completed" && run.conclusion !== null)
1872
+ return { kind: "concluded", conclusion: run.conclusion, runId: run.id };
1873
+ const runId = run === null ? lastRunId : run.id;
1874
+ const names = seenNames.length > 0 ? seenNames : lastSeenNames;
1855
1875
  if (deps.elapsedMs() >= options.timeoutMs)
1856
- return { kind: "timed-out", runId: run === null ? null : run.id, seenNames };
1876
+ return { kind: "timed-out", runId, seenNames: names };
1857
1877
  await deps.sleep(options.pollIntervalMs);
1858
- return poll();
1878
+ return poll(names, runId);
1859
1879
  };
1860
- return poll();
1880
+ return poll([], null);
1861
1881
  };
1862
1882
  var defaultSleep = (ms) => new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
1863
1883
  var monotonicElapsed = () => {
1864
- const start = Date.now();
1865
- return () => Date.now() - start;
1884
+ const start = performance.now();
1885
+ return () => performance.now() - start;
1866
1886
  };
1867
1887
  var renderCiOutputs = (outcome) => outcome.kind === "concluded" ? `ci_settled=true
1868
1888
  ci_conclusion=${outcome.conclusion}