@tablation/crew 0.127.2 → 0.127.4
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/cli.js +30 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6215,7 +6215,8 @@ async function raiseShipAttention(o, item) {
|
|
|
6215
6215
|
const previous = store.previous();
|
|
6216
6216
|
const next = upsert(previous, item);
|
|
6217
6217
|
store.persist(next);
|
|
6218
|
-
|
|
6218
|
+
const changed2 = item.kind === "sandbox_cache" && previous.some((i) => i.key === item.key && i.message !== item.message);
|
|
6219
|
+
if (transitions(previous, next).length === 0 && !changed2) return false;
|
|
6219
6220
|
announce(o.emit, item);
|
|
6220
6221
|
if (o.route && o.ship) {
|
|
6221
6222
|
await notify(o.route, o.ship, { level: "warn", headline: item.message }, o.emit);
|
|
@@ -12704,7 +12705,7 @@ var SandboxCache = class {
|
|
|
12704
12705
|
try {
|
|
12705
12706
|
await this.helper(this.s.helperImage, REFRESH_SCRIPT, [mirrorRelPath(r), forgeDescriptorFor(r.host).httpsUrl(r.host, r.path)], env);
|
|
12706
12707
|
} catch (e) {
|
|
12707
|
-
out.push({ repo: r, ok: false, detail: describe(e) });
|
|
12708
|
+
out.push({ repo: r, ok: false, detail: r.token ? describe(e) : `no readable forge token for ${r.host} (see \`crew forge list\`); ${describe(e)}` });
|
|
12708
12709
|
continue;
|
|
12709
12710
|
}
|
|
12710
12711
|
if (this.s.depsCommand && this.s.depsImage) {
|
|
@@ -12808,6 +12809,10 @@ function cacheSettingsOf(cfg) {
|
|
|
12808
12809
|
};
|
|
12809
12810
|
}
|
|
12810
12811
|
var sandboxCacheKey = (volume, r) => `sandbox_cache:${volume}:${r.host}/${r.path}`;
|
|
12812
|
+
function unmirroredRepos(served, mirrors) {
|
|
12813
|
+
const have = new Set(mirrors.map((m) => `${m.repo.host}/${m.repo.path}`));
|
|
12814
|
+
return served.map((r) => `${r.host}/${r.path}`).filter((k, i, a) => !have.has(k) && a.indexOf(k) === i);
|
|
12815
|
+
}
|
|
12811
12816
|
var CACHE_REFRESH_INTERVAL_MS = 6e4;
|
|
12812
12817
|
function makeCachePass(o) {
|
|
12813
12818
|
const now = o.now ?? Date.now;
|
|
@@ -12830,7 +12835,7 @@ function makeCachePass(o) {
|
|
|
12830
12835
|
for (const out of all) {
|
|
12831
12836
|
const key = sandboxCacheKey(o.volume, out.repo);
|
|
12832
12837
|
if (out.ok) o.ok(key);
|
|
12833
|
-
else await o.fail(key, `sandbox cache: ${out.repo.host}/${out.repo.path} did not refresh (${out.detail}); runs use the previous mirror. Resumes automatically when a later pass refreshes it
|
|
12838
|
+
else await o.fail(key, `sandbox cache: ${out.repo.host}/${out.repo.path} did not refresh (${out.detail}); runs use the previous mirror. Resumes automatically when a later pass refreshes it`, new Date(now()).toISOString());
|
|
12834
12839
|
}
|
|
12835
12840
|
return all;
|
|
12836
12841
|
};
|
|
@@ -13129,12 +13134,14 @@ function baseLayer() {
|
|
|
13129
13134
|
].join("\n");
|
|
13130
13135
|
return { name: "base", tag: `crew-sandbox-base:${hash({ SANDBOX_BASE_IMAGE, SANDBOX_OPENSHELL_VERSION })}`, dockerfile, files: {} };
|
|
13131
13136
|
}
|
|
13137
|
+
var APT_HTTPS_COMMAND = "sed -i -E 's#http://([a-z0-9.-]*\\.)?ubuntu\\.com#https://\\1ubuntu.com#g' /etc/apt/sources.list.d/ubuntu.sources 2>/dev/null || true";
|
|
13132
13138
|
function crewLayer(base, intel, bridge) {
|
|
13133
13139
|
const files = { "credential-helper": CREDENTIAL_HELPER, "mcp.json": MCP_CONFIG, ...bridge ? { "intel-bridge": bridge } : {} };
|
|
13134
13140
|
const env = Object.entries(CREW_ENV).map(([k, v]) => `${k}=${v}`).join(" ");
|
|
13135
13141
|
const dockerfile = [
|
|
13136
13142
|
`FROM ${base.tag}`,
|
|
13137
13143
|
"USER root",
|
|
13144
|
+
run2(APT_HTTPS_COMMAND),
|
|
13138
13145
|
run2(`apt-get update && apt-get install -y --no-install-recommends ca-certificates curl git${intel ? " python3 python3-venv nodejs" : ""} && rm -rf /var/lib/apt/lists/*`),
|
|
13139
13146
|
`COPY credential-helper ${CREW_PREFIX}/bin/credential-helper`,
|
|
13140
13147
|
`COPY mcp.json ${CREW_PREFIX}/mcp/mcp.json`,
|
|
@@ -13183,6 +13190,7 @@ function repoLayer(repo, decl, crew, warm) {
|
|
|
13183
13190
|
lines2.push(`FROM ${crew.tag}`, "USER root");
|
|
13184
13191
|
}
|
|
13185
13192
|
if (decl.packages.length > 0) {
|
|
13193
|
+
lines2.push(run2(APT_HTTPS_COMMAND));
|
|
13186
13194
|
lines2.push(run2(`apt-get update && apt-get install -y --no-install-recommends ${decl.packages.join(" ")} && rm -rf /var/lib/apt/lists/*`));
|
|
13187
13195
|
}
|
|
13188
13196
|
lines2.push(
|
|
@@ -19336,6 +19344,7 @@ function runForge(a, io) {
|
|
|
19336
19344
|
const tok = sourceFromArgs(a);
|
|
19337
19345
|
if (typeof tok === "string") return fail2(tok);
|
|
19338
19346
|
const doc = parseDocument4(io.readFile(io.configFile));
|
|
19347
|
+
doc.setIn(["ship", "forges", host, "username"], forgeDescriptorFor(host).credentialUsername);
|
|
19339
19348
|
doc.setIn(["ship", "forges", host, "token"], tok);
|
|
19340
19349
|
io.writeFile(io.configFile, doc.toString());
|
|
19341
19350
|
io.forges = { ...io.forges ?? {}, [host]: { username: forgeDescriptorFor(host).credentialUsername, token: tok } };
|
|
@@ -25540,7 +25549,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25540
25549
|
if (intelFlavor(loadRepoConfig(t.dir)?.hooks.intel) === "serena") intelImage = sandboxImageFor(images ??= readSandboxState(ship.stateDir), t.name);
|
|
25541
25550
|
} catch {
|
|
25542
25551
|
}
|
|
25543
|
-
out.push({ ...repo, dir: t.dir, token, username: forgeFor(ship.forges, repo.host)?.entry.username, intelImage });
|
|
25552
|
+
out.push({ ...repo, dir: t.dir, token, username: forgeFor(ship.forges, repo.host)?.entry.username || forgeDescriptorFor(repo.host).credentialUsername, intelImage });
|
|
25544
25553
|
}
|
|
25545
25554
|
return out;
|
|
25546
25555
|
}, buildSandboxCachePass = function(c, ship, state2, emit2) {
|
|
@@ -25551,7 +25560,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
25551
25560
|
volume: settings.volume,
|
|
25552
25561
|
repos: () => sandboxCacheRepos(c, ship),
|
|
25553
25562
|
lock: (dir) => acquireCheckoutLock(dir),
|
|
25554
|
-
fail: (key, message) => raiseShipAttention({ state: state2, emit: emit2, route: c, ship }, { kind: "sandbox_cache", key, message, since:
|
|
25563
|
+
fail: (key, message, failedAt) => raiseShipAttention({ state: state2, emit: emit2, route: c, ship }, { kind: "sandbox_cache", key, message, since: failedAt, lastFailedAt: failedAt }).then(() => void 0),
|
|
25555
25564
|
ok: (key) => clearShipAttention(state2, key)
|
|
25556
25565
|
});
|
|
25557
25566
|
return async () => {
|
|
@@ -28963,8 +28972,13 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28963
28972
|
}
|
|
28964
28973
|
const dropped = flag("prune") ? await cache.prune(served) : [];
|
|
28965
28974
|
const mirrors = await cache.list();
|
|
28975
|
+
const open = openShipAttention(new State(cfg.ship.stateDir));
|
|
28976
|
+
const failures = served.flatMap((r) => {
|
|
28977
|
+
const item = open.find((i) => i.kind === "sandbox_cache" && i.key === sandboxCacheKey(settings.volume, r));
|
|
28978
|
+
return item ? [{ repo: `${r.host}/${r.path}`, lastFailedAt: item.lastFailedAt ?? item.since, message: item.message }] : [];
|
|
28979
|
+
});
|
|
28966
28980
|
if (flag("json")) {
|
|
28967
|
-
process.stdout.write(`${JSON.stringify({ volume: settings.volume, mirrors, dropped }, null, 2)}
|
|
28981
|
+
process.stdout.write(`${JSON.stringify({ volume: settings.volume, mirrors, failures, dropped }, null, 2)}
|
|
28968
28982
|
`);
|
|
28969
28983
|
} else {
|
|
28970
28984
|
for (const d of dropped) process.stdout.write(`dropped ${d.host}/${d.path}
|
|
@@ -28975,6 +28989,8 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
28975
28989
|
process.stdout.write(`${m.repo.host}/${m.repo.path} last refresh ${m.lastRefresh ?? "never"}${m.intel ? ` intel ${m.intel.commit.slice(0, 12)} (${m.intel.indexedAt ?? "age unknown"})` : ""}
|
|
28976
28990
|
`);
|
|
28977
28991
|
}
|
|
28992
|
+
for (const f of failures) process.stdout.write(`${f.repo} REFRESH FAILING (last failed ${f.lastFailedAt}): ${f.message}
|
|
28993
|
+
`);
|
|
28978
28994
|
}
|
|
28979
28995
|
} catch (e) {
|
|
28980
28996
|
process.stderr.write(`crew sandbox cache: ${e instanceof Error ? e.message : String(e)}
|
|
@@ -30524,6 +30540,14 @@ watermark: ${state.watermark()}
|
|
|
30524
30540
|
for (const message of managedRuntimeWarnings(shipKind, cfg.ship)) problems.push({ severity: "attention", kind: "managed_runtime_default", message });
|
|
30525
30541
|
for (const message of managedGitIdentityWarnings(shipKind, readGlobalGitIdentity())) problems.push({ severity: "attention", kind: "managed_git_identity", message });
|
|
30526
30542
|
}
|
|
30543
|
+
const cacheSettings = cfg.ship.runner === "sandbox" ? cacheSettingsOf(cfg.ship.sandbox) : null;
|
|
30544
|
+
if (cacheSettings && !flag("offline")) {
|
|
30545
|
+
try {
|
|
30546
|
+
const missing = unmirroredRepos(sandboxCacheRepos(route2, cfg.ship), await new SandboxCache(cacheSettings).list());
|
|
30547
|
+
for (const r of missing) problems.push({ severity: "attention", kind: "sandbox_cache_unmirrored", route: route2.route, message: `${r} has no mirror in the cache volume ${cacheSettings.volume}, so sandboxed runs cannot clone it`, remedy: "see `crew sandbox cache` for the last refresh failure" });
|
|
30548
|
+
} catch {
|
|
30549
|
+
}
|
|
30550
|
+
}
|
|
30527
30551
|
for (const t of rejectedTunnels(cfg.ship.stateDir)) {
|
|
30528
30552
|
problems.push({ severity: "attention", kind: TUNNEL_REJECTED_KEY, message: tunnelRejectedMessage(t.workspaceId, t.quickExits), remedy: "rotate the slug with `crew rotate-passenger-url`" });
|
|
30529
30553
|
}
|
package/package.json
CHANGED