@tablation/crew 0.10.1 → 0.11.0
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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { resolve as resolve4, dirname as
|
|
4
|
+
import { resolve as resolve4, dirname as dirname10, join as join19, basename as basename7 } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { hostname as hostname2, homedir as homedir5 } from "os";
|
|
7
7
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
@@ -2323,9 +2323,14 @@ function programFromPlist(text) {
|
|
|
2323
2323
|
const args = [...block[1].matchAll(/<string>([\s\S]*?)<\/string>/g)].map((m) => xmlUnescape(m[1]));
|
|
2324
2324
|
return args.find((a) => a.endsWith("/bin/crew")) ?? args[0] ?? null;
|
|
2325
2325
|
}
|
|
2326
|
-
function
|
|
2327
|
-
|
|
2328
|
-
|
|
2326
|
+
function loadedCrewLabels() {
|
|
2327
|
+
const list = spawnSync("launchctl", ["list"], { encoding: "utf8" });
|
|
2328
|
+
if (list.status !== 0) return [];
|
|
2329
|
+
return [...parseLaunchctlList(list.stdout ?? "").keys()].filter((l) => l.startsWith(CREW_LAUNCHD_PREFIX));
|
|
2330
|
+
}
|
|
2331
|
+
function listLaunchdUnits(dir = launchAgentsDir(), loaded = []) {
|
|
2332
|
+
const files = existsSync5(dir) ? readdirSync(dir) : [];
|
|
2333
|
+
const units = files.filter((f) => f.startsWith(CREW_LAUNCHD_PREFIX) && f.endsWith(".plist")).sort().map((f) => {
|
|
2329
2334
|
const plistPath = join5(dir, f);
|
|
2330
2335
|
let program = null;
|
|
2331
2336
|
try {
|
|
@@ -2339,10 +2344,16 @@ function listLaunchdUnits(dir = launchAgentsDir()) {
|
|
|
2339
2344
|
programExists: program !== null && existsSync5(program)
|
|
2340
2345
|
};
|
|
2341
2346
|
});
|
|
2347
|
+
const seen = new Set(units.map((u) => u.label));
|
|
2348
|
+
for (const label of [...loaded].sort()) {
|
|
2349
|
+
if (!label.startsWith(CREW_LAUNCHD_PREFIX) || seen.has(label)) continue;
|
|
2350
|
+
units.push({ label, plistPath: join5(dir, `${label}.plist`), program: null, programExists: false, orphan: true });
|
|
2351
|
+
}
|
|
2352
|
+
return units;
|
|
2342
2353
|
}
|
|
2343
|
-
function foreignLaunchdUnits(crewHome, dir) {
|
|
2354
|
+
function foreignLaunchdUnits(crewHome, dir, loaded) {
|
|
2344
2355
|
const own = new Set(["run", "release", "passengers"].map((job) => labelFor(crewHome, job)));
|
|
2345
|
-
return listLaunchdUnits(dir).filter((u) => !own.has(u.label));
|
|
2356
|
+
return listLaunchdUnits(dir, loaded).filter((u) => !own.has(u.label));
|
|
2346
2357
|
}
|
|
2347
2358
|
function removeLaunchdUnit(unit, dryRun, log) {
|
|
2348
2359
|
if (dryRun) {
|
|
@@ -2354,9 +2365,9 @@ function removeLaunchdUnit(unit, dryRun, log) {
|
|
|
2354
2365
|
if (existsSync5(unit.plistPath)) unlinkSync(unit.plistPath);
|
|
2355
2366
|
log.emit(`removed ${unit.label} (${unit.plistPath})`);
|
|
2356
2367
|
}
|
|
2357
|
-
function clearForeignLaunchdUnits(crewHome, replace, dryRun, log, dir) {
|
|
2358
|
-
const foreign = foreignLaunchdUnits(crewHome, dir);
|
|
2359
|
-
const blocking = foreign.filter((u) => u.program === null || u.programExists);
|
|
2368
|
+
function clearForeignLaunchdUnits(crewHome, replace, dryRun, log, dir, loaded) {
|
|
2369
|
+
const foreign = foreignLaunchdUnits(crewHome, dir, loaded);
|
|
2370
|
+
const blocking = foreign.filter((u) => !u.orphan && (u.program === null || u.programExists));
|
|
2360
2371
|
if (blocking.length > 0 && !replace) {
|
|
2361
2372
|
log.warn(
|
|
2362
2373
|
`two crew installs target this machine: ${blocking.map((u) => `${u.label} runs ${u.program ?? "an unreadable ProgramArguments"}`).join("; ")}. Run \`crew uninstall\` from the other one, or pass --replace.`
|
|
@@ -2364,14 +2375,14 @@ function clearForeignLaunchdUnits(crewHome, replace, dryRun, log, dir) {
|
|
|
2364
2375
|
return false;
|
|
2365
2376
|
}
|
|
2366
2377
|
for (const unit of foreign) {
|
|
2367
|
-
const why = unit.program === null ? "replacing a unit with no readable ProgramArguments" : unit.programExists ? "replacing a live other install" : "removing a stale unit whose program is gone";
|
|
2378
|
+
const why = unit.orphan ? "removing a loaded job whose plist is gone" : unit.program === null ? "replacing a unit with no readable ProgramArguments" : unit.programExists ? "replacing a live other install" : "removing a stale unit whose program is gone";
|
|
2368
2379
|
log.emit(`${why}: ${unit.label}`);
|
|
2369
2380
|
removeLaunchdUnit(unit, dryRun, log);
|
|
2370
2381
|
}
|
|
2371
2382
|
return true;
|
|
2372
2383
|
}
|
|
2373
|
-
function removeAllLaunchdUnits(dryRun, log, dir) {
|
|
2374
|
-
for (const unit of listLaunchdUnits(dir)) removeLaunchdUnit(unit, dryRun, log);
|
|
2384
|
+
function removeAllLaunchdUnits(dryRun, log, dir, loaded) {
|
|
2385
|
+
for (const unit of listLaunchdUnits(dir, loaded)) removeLaunchdUnit(unit, dryRun, log);
|
|
2375
2386
|
}
|
|
2376
2387
|
function parseLaunchctlList(text) {
|
|
2377
2388
|
const jobs = /* @__PURE__ */ new Map();
|
|
@@ -2383,13 +2394,13 @@ function parseLaunchctlList(text) {
|
|
|
2383
2394
|
return jobs;
|
|
2384
2395
|
}
|
|
2385
2396
|
function describeForeignLaunchdUnits(crewHome, dir) {
|
|
2386
|
-
const foreign = foreignLaunchdUnits(crewHome, dir);
|
|
2387
|
-
if (foreign.length === 0) return [];
|
|
2388
2397
|
const list = spawnSync("launchctl", ["list"], { encoding: "utf8" });
|
|
2389
2398
|
const jobs = parseLaunchctlList(list.status === 0 ? list.stdout ?? "" : "");
|
|
2399
|
+
const foreign = foreignLaunchdUnits(crewHome, dir, jobs.keys());
|
|
2390
2400
|
return foreign.map((u) => {
|
|
2391
2401
|
const status2 = jobs.get(u.label);
|
|
2392
2402
|
const loaded = status2 ? `loaded, last exit ${status2.lastExit}` : "not loaded";
|
|
2403
|
+
if (u.orphan) return ` ${u.label}: ${loaded}; plist gone \u2014 stale: \`crew install\` removes it`;
|
|
2393
2404
|
const program = u.program ? `${u.program} (${u.programExists ? "present" : "GONE"})` : "no readable ProgramArguments";
|
|
2394
2405
|
const stale = status2 && !u.programExists ? " \u2014 stale: `crew install` removes it" : "";
|
|
2395
2406
|
return ` ${u.label}: ${loaded}; runs ${program}${stale}`;
|
|
@@ -3980,16 +3991,20 @@ function refreshBaseBranch(cwd, remote, base, dryRun = false) {
|
|
|
3980
3991
|
const [behindStr, aheadStr] = counts.split(/\s+/);
|
|
3981
3992
|
const behind = Number.parseInt(behindStr ?? "0", 10);
|
|
3982
3993
|
const ahead = Number.parseInt(aheadStr ?? "0", 10);
|
|
3994
|
+
const named = () => {
|
|
3995
|
+
const subjects = (gitOk(cwd, ["log", "--format=%h %s", "-5", `${upstream}..${base}`]) ?? "").split("\n").filter(Boolean);
|
|
3996
|
+
return subjects.length ? `: ${subjects.join("; ")}${ahead > subjects.length ? "; \u2026" : ""}` : "";
|
|
3997
|
+
};
|
|
3983
3998
|
if (ahead > 0 && behind > 0) {
|
|
3984
3999
|
return {
|
|
3985
4000
|
action: "diverged",
|
|
3986
4001
|
ahead,
|
|
3987
4002
|
behind,
|
|
3988
|
-
detail: `${base} has diverged from ${upstream} (${ahead} ahead, ${behind} behind)`
|
|
4003
|
+
detail: `${base} has diverged from ${upstream} (${ahead} ahead, ${behind} behind)${named()}`
|
|
3989
4004
|
};
|
|
3990
4005
|
}
|
|
3991
4006
|
if (behind === 0 && ahead > 0) {
|
|
3992
|
-
return { action: "ahead", ahead, detail: `${base} has ${ahead} commit(s) ${upstream} does not` };
|
|
4007
|
+
return { action: "ahead", ahead, detail: `${base} has ${ahead} commit(s) ${upstream} does not${named()}` };
|
|
3993
4008
|
}
|
|
3994
4009
|
if (behind === 0) return { action: "level", detail: `${base} is level with ${upstream}` };
|
|
3995
4010
|
if (dryRun) {
|
|
@@ -4004,8 +4019,22 @@ function refreshBaseBranch(cwd, remote, base, dryRun = false) {
|
|
|
4004
4019
|
detail: `fast-forwarded ${base} to ${upstream} (${behind} commit(s) from elsewhere)`
|
|
4005
4020
|
};
|
|
4006
4021
|
}
|
|
4007
|
-
function
|
|
4008
|
-
|
|
4022
|
+
function recoverStrandedReleaseCheckouts(cwd) {
|
|
4023
|
+
gitOk(cwd, ["worktree", "prune"]);
|
|
4024
|
+
const out = gitOk(cwd, ["worktree", "list", "--porcelain"]) ?? "";
|
|
4025
|
+
let path = "";
|
|
4026
|
+
for (const line of out.split("\n")) {
|
|
4027
|
+
if (line.startsWith("worktree ")) path = line.slice("worktree ".length);
|
|
4028
|
+
else if (line.startsWith("branch refs/heads/crew/release-") && path) {
|
|
4029
|
+
gitOk(cwd, ["worktree", "remove", "--force", path]);
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
const stranded = (gitOk(cwd, ["for-each-ref", "--format=%(refname:short)", "refs/heads/crew/release-*"]) ?? "").split("\n").filter(Boolean);
|
|
4033
|
+
for (const b of stranded) gitOk(cwd, ["branch", "-q", "-D", b]);
|
|
4034
|
+
return stranded;
|
|
4035
|
+
}
|
|
4036
|
+
function pushBranch(cwd, remote, branch, dst = branch) {
|
|
4037
|
+
git(cwd, ["push", remote, `${branch}:${dst}`]);
|
|
4009
4038
|
}
|
|
4010
4039
|
function worktrees(cwd) {
|
|
4011
4040
|
const out = gitOk(cwd, ["worktree", "list", "--porcelain"]) ?? "";
|
|
@@ -5442,8 +5471,9 @@ Wrote ${o.configPath}.
|
|
|
5442
5471
|
}
|
|
5443
5472
|
|
|
5444
5473
|
// src/release-run.ts
|
|
5445
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync9 } from "fs";
|
|
5446
|
-
import { join as join9 } from "path";
|
|
5474
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync9, copyFileSync, mkdirSync as mkdirSync7, mkdtempSync, rmSync as rmSync2 } from "fs";
|
|
5475
|
+
import { dirname as dirname7, join as join9 } from "path";
|
|
5476
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
5447
5477
|
|
|
5448
5478
|
// src/release.ts
|
|
5449
5479
|
function describeUnplaceable(unplaceable, verifiedStatus) {
|
|
@@ -6018,6 +6048,31 @@ async function confirmLastRelease(o, decision) {
|
|
|
6018
6048
|
if (!confirmed) o.emit.warn(`${decision.lastTag} is still not confirmed live \u2014 tickets stay verified`);
|
|
6019
6049
|
return { confirmed, version };
|
|
6020
6050
|
}
|
|
6051
|
+
function openReleaseCheckout(o) {
|
|
6052
|
+
const { remote, base } = o.repo.branch;
|
|
6053
|
+
const branch = `crew/release-${Date.now()}`;
|
|
6054
|
+
const root = mkdtempSync(join9(tmpdir2(), "crew-release-"));
|
|
6055
|
+
const dir = join9(root, "checkout");
|
|
6056
|
+
const close = () => {
|
|
6057
|
+
gitOk(o.cwd, ["worktree", "remove", "--force", dir]);
|
|
6058
|
+
rmSync2(root, { recursive: true, force: true });
|
|
6059
|
+
gitOk(o.cwd, ["worktree", "prune"]);
|
|
6060
|
+
gitOk(o.cwd, ["branch", "-D", branch]);
|
|
6061
|
+
};
|
|
6062
|
+
try {
|
|
6063
|
+
git(o.cwd, ["worktree", "add", "-q", "-b", branch, dir, `${remote}/${base}`]);
|
|
6064
|
+
} catch (e) {
|
|
6065
|
+
close();
|
|
6066
|
+
throw e;
|
|
6067
|
+
}
|
|
6068
|
+
for (const f of o.repo.worktrees.copy) {
|
|
6069
|
+
const src = join9(o.cwd, f);
|
|
6070
|
+
if (!existsSync9(src)) continue;
|
|
6071
|
+
mkdirSync7(dirname7(join9(dir, f)), { recursive: true });
|
|
6072
|
+
copyFileSync(src, join9(dir, f));
|
|
6073
|
+
}
|
|
6074
|
+
return { dir, branch, close };
|
|
6075
|
+
}
|
|
6021
6076
|
async function runRelease(o) {
|
|
6022
6077
|
const scoped = (msg) => o.scope ? `${o.scope}: ${msg}` : msg;
|
|
6023
6078
|
const tagPattern = o.repo.release.tagPattern ?? "v*";
|
|
@@ -6064,6 +6119,33 @@ async function runRelease(o) {
|
|
|
6064
6119
|
const externalClosures = await confirmExternalReleased(o, landed);
|
|
6065
6120
|
return { merged: [], deployed: false, stopped: "external", decision, externalClosures };
|
|
6066
6121
|
}
|
|
6122
|
+
const { remote, base } = o.repo.branch;
|
|
6123
|
+
if (o.dryRun || o.mergeOnly || !remoteBranchExists(o.cwd, remote, base)) {
|
|
6124
|
+
return mergeAndRelease(o, decision, fresh);
|
|
6125
|
+
}
|
|
6126
|
+
let checkout;
|
|
6127
|
+
const stranded = recoverStrandedReleaseCheckouts(o.cwd);
|
|
6128
|
+
if (stranded.length > 0) o.emit.warn(scoped(`dropped release checkout(s) stranded by a crash: ${stranded.join(", ")}`));
|
|
6129
|
+
try {
|
|
6130
|
+
checkout = openReleaseCheckout(o);
|
|
6131
|
+
} catch (e) {
|
|
6132
|
+
o.emit.error(scoped(`could not cut a release checkout from ${remote}/${base} \u2014 ${e.message}`));
|
|
6133
|
+
return { merged: [], deployed: false, stopped: "release checkout failed", decision };
|
|
6134
|
+
}
|
|
6135
|
+
try {
|
|
6136
|
+
return await mergeAndRelease({ ...o, cwd: checkout.dir }, decision, fresh, checkout.branch);
|
|
6137
|
+
} finally {
|
|
6138
|
+
checkout.close();
|
|
6139
|
+
const refreshed = refreshBaseBranch(o.cwd, remote, base);
|
|
6140
|
+
if (refreshed.action === "fast-forwarded" && o.repo.hooks.build) {
|
|
6141
|
+
const r = await hook(o, "build");
|
|
6142
|
+
if (r && r.code !== 0) {
|
|
6143
|
+
o.emit.warn(scoped(`rebuilding the primary checkout after the release failed (exit ${r.code}) \u2014 its dist/ is stale until \`${o.repo.hooks.build}\` is run there`));
|
|
6144
|
+
}
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
6147
|
+
}
|
|
6148
|
+
async function mergeAndRelease(o, decision, fresh, releaseBranch) {
|
|
6067
6149
|
o.emit.enter("merge");
|
|
6068
6150
|
const merged = [];
|
|
6069
6151
|
const conflicts = [];
|
|
@@ -6225,6 +6307,16 @@ async function runRelease(o) {
|
|
|
6225
6307
|
}
|
|
6226
6308
|
}
|
|
6227
6309
|
}
|
|
6310
|
+
if (releaseBranch && !o.dryRun) {
|
|
6311
|
+
const { remote, base } = o.repo.branch;
|
|
6312
|
+
if (fetchRemote(o.cwd, remote) && remoteBranchExists(o.cwd, remote, base)) {
|
|
6313
|
+
const moved = resolve2(o.cwd, `${remote}/${base}`);
|
|
6314
|
+
if (moved && !isAncestor(o.cwd, moved, "HEAD")) {
|
|
6315
|
+
o.emit.warn(`${remote}/${base} moved during the release \u2014 discarding it; the tickets stay verified and the next cycle retries`);
|
|
6316
|
+
return { merged, conflicts, unbuildable, version, deployed: false, decision, stopped: "base branch moved during release" };
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
}
|
|
6228
6320
|
let deployed = false;
|
|
6229
6321
|
let integrated = false;
|
|
6230
6322
|
if (o.repo.release.mode === "integrate") {
|
|
@@ -6254,7 +6346,7 @@ async function runRelease(o) {
|
|
|
6254
6346
|
o.emit.emit(`would push ${o.repo.branch.base} to ${o.repo.branch.remote}`);
|
|
6255
6347
|
} else {
|
|
6256
6348
|
try {
|
|
6257
|
-
pushBranch(o.cwd, o.repo.branch.remote, o.repo.branch.base);
|
|
6349
|
+
pushBranch(o.cwd, o.repo.branch.remote, releaseBranch ?? o.repo.branch.base, o.repo.branch.base);
|
|
6258
6350
|
o.emit.emit(`pushed ${o.repo.branch.base} to ${o.repo.branch.remote}`);
|
|
6259
6351
|
} catch (e) {
|
|
6260
6352
|
o.emit.error(
|
|
@@ -8009,7 +8101,7 @@ function applyRemoteBranchCleanup(cwd, remote, branches2, dryRun, log) {
|
|
|
8009
8101
|
}
|
|
8010
8102
|
|
|
8011
8103
|
// src/stream-sweep.ts
|
|
8012
|
-
import { existsSync as existsSync15, readdirSync as readdirSync3, rmSync as
|
|
8104
|
+
import { existsSync as existsSync15, readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync6 } from "fs";
|
|
8013
8105
|
import { join as join14 } from "path";
|
|
8014
8106
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
8015
8107
|
function planStreamSweep(stateDir, retentionDays, now = Date.now()) {
|
|
@@ -8032,7 +8124,7 @@ function applyStreamSweep(paths, dryRun, log) {
|
|
|
8032
8124
|
continue;
|
|
8033
8125
|
}
|
|
8034
8126
|
try {
|
|
8035
|
-
|
|
8127
|
+
rmSync3(path, { force: true });
|
|
8036
8128
|
removed++;
|
|
8037
8129
|
log.emit(`removed stream artifact ${path}`, { step: "worktree" });
|
|
8038
8130
|
} catch (e) {
|
|
@@ -8043,14 +8135,14 @@ function applyStreamSweep(paths, dryRun, log) {
|
|
|
8043
8135
|
}
|
|
8044
8136
|
|
|
8045
8137
|
// src/cli.ts
|
|
8046
|
-
import { readFileSync as readFileSync14, existsSync as existsSync19, mkdirSync as
|
|
8138
|
+
import { readFileSync as readFileSync14, existsSync as existsSync19, mkdirSync as mkdirSync11, writeFileSync as writeFileSync9, unlinkSync as unlinkSync5, copyFileSync as copyFileSync2, renameSync } from "fs";
|
|
8047
8139
|
import { createInterface } from "readline/promises";
|
|
8048
8140
|
import { dirname as dirOf, resolve as resolvePath } from "path";
|
|
8049
8141
|
|
|
8050
8142
|
// src/ssh-keys.ts
|
|
8051
8143
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
8052
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
8053
|
-
import { dirname as
|
|
8144
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync11, chmodSync } from "fs";
|
|
8145
|
+
import { dirname as dirname9, join as join15 } from "path";
|
|
8054
8146
|
var SshKeyError = class extends Error {
|
|
8055
8147
|
};
|
|
8056
8148
|
function shipSshKeyPathFor(stateDir) {
|
|
@@ -8060,7 +8152,7 @@ function ensureShipSshKeypair(stateDir) {
|
|
|
8060
8152
|
const privateKeyPath = shipSshKeyPathFor(stateDir);
|
|
8061
8153
|
const publicKeyPath = `${privateKeyPath}.pub`;
|
|
8062
8154
|
if (!existsSync16(privateKeyPath)) {
|
|
8063
|
-
|
|
8155
|
+
mkdirSync8(dirname9(privateKeyPath), { recursive: true });
|
|
8064
8156
|
try {
|
|
8065
8157
|
execFileSync3("ssh-keygen", [
|
|
8066
8158
|
"-t",
|
|
@@ -8297,7 +8389,7 @@ function syncAllPassengerCheckouts(cfg) {
|
|
|
8297
8389
|
|
|
8298
8390
|
// src/tunnel.ts
|
|
8299
8391
|
import { spawn as spawn3 } from "child_process";
|
|
8300
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
8392
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync4 } from "fs";
|
|
8301
8393
|
import { randomInt } from "crypto";
|
|
8302
8394
|
import { join as join16 } from "path";
|
|
8303
8395
|
var DEFAULT_SPAWN_OPTIONS = { stdio: "ignore", detached: true };
|
|
@@ -8379,7 +8471,7 @@ function readPersistedTunnel(stateDir, workspaceId) {
|
|
|
8379
8471
|
}
|
|
8380
8472
|
function writePersistedTunnel(stateDir, state) {
|
|
8381
8473
|
const path = tunnelStatePath(stateDir, state.workspaceId);
|
|
8382
|
-
|
|
8474
|
+
mkdirSync9(join16(stateDir, "passengers"), { recursive: true });
|
|
8383
8475
|
writeFileSync7(path, `${JSON.stringify(state, null, 2)}
|
|
8384
8476
|
`);
|
|
8385
8477
|
}
|
|
@@ -8599,7 +8691,7 @@ async function unregisterEndpoint(workspaceId, info, d) {
|
|
|
8599
8691
|
import { createServer as createHttpServer } from "http";
|
|
8600
8692
|
import { spawn as spawn4 } from "child_process";
|
|
8601
8693
|
import { randomBytes } from "crypto";
|
|
8602
|
-
import { existsSync as existsSync18, mkdirSync as
|
|
8694
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync8, unlinkSync as unlinkSync4, readdirSync as readdirSync5 } from "fs";
|
|
8603
8695
|
import { join as join17 } from "path";
|
|
8604
8696
|
|
|
8605
8697
|
// src/secret-compare.ts
|
|
@@ -8702,7 +8794,7 @@ function readPersistedSyncDaemon(stateDir, workspaceId) {
|
|
|
8702
8794
|
}
|
|
8703
8795
|
function writePersistedSyncDaemon(stateDir, state) {
|
|
8704
8796
|
const path = syncDaemonStatePath(stateDir, state.workspaceId);
|
|
8705
|
-
|
|
8797
|
+
mkdirSync10(join17(stateDir, "passengers"), { recursive: true });
|
|
8706
8798
|
writeFileSync8(path, `${JSON.stringify(state, null, 2)}
|
|
8707
8799
|
`);
|
|
8708
8800
|
}
|
|
@@ -9066,7 +9158,7 @@ async function buildEnvironment(route, ship, ticket) {
|
|
|
9066
9158
|
}
|
|
9067
9159
|
|
|
9068
9160
|
// src/cli.ts
|
|
9069
|
-
var CREW_HOME = isCompiledBinary(import.meta.url) ?
|
|
9161
|
+
var CREW_HOME = isCompiledBinary(import.meta.url) ? dirname10(process.execPath) : resolve4(dirname10(fileURLToPath(import.meta.url)), "..");
|
|
9070
9162
|
var RELEASE_LOCK_TTL_MS = 20 * 60 * 1e3;
|
|
9071
9163
|
var CYCLE_SECONDS = 120;
|
|
9072
9164
|
var STALE_CYCLES = 3;
|
|
@@ -9516,7 +9608,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
9516
9608
|
`),
|
|
9517
9609
|
warn: (m) => process.stderr.write(`crew install: ${m}
|
|
9518
9610
|
`)
|
|
9519
|
-
});
|
|
9611
|
+
}, void 0, loadedCrewLabels());
|
|
9520
9612
|
if (!ok) return false;
|
|
9521
9613
|
}
|
|
9522
9614
|
const installPathProblem = cfg.routes.some((r) => r.enabled && r.hostPassengers) ? dockerPathProblem(cfg.ship) : void 0;
|
|
@@ -10518,7 +10610,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
10518
10610
|
const raw = existsSync19(resolvedPath) ? JSON.parse(readFileSync14(resolvedPath, "utf8")) : {};
|
|
10519
10611
|
raw.agentPersonas = personaResult.agentPersonas;
|
|
10520
10612
|
raw.agentSkills = skillResult.agentSkills;
|
|
10521
|
-
|
|
10613
|
+
mkdirSync11(dirOf(resolvedPath), { recursive: true });
|
|
10522
10614
|
writeFileSync9(resolvedPath, `${JSON.stringify(raw, null, 2)}
|
|
10523
10615
|
`);
|
|
10524
10616
|
}
|
|
@@ -10566,7 +10658,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
10566
10658
|
const resolvedPath = resolvedPathFor(cfg.ship.stateDir, target.route);
|
|
10567
10659
|
const raw = existsSync19(resolvedPath) ? JSON.parse(readFileSync14(resolvedPath, "utf8")) : {};
|
|
10568
10660
|
raw.agentSkills = result.agentSkills;
|
|
10569
|
-
|
|
10661
|
+
mkdirSync11(dirOf(resolvedPath), { recursive: true });
|
|
10570
10662
|
writeFileSync9(resolvedPath, `${JSON.stringify(raw, null, 2)}
|
|
10571
10663
|
`);
|
|
10572
10664
|
}
|
|
@@ -10610,7 +10702,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
10610
10702
|
}
|
|
10611
10703
|
const originOf = (dir) => gitOk(dir, ["remote", "get-url", "origin"]) ?? void 0;
|
|
10612
10704
|
const text = configText;
|
|
10613
|
-
const base =
|
|
10705
|
+
const base = dirname10(cfg.configFile);
|
|
10614
10706
|
try {
|
|
10615
10707
|
if (sub === "list") {
|
|
10616
10708
|
const repos = configuredRepos(text, routeName, base);
|
|
@@ -10971,8 +11063,8 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
10971
11063
|
process.stderr.write(`(dry run) would write resolved ids to ${resolvedPath}
|
|
10972
11064
|
`);
|
|
10973
11065
|
} else {
|
|
10974
|
-
|
|
10975
|
-
if (hadPreviousFile)
|
|
11066
|
+
mkdirSync11(dirname10(resolvedPath), { recursive: true });
|
|
11067
|
+
if (hadPreviousFile) copyFileSync2(resolvedPath, `${resolvedPath}.bak`);
|
|
10976
11068
|
const tmpPath = `${resolvedPath}.tmp${process.pid}`;
|
|
10977
11069
|
writeFileSync9(tmpPath, `${JSON.stringify(resolved, null, 2)}
|
|
10978
11070
|
`);
|
|
@@ -10988,7 +11080,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
10988
11080
|
process.stderr.write(`(dry run) would write the minted API key to ${apiKeyFile}
|
|
10989
11081
|
`);
|
|
10990
11082
|
} else {
|
|
10991
|
-
|
|
11083
|
+
mkdirSync11(dirname10(apiKeyFile), { recursive: true });
|
|
10992
11084
|
writeFileSync9(apiKeyFile, `${apiKeyVar}=${apiKey}
|
|
10993
11085
|
`, { mode: 384 });
|
|
10994
11086
|
process.stderr.write(`API key written to ${apiKeyFile}
|
|
@@ -11444,7 +11536,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
11444
11536
|
`),
|
|
11445
11537
|
warn: (m) => process.stderr.write(`crew uninstall: ${m}
|
|
11446
11538
|
`)
|
|
11447
|
-
});
|
|
11539
|
+
}, void 0, loadedCrewLabels());
|
|
11448
11540
|
}
|
|
11449
11541
|
break;
|
|
11450
11542
|
}
|
package/package.json
CHANGED
|
@@ -353,9 +353,12 @@ if `report_type` is either of those.
|
|
|
353
353
|
reconcile it yourself. Post a comment on the ticket naming the repo and the
|
|
354
354
|
counts `crew sync` printed, leave the ticket as you found it, and end the
|
|
355
355
|
run — the operator reconciles the checkout. Otherwise, from
|
|
356
|
-
the primary checkout, `git worktree add
|
|
357
|
-
ticket, on a new branch cut from the base
|
|
358
|
-
|
|
356
|
+
the primary checkout, `git worktree add <dir> -b <branch> <remote>/<base>`
|
|
357
|
+
a sibling worktree for this ticket, on a new branch cut from the base
|
|
358
|
+
branch's REMOTE-TRACKING ref (`origin/main`, say), never from the primary
|
|
359
|
+
checkout's own local base — that copy is a cache of the remote, and a
|
|
360
|
+
local commit on it would be carried into every ticket cut from it
|
|
361
|
+
(CREW-1383). The digest's `worktree` and `branch` columns give this ticket's own directory
|
|
359
362
|
and branch name — use them verbatim. The Environment section names the
|
|
360
363
|
base branch and describes the general pattern, but its own worked example
|
|
361
364
|
is illustrative only (rendered before any ticket is chosen, so it cannot
|
|
@@ -334,8 +334,12 @@ if `report_type` is either of those.
|
|
|
334
334
|
reconcile it yourself. Post a comment on the ticket naming the repo and the
|
|
335
335
|
counts `crew sync` printed, leave the ticket as you found it, and end the
|
|
336
336
|
run — the operator reconciles the checkout. Otherwise, from
|
|
337
|
-
the primary checkout, `git worktree add
|
|
338
|
-
ticket, on a new branch cut from the base
|
|
337
|
+
the primary checkout, `git worktree add <dir> -b <branch> <remote>/<base>`
|
|
338
|
+
a sibling worktree for this ticket, on a new branch cut from the base
|
|
339
|
+
branch's REMOTE-TRACKING ref (`origin/main`, say), never from the primary
|
|
340
|
+
checkout's own local base — that copy is a cache of the remote, and a
|
|
341
|
+
local commit on it would be carried into every ticket cut from it
|
|
342
|
+
(CREW-1383). The
|
|
339
343
|
digest's `worktree` and `branch` columns give this ticket's own directory
|
|
340
344
|
and branch name — use them verbatim. The Environment section names the
|
|
341
345
|
base branch and describes the general pattern, but its own worked example
|