Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
59 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Every install in g1t's workflows and deploy tool goes through scripts/deploy/npm-ci.mjs, which runs npm ci again when a connection drops: npm does not retry a body that breaks off midway, so an ECONNRESET or network aborted, an install that ends without saying why, or one that prints nothing for 12 minutes is tried again, up to three times; a real error, such as a lockfile out of step, still fails at once. A test keeps every workflow on it.1import { test } from "node:test";
2import assert from "node:assert/strict";
3import { npmCi, retryable } from "./npm-ci.mjs";
4
5const quiet = () => {};
6const noSleep = async () => {};
7
8/** A fake npm that answers each try in turn. */
9function tries(...answers) {
10 const seen = [];
11 const run = async (args) => {
12 seen.push(args);
13 return { stalled: false, output: "", ...answers[seen.length - 1] };
14 };
15 return { seen, run };
16}
17
18test("a body that broke off is worth another try, a lockfile out of step is not", () => {
19 assert.equal(retryable("npm error code ECONNRESET\nnpm error network aborted"), true);
20 assert.equal(retryable("npm error request to https://registry.npmjs.org/x failed, reason: socket hang up"), true);
21 assert.equal(retryable("npm error code EAI_AGAIN"), true);
22 assert.equal(retryable("npm error `npm ci` can only install packages when your package.json and package-lock.json are in sync"), false);
23 assert.equal(retryable("npm error code E404"), false);
24});
25
26test("an install that ends without saying why, or stalls, is tried again", () => {
27 assert.equal(retryable(""), true);
28 assert.equal(retryable("added 12 packages"), true);
29 assert.equal(retryable("npm error code E404", { stalled: true }), true);
30});
31
32test("a dropped connection is tried again until the install passes", async () => {
33 const waits = [];
34 const { seen, run } = tries({ code: 1, output: "npm error code ECONNRESET" }, { code: 0 });
35 const code = await npmCi(["--prefer-offline", "--no-audit"], { run, sleep: async (ms) => waits.push(ms), waits: [5, 15], log: quiet });
36 assert.equal(code, 0);
37 assert.equal(seen.length, 2);
38 assert.deepEqual(seen[1], ["ci", "--prefer-offline", "--no-audit"]);
39 assert.deepEqual(waits, [5]);
40});
41
42test("a real error fails at once", async () => {
43 const { seen, run } = tries({ code: 1, output: "npm error code ERESOLVE" });
44 assert.equal(await npmCi([], { run, sleep: noSleep, log: quiet }), 1);
45 assert.equal(seen.length, 1);
46});
47
48test("it gives up after its tries, with npm's exit code", async () => {
49 const reset = { code: 7, output: "npm error network aborted" };
50 const { seen, run } = tries(reset, reset, reset, reset);
51 assert.equal(await npmCi([], { run, sleep: noSleep, attempts: 3, log: quiet }), 7);
52 assert.equal(seen.length, 3);
53});
54
55test("a stalled install is run again", async () => {
56 const { seen, run } = tries({ code: 1, stalled: true }, { code: 0 });
57 assert.equal(await npmCi([], { run, sleep: noSleep, log: quiet }), 0);
58 assert.equal(seen.length, 2);
59});