@mutmutco/cli 4.5.124 → 4.5.126
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/main.cjs +323 -209
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -76,19 +76,19 @@ function hardExit(code) {
|
|
|
76
76
|
process.exit(code);
|
|
77
77
|
}
|
|
78
78
|
function flushStream(stream) {
|
|
79
|
-
return new Promise((
|
|
79
|
+
return new Promise((resolve8) => {
|
|
80
80
|
try {
|
|
81
|
-
stream.write("", () =>
|
|
81
|
+
stream.write("", () => resolve8());
|
|
82
82
|
} catch {
|
|
83
|
-
|
|
83
|
+
resolve8();
|
|
84
84
|
}
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
async function flushStdio(timeoutMs = STDIO_FLUSH_TIMEOUT_MS) {
|
|
88
88
|
await Promise.race([
|
|
89
89
|
Promise.all([flushStream(process.stdout), flushStream(process.stderr)]),
|
|
90
|
-
new Promise((
|
|
91
|
-
setTimeout(
|
|
90
|
+
new Promise((resolve8) => {
|
|
91
|
+
setTimeout(resolve8, timeoutMs).unref?.();
|
|
92
92
|
})
|
|
93
93
|
]);
|
|
94
94
|
}
|
|
@@ -96,7 +96,7 @@ async function cleanExit(code) {
|
|
|
96
96
|
process.exitCode = code;
|
|
97
97
|
await closeHttpPool();
|
|
98
98
|
await flushStdio();
|
|
99
|
-
await new Promise((
|
|
99
|
+
await new Promise((resolve8) => setImmediate(resolve8));
|
|
100
100
|
return void 0;
|
|
101
101
|
}
|
|
102
102
|
async function finishCliRun(watchdogMs = CLI_EXIT_WATCHDOG_MS) {
|
|
@@ -644,7 +644,7 @@ function rateLimitedReceipt(opts) {
|
|
|
644
644
|
};
|
|
645
645
|
}
|
|
646
646
|
async function runWithRateLimitBackoff(operation, opts) {
|
|
647
|
-
const sleep2 = opts.sleep ?? ((ms) => new Promise((
|
|
647
|
+
const sleep2 = opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
648
648
|
const now = opts.now ?? Date.now;
|
|
649
649
|
const log = opts.log ?? ((message2) => console.warn(message2));
|
|
650
650
|
const capMs = opts.capMs ?? RATE_LIMIT_WAIT_CAP_MS;
|
|
@@ -734,7 +734,7 @@ async function fetchWithRetry(fetchImpl, url, init, opts = {}) {
|
|
|
734
734
|
const attempts = opts.attempts ?? 3;
|
|
735
735
|
const baseDelayMs = opts.baseDelayMs ?? 250;
|
|
736
736
|
const retryOn = opts.retryOn ?? ((res) => res.status >= 500);
|
|
737
|
-
const sleep2 = opts.sleep ?? ((ms) => new Promise((
|
|
737
|
+
const sleep2 = opts.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
738
738
|
let lastErr;
|
|
739
739
|
for (let i = 0; i < attempts; i++) {
|
|
740
740
|
const isLast = i === attempts - 1;
|
|
@@ -1057,8 +1057,8 @@ async function readStdin(opts = {}) {
|
|
|
1057
1057
|
})().catch(() => {
|
|
1058
1058
|
});
|
|
1059
1059
|
let timer;
|
|
1060
|
-
const timeout = new Promise((
|
|
1061
|
-
timer = setTimeout(
|
|
1060
|
+
const timeout = new Promise((resolve8) => {
|
|
1061
|
+
timer = setTimeout(resolve8, timeoutMs);
|
|
1062
1062
|
});
|
|
1063
1063
|
try {
|
|
1064
1064
|
await Promise.race([drain, timeout]);
|
|
@@ -1125,12 +1125,12 @@ function killProcessTree(pid) {
|
|
|
1125
1125
|
function execFileHard(file, args, options) {
|
|
1126
1126
|
const { timeout, step, ...rest } = options;
|
|
1127
1127
|
const started = Date.now();
|
|
1128
|
-
return new Promise((
|
|
1128
|
+
return new Promise((resolve8, reject) => {
|
|
1129
1129
|
const child2 = (0, import_node_child_process2.execFile)(file, args, { encoding: "utf8", windowsHide: true, ...rest, timeout: 0 }, (error, stdout, stderr) => {
|
|
1130
1130
|
clearTimeout(timer);
|
|
1131
1131
|
if (expired) return;
|
|
1132
1132
|
if (error) reject(error);
|
|
1133
|
-
else
|
|
1133
|
+
else resolve8({ stdout: String(stdout), stderr: String(stderr) });
|
|
1134
1134
|
});
|
|
1135
1135
|
let expired = false;
|
|
1136
1136
|
const timer = setTimeout(() => {
|
|
@@ -5656,7 +5656,7 @@ function resolveVerbAliasShim(argv) {
|
|
|
5656
5656
|
|
|
5657
5657
|
// src/command-composition.ts
|
|
5658
5658
|
var import_node_os25 = require("node:os");
|
|
5659
|
-
var
|
|
5659
|
+
var import_node_path56 = require("node:path");
|
|
5660
5660
|
|
|
5661
5661
|
// src/board-read.ts
|
|
5662
5662
|
var import_node_fs14 = require("node:fs");
|
|
@@ -6735,7 +6735,7 @@ async function readRestPrSnapshotWithRetry(prNumber, repo, gh2 = defaultGhApi, o
|
|
|
6735
6735
|
const retries = options?.retries ?? PR_SNAPSHOT_READ_RETRIES;
|
|
6736
6736
|
const untilMs = options?.retryTransientUntilMs;
|
|
6737
6737
|
const delayMs = options?.delayMs ?? (untilMs !== void 0 ? PR_CHECKS_POLL_MS : PR_SNAPSHOT_READ_DELAY_MS);
|
|
6738
|
-
const sleep2 = options?.sleep ?? ((ms) => new Promise((
|
|
6738
|
+
const sleep2 = options?.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
6739
6739
|
const now = options?.now ?? (() => Date.now());
|
|
6740
6740
|
let lastError = "no attempt completed";
|
|
6741
6741
|
let attempt = 0;
|
|
@@ -8766,8 +8766,9 @@ async function retireProject(slug, deps) {
|
|
|
8766
8766
|
async function setDeployCoords(slug, payload, deps) {
|
|
8767
8767
|
return postJson(`/projects/${encodeURIComponent(slug)}/deploy`, payload, deps);
|
|
8768
8768
|
}
|
|
8769
|
-
async function retireDeployCoords(slug, stage, deps) {
|
|
8770
|
-
|
|
8769
|
+
async function retireDeployCoords(slug, stage, deps, decommissioned = false) {
|
|
8770
|
+
const q = decommissioned ? "?decommissioned=1" : "";
|
|
8771
|
+
return postJson(`/projects/${encodeURIComponent(slug)}/deploy/${encodeURIComponent(stage)}${q}`, {}, deps, "DELETE", { noRetry: true });
|
|
8771
8772
|
}
|
|
8772
8773
|
async function postSchedulesLift(repo, schedules, deps) {
|
|
8773
8774
|
const res = await postJson("/schedules/lift", { repo, schedules }, deps);
|
|
@@ -10588,7 +10589,7 @@ async function createPrViaRestFallback(args, swappedArgs, deps, knownPools) {
|
|
|
10588
10589
|
}
|
|
10589
10590
|
async function ghCreate(args, deps = {}) {
|
|
10590
10591
|
const exec3 = deps.exec ?? execFileP;
|
|
10591
|
-
const sleep2 = deps.sleep ?? ((ms) => new Promise((
|
|
10592
|
+
const sleep2 = deps.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
10592
10593
|
const now = deps.now ?? Date.now;
|
|
10593
10594
|
const read = deps.readFile ?? import_promises.readFile;
|
|
10594
10595
|
const restCreatePr = deps.restCreatePr ?? ((input) => defaultRestCreatePr(exec3, input));
|
|
@@ -11416,8 +11417,8 @@ var PRE_SPAWN_DRAIN_TIMEOUT_MS = 2e3;
|
|
|
11416
11417
|
async function drainHttpPoolBeforeSpawn() {
|
|
11417
11418
|
const drained = await Promise.race([
|
|
11418
11419
|
closeHttpPool().then(() => true),
|
|
11419
|
-
new Promise((
|
|
11420
|
-
setTimeout(() =>
|
|
11420
|
+
new Promise((resolve8) => {
|
|
11421
|
+
setTimeout(() => resolve8(false), PRE_SPAWN_DRAIN_TIMEOUT_MS).unref?.();
|
|
11421
11422
|
})
|
|
11422
11423
|
]);
|
|
11423
11424
|
if (!drained) destroyHttpPool();
|
|
@@ -15004,7 +15005,7 @@ async function setBoardItemPriority(client, cfg, itemId, priority) {
|
|
|
15004
15005
|
await updateItemSingleSelect(client, cfg.projectId, itemId, cfg.priorityFieldId, optionId);
|
|
15005
15006
|
return cliPriorityToFieldName(priority);
|
|
15006
15007
|
}
|
|
15007
|
-
var defaultRetrySleep = (ms) => new Promise((
|
|
15008
|
+
var defaultRetrySleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
15008
15009
|
async function resolveProjectItemIdWithRetry(client, cfg, selector, opts = {}) {
|
|
15009
15010
|
const attempts = Math.max(1, opts.attempts ?? 5);
|
|
15010
15011
|
const delayMs = opts.delayMs ?? 300;
|
|
@@ -18243,10 +18244,10 @@ var rollout_plan_default = {
|
|
|
18243
18244
|
note: "The v4.0.0 stamp happens at cut time (D6e #4463); until then the candidate is the origin/development head artifacts (built cli/dist + npm pack), identity proven by dist content hash (D6a)."
|
|
18244
18245
|
},
|
|
18245
18246
|
baseline: {
|
|
18246
|
-
version: "4.5.
|
|
18247
|
-
tag: "v4.5.
|
|
18248
|
-
commit: "
|
|
18249
|
-
npm: "@mutmutco/cli@4.5.
|
|
18247
|
+
version: "4.5.126",
|
|
18248
|
+
tag: "v4.5.126",
|
|
18249
|
+
commit: "bf7736630f4c",
|
|
18250
|
+
npm: "@mutmutco/cli@4.5.126"
|
|
18250
18251
|
},
|
|
18251
18252
|
exitCriterion: "fleet-n-of-n",
|
|
18252
18253
|
hubOnlyShortcut: "forbidden",
|
|
@@ -18263,14 +18264,14 @@ var rollout_plan_default = {
|
|
|
18263
18264
|
repo: "mutmutco/mmi-hub",
|
|
18264
18265
|
role: "canary",
|
|
18265
18266
|
schedule: "train",
|
|
18266
|
-
v3Target: "v4.5.
|
|
18267
|
+
v3Target: "v4.5.126"
|
|
18267
18268
|
}
|
|
18268
18269
|
],
|
|
18269
18270
|
rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
|
|
18270
18271
|
rollback: {
|
|
18271
18272
|
independent: true,
|
|
18272
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
18273
|
-
v3Target: "v4.5.
|
|
18273
|
+
mechanism: "npm dist-tag latest -> 4.5.126 and redeploy the Hub Lambda from tag v4.5.126 (bf7736630f4c); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
18274
|
+
v3Target: "v4.5.126 (@mutmutco/cli@4.5.126, tag commit bf7736630f4c \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
18274
18275
|
}
|
|
18275
18276
|
},
|
|
18276
18277
|
{
|
|
@@ -20353,7 +20354,7 @@ async function runMergeTreePreflight(deps, ours, theirs) {
|
|
|
20353
20354
|
async function predictMergeConflicts(deps, ours, theirs) {
|
|
20354
20355
|
return runMergeTreePreflight(deps, ours, theirs);
|
|
20355
20356
|
}
|
|
20356
|
-
async function mergeWithToleratedResolution(deps, sourceRef, label,
|
|
20357
|
+
async function mergeWithToleratedResolution(deps, sourceRef, label, resolve8, extraTolerated = []) {
|
|
20357
20358
|
try {
|
|
20358
20359
|
await deps.run("git", ["merge", sourceRef, "--no-edit"]);
|
|
20359
20360
|
return;
|
|
@@ -20367,7 +20368,7 @@ async function mergeWithToleratedResolution(deps, sourceRef, label, resolve7, ex
|
|
|
20367
20368
|
unmerged.length === 0 ? `${label} merge failed without conflicted paths \u2014 merge aborted; inspect the repo state and rerun` : `${label} merge conflicts on untolerated path(s): ${blocking.join(", ")} \u2014 merge aborted (the train is misaligned; reconcile the branches via an approved alignment PR, then rerun)`
|
|
20368
20369
|
);
|
|
20369
20370
|
}
|
|
20370
|
-
await deps.run("git", ["checkout", `--${
|
|
20371
|
+
await deps.run("git", ["checkout", `--${resolve8}`, "--", ...unmerged]);
|
|
20371
20372
|
await deps.run("git", ["add", "--", ...unmerged]);
|
|
20372
20373
|
await deps.run("git", ["commit", "--no-edit"]);
|
|
20373
20374
|
}
|
|
@@ -20547,7 +20548,7 @@ var CORRELATE_SKEW_SLACK_MS = 1e4;
|
|
|
20547
20548
|
var CORRELATE_PAGE_LIMIT = 50;
|
|
20548
20549
|
var RUN_CONFIRM_ATTEMPTS = 3;
|
|
20549
20550
|
var RUN_CONFIRM_DELAY_MS = 1e3;
|
|
20550
|
-
var defaultSleep = (ms) => new Promise((
|
|
20551
|
+
var defaultSleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
20551
20552
|
function resolveSleep(deps) {
|
|
20552
20553
|
return deps.sleep ?? defaultSleep;
|
|
20553
20554
|
}
|
|
@@ -23726,7 +23727,7 @@ function lockTokenPid(token) {
|
|
|
23726
23727
|
const m = /^(\d+)-/.exec(token);
|
|
23727
23728
|
return m ? Number(m[1]) : void 0;
|
|
23728
23729
|
}
|
|
23729
|
-
var sleep = (ms) => new Promise((
|
|
23730
|
+
var sleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
23730
23731
|
var IMMEDIATE_RETRY_BUDGET = 3;
|
|
23731
23732
|
var FileLockBusyError = class extends Error {
|
|
23732
23733
|
lockPath;
|
|
@@ -24602,7 +24603,7 @@ async function defaultWatchRun(deps, runId, repo) {
|
|
|
24602
24603
|
}
|
|
24603
24604
|
let confirmError;
|
|
24604
24605
|
for (let attempt = 0; attempt < RUN_CONFIRM_ATTEMPTS2; attempt++) {
|
|
24605
|
-
if (attempt > 0) await new Promise((
|
|
24606
|
+
if (attempt > 0) await new Promise((resolve8) => setTimeout(resolve8, RUN_CONFIRM_DELAY_MS2));
|
|
24606
24607
|
try {
|
|
24607
24608
|
const parsed = JSON.parse(await deps.run("gh", ["run", "view", String(runId), "--repo", repo, "--json", "status,conclusion"]));
|
|
24608
24609
|
if (parsed.status === "completed") return parsed.conclusion === "success" ? "success" : "failure";
|
|
@@ -25644,11 +25645,11 @@ var defaultDeps = {
|
|
|
25644
25645
|
// #5813: the caller supplies that command line. `process.argv` is NOT it — the house shim splices
|
|
25645
25646
|
// the house root out in place, so re-reading it here re-ran the removed flat alias (`release …`
|
|
25646
25647
|
// instead of `devops release …`) and the converged child refused with exit 2.
|
|
25647
|
-
reexec: (argv) => new Promise((
|
|
25648
|
+
reexec: (argv) => new Promise((resolve8) => {
|
|
25648
25649
|
const args = [...argv];
|
|
25649
25650
|
const child2 = isWin2 ? (0, import_node_child_process8.spawn)("cmd.exe", ["/c", "mmi-cli", ...args], { stdio: "inherit", windowsHide: true }) : (0, import_node_child_process8.spawn)("mmi-cli", args, { stdio: "inherit", windowsHide: true });
|
|
25650
|
-
child2.on("exit", (code) =>
|
|
25651
|
-
child2.on("error", () =>
|
|
25651
|
+
child2.on("exit", (code) => resolve8(code ?? 1));
|
|
25652
|
+
child2.on("error", () => resolve8(1));
|
|
25652
25653
|
}),
|
|
25653
25654
|
// stderr only — stdout may be carrying --json output.
|
|
25654
25655
|
warn: (line) => console.error(line)
|
|
@@ -25754,7 +25755,7 @@ var defaultDeps2 = {
|
|
|
25754
25755
|
}
|
|
25755
25756
|
},
|
|
25756
25757
|
registryWhoami: probeRegistryWhoami,
|
|
25757
|
-
sleep: (ms) => new Promise((
|
|
25758
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms)),
|
|
25758
25759
|
env: process.env
|
|
25759
25760
|
};
|
|
25760
25761
|
function message(e) {
|
|
@@ -37162,7 +37163,7 @@ function readSuiteCut(path2) {
|
|
|
37162
37163
|
} catch {
|
|
37163
37164
|
throw new Error(`suite cut record unreadable at ${path2}; repair it, never recut`);
|
|
37164
37165
|
}
|
|
37165
|
-
if (record.schema !== SCHEMA || record.lead !== SUITE_REPO || !SHA2.test(record.leadDevelopment) || !SHA2.test(record.leadPreviousRc) || !Array.isArray(record.members) || record.members.length === 0 || record.pinPr !== void 0 && (typeof record.pinPr !== "string" || !record.pinPr.startsWith("https://github.com/mutmutco/MM-Work/pull/")) || record.pinsUnchanged !== void 0 && (record.pinsUnchanged !== true || record.pinPr !== void 0) || record.pinMerged !== void 0 && (record.pinMerged !== true && record.pinMerged !== false || !record.pinPr && !record.pinsUnchanged) || record.leadRcTag !== void 0 && (!RC_TAG.test(record.leadRcTag) || !SHA2.test(record.leadRcSha ?? "") || !record.pinMerged) || record.leadReleased !== void 0 && (record.leadReleased !== true || !record.leadRcTag) || record.announcement !== void 0 && (!["pending", "sent", "skipped"].includes(record.announcement) || !record.leadReleased) || record.heldMembers !== void 0 && (!Array.isArray(record.heldMembers) || record.heldMembers.some((h) => !h.id || !h.repo || typeof h.reason !== "string" || !h.reason.trim() || h.since !== void 0 && typeof h.since !== "string" || record.members.some((m) => m.id === h.id))) || record.members.some((m) => !m.id || !m.repo || !m.backend || !m.host || !SHA2.test(m.development) || !SHA2.test(m.previousRc) || m.rcWasAbsent !== void 0 && m.rcWasAbsent !== true || m.tag !== void 0 && (!RC_TAG.test(m.tag) || !SHA2.test(m.sha ?? "")) || m.published !== void 0 && (m.published !== true || !m.tag) || m.released !== void 0 && (m.released !== true || !m.published) || m.mainPublished !== void 0 && (m.mainPublished !== true || !m.released || !!m.carried) || m.backendAfterRelease !== void 0 && (!m.released || typeof m.backendAfterRelease !== "string") || m.carried !== void 0 && (m.carried !== true || m.tag !== void 0 || m.published !== void 0 || !isPin(m.rcPin) || !isPin(m.mainPin)) || m.carried === void 0 && (m.rcPin !== void 0 || m.mainPin !== void 0) || m.ruleset !== void 0 && (!["rc", "main"].includes(m.ruleset.after) || typeof m.ruleset.ok !== "boolean" || !Array.isArray(m.ruleset.lines))))
|
|
37166
|
+
if (record.schema !== SCHEMA || record.lead !== SUITE_REPO || !SHA2.test(record.leadDevelopment) || !SHA2.test(record.leadPreviousRc) || !Array.isArray(record.members) || record.members.length === 0 || record.pinPr !== void 0 && (typeof record.pinPr !== "string" || !record.pinPr.startsWith("https://github.com/mutmutco/MM-Work/pull/")) || record.pinsUnchanged !== void 0 && (record.pinsUnchanged !== true || record.pinPr !== void 0) || record.pinMerged !== void 0 && (record.pinMerged !== true && record.pinMerged !== false || !record.pinPr && !record.pinsUnchanged) || record.leadRcTag !== void 0 && (!RC_TAG.test(record.leadRcTag) || !SHA2.test(record.leadRcSha ?? "") || !record.pinMerged) || record.leadReleased !== void 0 && (record.leadReleased !== true || !record.leadRcTag) || record.announcement !== void 0 && (!["pending", "sent", "skipped"].includes(record.announcement) || !record.leadReleased) || record.heldMembers !== void 0 && (!Array.isArray(record.heldMembers) || record.heldMembers.some((h) => !h.id || !h.repo || typeof h.reason !== "string" || !h.reason.trim() || h.since !== void 0 && typeof h.since !== "string" || record.members.some((m) => m.id === h.id))) || record.members.some((m) => !m.id || !m.repo || !m.backend || !m.host || !SHA2.test(m.development) || !SHA2.test(m.previousRc) || m.rcWasAbsent !== void 0 && m.rcWasAbsent !== true || m.tag !== void 0 && (!RC_TAG.test(m.tag) || !SHA2.test(m.sha ?? "")) || m.carriedPublished !== void 0 && (m.carriedPublished !== true || !m.carried) || m.published !== void 0 && (m.published !== true || !m.tag) || m.released !== void 0 && (m.released !== true || !m.published) || m.mainPublished !== void 0 && (m.mainPublished !== true || !m.released || !!m.carried) || m.backendAfterRelease !== void 0 && (!m.released || typeof m.backendAfterRelease !== "string") || m.carried !== void 0 && (m.carried !== true || m.tag !== void 0 || m.published !== void 0 || !isPin(m.rcPin) || !isPin(m.mainPin)) || m.carried === void 0 && (m.rcPin !== void 0 || m.mainPin !== void 0) || m.ruleset !== void 0 && (!["rc", "main"].includes(m.ruleset.after) || typeof m.ruleset.ok !== "boolean" || !Array.isArray(m.ruleset.lines))))
|
|
37166
37167
|
throw new Error(`suite cut record has unknown or invalid state at ${path2}; repair it, never recut`);
|
|
37167
37168
|
return record;
|
|
37168
37169
|
}
|
|
@@ -37274,7 +37275,22 @@ async function pendingBackend(deps, m, dev) {
|
|
|
37274
37275
|
const files = (await deps.changedPaths(m.repo, live, dev)).filter((f) => !NOT_BACKEND.test(f));
|
|
37275
37276
|
return files.length ? `${files.length} backend file(s) changed since live ${version}, e.g. ${files[0]}` : "";
|
|
37276
37277
|
}
|
|
37278
|
+
function existingCutDescription(record) {
|
|
37279
|
+
const tags = [...record.members.flatMap((m) => m.tag ? [m.tag] : []), ...record.leadRcTag ? [record.leadRcTag] : []];
|
|
37280
|
+
return `from ${record.leadDevelopment.slice(0, 12)}; tags: ${tags.join(", ") || "none"}; pin PR: ${record.pinPr ?? "none"}`;
|
|
37281
|
+
}
|
|
37277
37282
|
async function suiteRcand(deps, opts) {
|
|
37283
|
+
const existing = readSuiteCut(deps.recordPath);
|
|
37284
|
+
try {
|
|
37285
|
+
return await suiteRcandRun(deps, opts);
|
|
37286
|
+
} catch (e) {
|
|
37287
|
+
if (existing && !opts.dryRun && opts.ownerGo && readSuiteCut(deps.recordPath))
|
|
37288
|
+
throw new Error(`${e.message}
|
|
37289
|
+
An existing cut record ${existingCutDescription(existing)} was resumed. mmi-cli devops suite abandon --owner-go retires it (subject to abandon safety checks).`);
|
|
37290
|
+
throw e;
|
|
37291
|
+
}
|
|
37292
|
+
}
|
|
37293
|
+
async function suiteRcandRun(deps, opts) {
|
|
37278
37294
|
if (!opts.ownerGo && !opts.dryRun) throw new Error("suite rcand requires --owner-go (rc uses live data); nothing was written");
|
|
37279
37295
|
const members = suiteMembers(await deps.registry());
|
|
37280
37296
|
const modules = trainModules(members);
|
|
@@ -37288,6 +37304,8 @@ async function suiteRcand(deps, opts) {
|
|
|
37288
37304
|
const lead = await deps.head(SUITE_REPO, "development");
|
|
37289
37305
|
plan.push(await kitCheck(deps, lead, active.map((m) => ({ id: m.id, url: m.bundles.dev })), "dev bundles"));
|
|
37290
37306
|
if (opts.dryRun) {
|
|
37307
|
+
const existing = readSuiteCut(deps.recordPath);
|
|
37308
|
+
if (existing) plan.push(`existing cut record: ${deps.recordPath} (${existingCutDescription(existing)})`);
|
|
37291
37309
|
plan.push(...await Promise.all(modules.map(async (m) => `${m.repo}: ${heldById.has(m.id) ? "HELD" : await dryRunStatus(deps, m)}`)));
|
|
37292
37310
|
return { plan };
|
|
37293
37311
|
}
|
|
@@ -37372,7 +37390,7 @@ async function suiteRcand(deps, opts) {
|
|
|
37372
37390
|
}
|
|
37373
37391
|
const refusals = [];
|
|
37374
37392
|
for (const member of record.members) {
|
|
37375
|
-
if (member.published) continue;
|
|
37393
|
+
if (member.published || member.carriedPublished) continue;
|
|
37376
37394
|
try {
|
|
37377
37395
|
await deps.preflight(member.repo);
|
|
37378
37396
|
} catch (e) {
|
|
@@ -37386,28 +37404,60 @@ async function suiteRcand(deps, opts) {
|
|
|
37386
37404
|
${refusals.join("\n")}
|
|
37387
37405
|
Each module must ship a live release that bind-mounts <deployPath>/data read-only and serves <data>/rc/module.js at /rc/module.js (docs/Guides/suite-trains.md).`);
|
|
37388
37406
|
}
|
|
37389
|
-
|
|
37390
|
-
|
|
37391
|
-
|
|
37392
|
-
|
|
37393
|
-
|
|
37394
|
-
|
|
37395
|
-
}
|
|
37396
|
-
|
|
37397
|
-
|
|
37398
|
-
|
|
37399
|
-
|
|
37400
|
-
|
|
37401
|
-
|
|
37402
|
-
|
|
37403
|
-
|
|
37404
|
-
|
|
37405
|
-
|
|
37406
|
-
await deps.
|
|
37407
|
-
|
|
37408
|
-
|
|
37407
|
+
const cutRecord = record;
|
|
37408
|
+
let writes = Promise.resolve();
|
|
37409
|
+
const persist = (mutate) => {
|
|
37410
|
+
const next = writes.then(() => {
|
|
37411
|
+
mutate();
|
|
37412
|
+
writeSuiteCut(deps.recordPath, cutRecord);
|
|
37413
|
+
});
|
|
37414
|
+
writes = next.catch(() => {
|
|
37415
|
+
});
|
|
37416
|
+
return next;
|
|
37417
|
+
};
|
|
37418
|
+
let running = 0;
|
|
37419
|
+
const waiting = [];
|
|
37420
|
+
const results = await Promise.allSettled(record.members.map(async (member) => {
|
|
37421
|
+
if (running >= 4) await new Promise((resolve8) => waiting.push(resolve8));
|
|
37422
|
+
else running++;
|
|
37423
|
+
try {
|
|
37424
|
+
if ((await deps.head(member.repo, "development"))?.toLowerCase() !== member.development.toLowerCase())
|
|
37425
|
+
throw new Error(`${member.repo}: development moved after the cut snapshot; refuse to add untested code`);
|
|
37426
|
+
if (member.carried) {
|
|
37427
|
+
if (!member.carriedPublished) {
|
|
37428
|
+
await deps.publish(member.repo, pinVersion(member.rcPin));
|
|
37429
|
+
await persist(() => {
|
|
37430
|
+
member.carriedPublished = true;
|
|
37431
|
+
});
|
|
37432
|
+
}
|
|
37433
|
+
return;
|
|
37434
|
+
}
|
|
37435
|
+
if (!member.tag) {
|
|
37436
|
+
const cut = await deps.rcand(member.repo, member.previousRc, member.rcWasAbsent);
|
|
37437
|
+
if (!RC_TAG.test(cut.tag) || !SHA2.test(cut.sha) || cut.sha.toLowerCase() === member.previousRc.toLowerCase()) throw new Error(`${member.repo}: rcand did not return a new immutable rc tag/SHA`);
|
|
37438
|
+
if (!await deps.contains(member.repo, member.development, cut.sha)) throw new Error(`${member.repo}: rc tag does not carry the snapshotted development SHA; refuse`);
|
|
37439
|
+
await persist(() => {
|
|
37440
|
+
member.tag = cut.tag;
|
|
37441
|
+
member.sha = cut.sha;
|
|
37442
|
+
});
|
|
37443
|
+
}
|
|
37444
|
+
const tag = member.tag;
|
|
37445
|
+
if ((await deps.tagSha(member.repo, tag))?.toLowerCase() !== member.sha.toLowerCase()) throw new Error(`${member.repo}: rc tag ${member.tag} moved or is unreadable; stop`);
|
|
37446
|
+
if (!member.published) {
|
|
37447
|
+
await deps.publish(member.repo, tag);
|
|
37448
|
+
await persist(() => {
|
|
37449
|
+
member.published = true;
|
|
37450
|
+
});
|
|
37451
|
+
}
|
|
37452
|
+
} finally {
|
|
37453
|
+
const next = waiting.shift();
|
|
37454
|
+
if (next) next();
|
|
37455
|
+
else running--;
|
|
37409
37456
|
}
|
|
37410
|
-
}
|
|
37457
|
+
}));
|
|
37458
|
+
const failures = results.flatMap((result, i) => result.status === "rejected" ? [`${record.members[i].repo}: ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`] : []);
|
|
37459
|
+
if (failures.length) throw new Error(`suite member cuts failed:
|
|
37460
|
+
${failures.join("\n")}`);
|
|
37411
37461
|
for (const member of record.members) {
|
|
37412
37462
|
const [live, devHead] = await Promise.all([
|
|
37413
37463
|
deps.backend({ repo: member.repo, id: member.id, bundles: {} }),
|
|
@@ -37852,8 +37902,10 @@ async function runRcDataSwitch(deps, opts) {
|
|
|
37852
37902
|
}
|
|
37853
37903
|
|
|
37854
37904
|
// src/suite-train-io.ts
|
|
37855
|
-
var
|
|
37905
|
+
var import_node_child_process18 = require("node:child_process");
|
|
37856
37906
|
var import_node_path44 = require("node:path");
|
|
37907
|
+
var import_node_fs45 = require("node:fs");
|
|
37908
|
+
var import_node_path45 = require("node:path");
|
|
37857
37909
|
init_cli_shared();
|
|
37858
37910
|
|
|
37859
37911
|
// src/command-register-train-operations.ts
|
|
@@ -38035,7 +38087,7 @@ function clean3(out) {
|
|
|
38035
38087
|
return out.trim();
|
|
38036
38088
|
}
|
|
38037
38089
|
function sleeper(deps) {
|
|
38038
|
-
return deps.sleep ?? ((ms) => new Promise((
|
|
38090
|
+
return deps.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
38039
38091
|
}
|
|
38040
38092
|
function normalizeHotfixVersion(input) {
|
|
38041
38093
|
const m = /^v?(\d+\.\d+\.\d+)$/.exec(input.trim());
|
|
@@ -39707,7 +39759,7 @@ async function updatePrHeadFromBase(input) {
|
|
|
39707
39759
|
} catch (e) {
|
|
39708
39760
|
throw new Error(`GitHub could not update ${input.head} from ${input.base} (${e.message.trim()}) \u2014 ${remedy}`);
|
|
39709
39761
|
}
|
|
39710
|
-
const sleep2 = input.sleep ?? ((ms) => new Promise((
|
|
39762
|
+
const sleep2 = input.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
39711
39763
|
for (let attempt = 0; attempt < PR_HEAD_UPDATE_API_READ_RETRIES; attempt++) {
|
|
39712
39764
|
const to = await readHead2();
|
|
39713
39765
|
if (to && to !== from) return { from, to, base: input.base, via: "update-branch-api" };
|
|
@@ -39725,7 +39777,7 @@ async function mergeAutoWithTransientRetry(prNumber, repo, deps) {
|
|
|
39725
39777
|
if (first.mergeStatus !== "failed") return first;
|
|
39726
39778
|
const ready = await deps.probeMergeReady(prNumber, repo).catch(() => ({ open: false, mergeable: false, checksPassing: false }));
|
|
39727
39779
|
if (!ready.open || !ready.mergeable || !ready.checksPassing) return first;
|
|
39728
|
-
const sleep2 = deps.sleep ?? ((ms) => new Promise((
|
|
39780
|
+
const sleep2 = deps.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
39729
39781
|
await sleep2(PR_LAND_MERGE_RETRY_DELAY_MS);
|
|
39730
39782
|
const retried = await deps.mergeAuto(prNumber, repo);
|
|
39731
39783
|
if (retried.mergeStatus !== "failed") return retried;
|
|
@@ -39736,7 +39788,7 @@ var AUTO_MERGE_CONFIRM_DELAY_MS = 15e3;
|
|
|
39736
39788
|
async function confirmAutoMergeEnqueued(deps, options) {
|
|
39737
39789
|
const retries = options?.retries ?? AUTO_MERGE_CONFIRM_RETRIES;
|
|
39738
39790
|
const delayMs = options?.delayMs ?? AUTO_MERGE_CONFIRM_DELAY_MS;
|
|
39739
|
-
const sleep2 = deps.sleep ?? ((ms) => new Promise((
|
|
39791
|
+
const sleep2 = deps.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
39740
39792
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
39741
39793
|
if (await deps.readMerged().catch(() => false)) return "merged";
|
|
39742
39794
|
const stuck = await deps.readAutoMergeRequest().then((s) => s.trim()).catch(() => "");
|
|
@@ -39753,7 +39805,7 @@ async function confirmAutoMergeEnqueued(deps, options) {
|
|
|
39753
39805
|
async function readGhPrStateWithRetry(fetchState, options) {
|
|
39754
39806
|
const retries = options?.retries ?? PR_LAND_STATE_READ_RETRIES;
|
|
39755
39807
|
const delayMs = options?.delayMs ?? PR_LAND_STATE_READ_DELAY_MS;
|
|
39756
|
-
const sleep2 = options?.sleep ?? ((ms) => new Promise((
|
|
39808
|
+
const sleep2 = options?.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
39757
39809
|
let lastError = "empty state";
|
|
39758
39810
|
for (let attempt = 0; attempt < retries; attempt++) {
|
|
39759
39811
|
try {
|
|
@@ -43381,7 +43433,7 @@ async function checkPrReview(number, repo, head, deps = {
|
|
|
43381
43433
|
}
|
|
43382
43434
|
}
|
|
43383
43435
|
function computePrPatchId(number, repo) {
|
|
43384
|
-
return new Promise((
|
|
43436
|
+
return new Promise((resolve8, reject) => {
|
|
43385
43437
|
const gh2 = (0, import_node_child_process14.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
43386
43438
|
const git3 = (0, import_node_child_process14.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
|
|
43387
43439
|
let out = "";
|
|
@@ -43419,7 +43471,7 @@ function computePrPatchId(number, repo) {
|
|
|
43419
43471
|
if (gitCode !== 0) return reject(new Error(`git patch-id --stable exited ${gitCode}: ${gitErr.trim()}`));
|
|
43420
43472
|
const id = out.trim().split(/\s+/)[0];
|
|
43421
43473
|
if (!/^[0-9a-f]{40}$/.test(id ?? "")) return reject(new Error(`patch-id: PR #${number} diff is empty or unreadable (gh: ${ghErr.trim() || "no stderr"})`));
|
|
43422
|
-
|
|
43474
|
+
resolve8(id);
|
|
43423
43475
|
};
|
|
43424
43476
|
gh2.on("close", (code) => {
|
|
43425
43477
|
ghCode = code;
|
|
@@ -43470,7 +43522,7 @@ init_cli_shared();
|
|
|
43470
43522
|
var GIT_TIMEOUT_MS2 = 15e3;
|
|
43471
43523
|
function catFileBatch(root, ref, paths) {
|
|
43472
43524
|
if (paths.length === 0) return Promise.resolve([]);
|
|
43473
|
-
return new Promise((
|
|
43525
|
+
return new Promise((resolve8) => {
|
|
43474
43526
|
const chunks = [];
|
|
43475
43527
|
let settled = false;
|
|
43476
43528
|
const child2 = (0, import_node_child_process15.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
|
|
@@ -43478,7 +43530,7 @@ function catFileBatch(root, ref, paths) {
|
|
|
43478
43530
|
if (settled) return;
|
|
43479
43531
|
settled = true;
|
|
43480
43532
|
clearTimeout(timer);
|
|
43481
|
-
|
|
43533
|
+
resolve8(parseCatFileBatch(Buffer.concat(chunks), paths.length));
|
|
43482
43534
|
};
|
|
43483
43535
|
const timer = setTimeout(() => {
|
|
43484
43536
|
child2.kill("SIGKILL");
|
|
@@ -43903,7 +43955,7 @@ function healthPollIntervalMs() {
|
|
|
43903
43955
|
return HEALTH_POLL_INTERVAL_MS;
|
|
43904
43956
|
}
|
|
43905
43957
|
function waitForProcessStability(child2, graceMs = earlyExitGraceMs()) {
|
|
43906
|
-
return new Promise((
|
|
43958
|
+
return new Promise((resolve8, reject) => {
|
|
43907
43959
|
let settled = false;
|
|
43908
43960
|
const finish = (fn) => {
|
|
43909
43961
|
if (settled) return;
|
|
@@ -43913,7 +43965,7 @@ function waitForProcessStability(child2, graceMs = earlyExitGraceMs()) {
|
|
|
43913
43965
|
child2.removeAllListeners("exit");
|
|
43914
43966
|
fn();
|
|
43915
43967
|
};
|
|
43916
|
-
const timer = setTimeout(() => finish(
|
|
43968
|
+
const timer = setTimeout(() => finish(resolve8), graceMs);
|
|
43917
43969
|
child2.on("error", (err) => finish(() => reject(new Error(`stage process failed to start: ${err.message}`))));
|
|
43918
43970
|
child2.on("exit", (code, signal) => {
|
|
43919
43971
|
const detail = code != null ? `code ${code}` : signal ? `signal ${signal}` : "unknown reason";
|
|
@@ -44106,10 +44158,10 @@ function pickStagePort(range, isFree) {
|
|
|
44106
44158
|
throw new Error(`no free stage port in range ${start}-${end} \u2014 every port is in use`);
|
|
44107
44159
|
}
|
|
44108
44160
|
function isPortFree(port) {
|
|
44109
|
-
return new Promise((
|
|
44161
|
+
return new Promise((resolve8) => {
|
|
44110
44162
|
const srv = (0, import_node_net.createServer)();
|
|
44111
|
-
srv.once("error", () =>
|
|
44112
|
-
srv.once("listening", () => srv.close(() =>
|
|
44163
|
+
srv.once("error", () => resolve8(false));
|
|
44164
|
+
srv.once("listening", () => srv.close(() => resolve8(true)));
|
|
44113
44165
|
srv.listen(port, "127.0.0.1");
|
|
44114
44166
|
});
|
|
44115
44167
|
}
|
|
@@ -44387,7 +44439,7 @@ async function killTree(pid) {
|
|
|
44387
44439
|
} catch {
|
|
44388
44440
|
}
|
|
44389
44441
|
}
|
|
44390
|
-
await new Promise((
|
|
44442
|
+
await new Promise((resolve8) => setTimeout(resolve8, 500));
|
|
44391
44443
|
try {
|
|
44392
44444
|
process.kill(-pid, "SIGKILL");
|
|
44393
44445
|
} catch {
|
|
@@ -44460,7 +44512,7 @@ async function waitForHealth(url, timeoutMs, anyStatus = false) {
|
|
|
44460
44512
|
} catch (e) {
|
|
44461
44513
|
last = e.message;
|
|
44462
44514
|
}
|
|
44463
|
-
await new Promise((
|
|
44515
|
+
await new Promise((resolve8) => setTimeout(resolve8, healthPollIntervalMs()));
|
|
44464
44516
|
}
|
|
44465
44517
|
throw new Error(`stage health check timed out for ${url}${last ? ` (${last})` : ""}`);
|
|
44466
44518
|
}
|
|
@@ -44820,7 +44872,7 @@ function unlinkNodeModulesJunction(wtPath) {
|
|
|
44820
44872
|
}
|
|
44821
44873
|
}
|
|
44822
44874
|
function defaultSleep2(ms) {
|
|
44823
|
-
return new Promise((
|
|
44875
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
44824
44876
|
}
|
|
44825
44877
|
async function removeResidueDirectory(wtPath, options = {}) {
|
|
44826
44878
|
const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs42.rmdirSync, exists = import_node_fs42.existsSync } = options;
|
|
@@ -46570,7 +46622,7 @@ ${list}`);
|
|
|
46570
46622
|
// #5400: after grace, name "GitHub delivered zero runs" instead of burning the full budget as pending.
|
|
46571
46623
|
pollHeadWorkflowRunCount: () => waitLoopHeadWorkflowRunCount("pr checks-wait", number, repo),
|
|
46572
46624
|
baseBranch,
|
|
46573
|
-
sleep: (ms) => new Promise((
|
|
46625
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms)),
|
|
46574
46626
|
log: (message2) => console.warn(message2),
|
|
46575
46627
|
timeoutMs: Math.max(1, budgetMs - (Date.now() - waitStarted)),
|
|
46576
46628
|
// Liveness on stderr, one line per poll. A silent bounded wait is indistinguishable from a hang, and
|
|
@@ -46725,7 +46777,7 @@ ${list}`);
|
|
|
46725
46777
|
// #5400: same zero-runs delivery probe as checks-wait — do not burn the land budget on silence.
|
|
46726
46778
|
pollHeadWorkflowRunCount: () => waitLoopHeadWorkflowRunCount("pr land", prNumber, repo),
|
|
46727
46779
|
baseBranch: "development",
|
|
46728
|
-
sleep: (ms) => new Promise((
|
|
46780
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms)),
|
|
46729
46781
|
log: (message2) => console.warn(message2),
|
|
46730
46782
|
// `pr land` inherits the same (raised) checks budget, so it needs the same liveness — otherwise the
|
|
46731
46783
|
// 30m wait is SILENT and reads exactly like the hang #2940 was filed about, only three times longer.
|
|
@@ -46776,7 +46828,7 @@ ${list}`);
|
|
|
46776
46828
|
} else {
|
|
46777
46829
|
lastFailure = void 0;
|
|
46778
46830
|
}
|
|
46779
|
-
await new Promise((
|
|
46831
|
+
await new Promise((resolve8) => setTimeout(resolve8, PR_LAND_POLL_MS));
|
|
46780
46832
|
}
|
|
46781
46833
|
if (lastFailure) {
|
|
46782
46834
|
throw new Error(
|
|
@@ -46934,7 +46986,7 @@ ${list}`);
|
|
|
46934
46986
|
checksDiagnosticCommand: `gh pr checks ${number} --repo ${repo}`,
|
|
46935
46987
|
pollHeadWorkflowRunCount: () => waitLoopHeadWorkflowRunCount("pr merge --wait", number, repo),
|
|
46936
46988
|
baseBranch,
|
|
46937
|
-
sleep: (ms) => new Promise((
|
|
46989
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms)),
|
|
46938
46990
|
log: (message2) => console.warn(message2),
|
|
46939
46991
|
timeoutMs: Math.max(1, budgetMs - (Date.now() - waitStarted)),
|
|
46940
46992
|
progress: ({ state, elapsedMs, remainingMs }) => console.warn(`pr merge: --wait checks \u2014 ${state}, ${Math.round(elapsedMs / 1e3)}s elapsed, ${Math.round(remainingMs / 6e4)}m left`)
|
|
@@ -47003,7 +47055,7 @@ ${list}`);
|
|
|
47003
47055
|
}
|
|
47004
47056
|
if (!o.auto && mergeRejectedBaseBranchModified(message2)) {
|
|
47005
47057
|
console.warn(`pr merge: the base branch was modified by a concurrent merge \u2014 waiting ${PR_MERGE_BASE_RACE_RETRY_DELAY_MS / 1e3}s and retrying PR #${number}'s merge once (#6052).`);
|
|
47006
|
-
await new Promise((
|
|
47058
|
+
await new Promise((resolve8) => setTimeout(resolve8, PR_MERGE_BASE_RACE_RETRY_DELAY_MS));
|
|
47007
47059
|
await execFileP("gh", buildPrMergeArgs({ number, repoArgs, method, auto: false, deleteBranch: false, bodyFile }), { timeout: GH_MUTATION_TIMEOUT_MS }).catch((e2) => {
|
|
47008
47060
|
const m2 = String(e2.message || "");
|
|
47009
47061
|
if (/already been merged/i.test(m2)) {
|
|
@@ -47264,7 +47316,7 @@ ${list}`);
|
|
|
47264
47316
|
console.warn(`ci checks-wait: zero-runs probe FAILED (${read.error}) \u2014 not treating as delivery failure this cycle`);
|
|
47265
47317
|
return null;
|
|
47266
47318
|
},
|
|
47267
|
-
sleep: (ms) => new Promise((
|
|
47319
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms)),
|
|
47268
47320
|
log: (message2) => console.warn(message2),
|
|
47269
47321
|
timeoutMs: timeoutMs ?? PR_CHECKS_TIMEOUT_MS,
|
|
47270
47322
|
progress: ({ state, elapsedMs, remainingMs }) => console.warn(`ci checks-wait: ${state} \u2014 ${Math.round(elapsedMs / 1e3)}s elapsed, ${Math.round(remainingMs / 6e4)}m left`)
|
|
@@ -47629,7 +47681,7 @@ function hotfixFollowUpLegs(runs, foldPort, alignment, foldNote, deployNote) {
|
|
|
47629
47681
|
}
|
|
47630
47682
|
return legs;
|
|
47631
47683
|
}
|
|
47632
|
-
async function runProjectInfoSyncLeg(cb, repo, sleep2 = (ms) => new Promise((
|
|
47684
|
+
async function runProjectInfoSyncLeg(cb, repo, sleep2 = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms))) {
|
|
47633
47685
|
for (let attempt = 0; ; attempt++) {
|
|
47634
47686
|
try {
|
|
47635
47687
|
return await cb(repo, true);
|
|
@@ -48358,18 +48410,63 @@ function rcRunCauseFromLog(log) {
|
|
|
48358
48410
|
function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
|
|
48359
48411
|
return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
|
|
48360
48412
|
}
|
|
48361
|
-
var suiteStateDir = (root) => (0,
|
|
48413
|
+
var suiteStateDir = (root) => (0, import_node_path45.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
|
|
48414
|
+
async function runSuiteMemberRcand(repo, previousRc, rcWasAbsent) {
|
|
48415
|
+
const deps = trainApplyDeps();
|
|
48416
|
+
deps.suiteCut = suiteCutContext(repo, SUITE_REPO);
|
|
48417
|
+
deps.announce = async () => ({ status: "skipped", note: "suite announcement belongs to MM-Work" });
|
|
48418
|
+
return rcandInCheckout(repo, deps, previousRc, rcWasAbsent);
|
|
48419
|
+
}
|
|
48420
|
+
async function rcandInCheckout(repo, deps, previousRc, rcWasAbsent) {
|
|
48421
|
+
if (repo !== SUITE_REPO) await prepareDevelopmentCheckout((args) => deps.run("git", args), repo);
|
|
48422
|
+
await deps.run("git", ["fetch", "origin", "--tags"]);
|
|
48423
|
+
let rcNow;
|
|
48424
|
+
try {
|
|
48425
|
+
rcNow = (await deps.run("git", ["rev-parse", "--verify", "origin/rc"])).trim();
|
|
48426
|
+
} catch (e) {
|
|
48427
|
+
if (!rcWasAbsent || !previousRc || repo === SUITE_REPO) throw e;
|
|
48428
|
+
const slug = repo.split("/")[1].toLowerCase();
|
|
48429
|
+
const meta = await fetchProjectBySlugChecked(slug, registryClientDeps(await loadConfig()));
|
|
48430
|
+
if (!meta.ok || meta.project?.releaseTrack !== "full" || meta.project.suite !== "mm-work")
|
|
48431
|
+
throw new Error(`${repo}: first rc branch requires releaseTrack full and suite=mm-work in META; no branch created`);
|
|
48432
|
+
const main = (await deps.run("git", ["rev-parse", "origin/main"])).trim();
|
|
48433
|
+
if (main.toLowerCase() !== previousRc.toLowerCase()) throw new Error(`${repo}: main moved since the cut snapshot; no rc branch created`);
|
|
48434
|
+
await deps.run("git", ["push", "origin", `${previousRc}:refs/heads/rc`]);
|
|
48435
|
+
await deps.run("git", ["fetch", "origin", "rc"]);
|
|
48436
|
+
rcNow = (await deps.run("git", ["rev-parse", "origin/rc"])).trim();
|
|
48437
|
+
}
|
|
48438
|
+
if (!(await deps.run("git", ["branch", "--list", "rc"])).trim()) {
|
|
48439
|
+
await deps.run("git", ["switch", "-c", "rc", "--track", "origin/rc"]);
|
|
48440
|
+
await deps.run("git", ["switch", "development"]);
|
|
48441
|
+
}
|
|
48442
|
+
if (previousRc && rcNow.toLowerCase() !== previousRc.toLowerCase()) {
|
|
48443
|
+
const tags = (await deps.run("git", ["tag", "--points-at", rcNow, "--list", "v*-rc.*"])).trim().split("\n").filter(Boolean);
|
|
48444
|
+
if (tags.length !== 1) throw new Error(`${repo}: rc moved since cut start without exactly one candidate tag; stop`);
|
|
48445
|
+
return { tag: tags[0], sha: rcNow };
|
|
48446
|
+
}
|
|
48447
|
+
try {
|
|
48448
|
+
const result = await runTrainApply("rcand", deps, { watch: true });
|
|
48449
|
+
if (result.deployStatus !== "success") throw new Error(`${repo}: rcand deploy not green (${result.deployStatus})`);
|
|
48450
|
+
return { tag: result.tag, sha: (await deps.run("git", ["rev-parse", result.tag])).trim() };
|
|
48451
|
+
} catch (e) {
|
|
48452
|
+
const existing = (await deps.run("git", ["tag", "--list", "v*-rc.*"])).trim();
|
|
48453
|
+
if (!existing || !/resume|partial|ledger|tag.*pushed/i.test(e.message)) throw e;
|
|
48454
|
+
const result = await runRcandResume(deps, { watch: true });
|
|
48455
|
+
if (result.deployStatus !== "success") throw new Error(`${repo}: resumed rcand deploy not green (${result.deployStatus})`);
|
|
48456
|
+
return { tag: result.tag, sha: result.tagSha };
|
|
48457
|
+
}
|
|
48458
|
+
}
|
|
48362
48459
|
function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
|
|
48363
|
-
const recordPath = (0,
|
|
48364
|
-
const base = (0,
|
|
48460
|
+
const recordPath = (0, import_node_path45.join)(suiteStateDir(root), "cut.json");
|
|
48461
|
+
const base = (0, import_node_path45.join)(suiteStateDir(root), "checkouts");
|
|
48365
48462
|
const checkout = async (repo) => {
|
|
48366
48463
|
if (repo === SUITE_REPO) return root;
|
|
48367
|
-
const target = (0,
|
|
48464
|
+
const target = (0, import_node_path45.join)(base, repo.split("/")[1]);
|
|
48368
48465
|
if (!(0, import_node_fs45.existsSync)(target)) {
|
|
48369
48466
|
(0, import_node_fs45.mkdirSync)(base, { recursive: true });
|
|
48370
48467
|
await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
|
|
48371
48468
|
}
|
|
48372
|
-
if (!(0, import_node_fs45.existsSync)((0,
|
|
48469
|
+
if (!(0, import_node_fs45.existsSync)((0, import_node_path45.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
|
|
48373
48470
|
const origin = await exec("git", ["remote", "get-url", "origin"], target);
|
|
48374
48471
|
if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
|
|
48375
48472
|
throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
|
|
@@ -48429,45 +48526,28 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
48429
48526
|
throw e;
|
|
48430
48527
|
}
|
|
48431
48528
|
};
|
|
48432
|
-
const runRcand = async (repo, previousRc, rcWasAbsent) =>
|
|
48433
|
-
if (repo
|
|
48434
|
-
|
|
48435
|
-
|
|
48436
|
-
|
|
48437
|
-
|
|
48438
|
-
|
|
48439
|
-
|
|
48440
|
-
|
|
48441
|
-
|
|
48442
|
-
|
|
48443
|
-
|
|
48444
|
-
|
|
48445
|
-
|
|
48446
|
-
|
|
48447
|
-
|
|
48448
|
-
|
|
48449
|
-
|
|
48450
|
-
|
|
48451
|
-
|
|
48452
|
-
|
|
48453
|
-
|
|
48454
|
-
if (previousRc && rcNow.toLowerCase() !== previousRc.toLowerCase()) {
|
|
48455
|
-
const tags = (await deps.run("git", ["tag", "--points-at", rcNow, "--list", "v*-rc.*"])).trim().split("\n").filter(Boolean);
|
|
48456
|
-
if (tags.length !== 1) throw new Error(`${repo}: rc moved since cut start without exactly one candidate tag; stop`);
|
|
48457
|
-
return { tag: tags[0], sha: rcNow };
|
|
48458
|
-
}
|
|
48459
|
-
try {
|
|
48460
|
-
const result = await runTrainApply("rcand", deps, { watch: true });
|
|
48461
|
-
if (result.deployStatus !== "success") throw new Error(`${repo}: rcand deploy not green (${result.deployStatus})`);
|
|
48462
|
-
return { tag: result.tag, sha: (await deps.run("git", ["rev-parse", result.tag])).trim() };
|
|
48463
|
-
} catch (e) {
|
|
48464
|
-
const existing = (await deps.run("git", ["tag", "--list", "v*-rc.*"])).trim();
|
|
48465
|
-
if (!existing || !/resume|partial|ledger|tag.*pushed/i.test(e.message)) throw e;
|
|
48466
|
-
const result = await runRcandResume(deps, { watch: true });
|
|
48467
|
-
if (result.deployStatus !== "success") throw new Error(`${repo}: resumed rcand deploy not green (${result.deployStatus})`);
|
|
48468
|
-
return { tag: result.tag, sha: result.tagSha };
|
|
48469
|
-
}
|
|
48470
|
-
});
|
|
48529
|
+
const runRcand = async (repo, previousRc, rcWasAbsent) => {
|
|
48530
|
+
if (repo === SUITE_REPO) return inTrain(repo, (deps) => rcandInCheckout(repo, deps, previousRc, rcWasAbsent));
|
|
48531
|
+
const target = await checkout(repo);
|
|
48532
|
+
return new Promise((resolveResult, reject) => {
|
|
48533
|
+
const child2 = (0, import_node_child_process18.fork)((0, import_node_path44.resolve)(process.argv[1]), ["devops", "suite", "member-rcand-internal", repo, previousRc ?? "", ...rcWasAbsent ? ["--rc-was-absent"] : []], {
|
|
48534
|
+
cwd: target,
|
|
48535
|
+
stdio: ["ignore", "inherit", "inherit", "ipc"],
|
|
48536
|
+
execArgv: []
|
|
48537
|
+
});
|
|
48538
|
+
let result;
|
|
48539
|
+
let failure;
|
|
48540
|
+
child2.on("message", (message2) => {
|
|
48541
|
+
result = message2.result;
|
|
48542
|
+
failure = message2.error;
|
|
48543
|
+
});
|
|
48544
|
+
child2.on("error", reject);
|
|
48545
|
+
child2.on("exit", (code) => {
|
|
48546
|
+
if (code === 0 && result) resolveResult(result);
|
|
48547
|
+
else reject(new Error(failure ?? `${repo}: member rcand process exited ${code} without a result`));
|
|
48548
|
+
});
|
|
48549
|
+
});
|
|
48550
|
+
};
|
|
48471
48551
|
const release = async (repo, expected, rcSha, opts) => inTrain(repo, async (deps) => {
|
|
48472
48552
|
await prepareRcCheckout((args) => deps.run("git", args), repo);
|
|
48473
48553
|
const plainWords = {
|
|
@@ -48522,7 +48602,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
48522
48602
|
if (!reuse) await gh(["workflow", "run", "module-rc-publish.yml", "--repo", "mutmutco/MMI-Hub", ...fields.flatMap((f) => ["--field", f])]);
|
|
48523
48603
|
let candidate = reuse;
|
|
48524
48604
|
for (let i = 0; !candidate && i < 25; i++) {
|
|
48525
|
-
await new Promise((
|
|
48605
|
+
await new Promise((resolve8) => setTimeout(resolve8, 1e3));
|
|
48526
48606
|
candidate = (await rcRuns()).find((r) => r.displayTitle === title && Date.parse(r.createdAt) >= since);
|
|
48527
48607
|
}
|
|
48528
48608
|
if (!candidate) throw new Error(`workflow dispatch outcome ambiguous for "${title}"; inspect Actions before retrying`);
|
|
@@ -48677,7 +48757,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
48677
48757
|
for (let i = 0; ; i++) {
|
|
48678
48758
|
const pin = await openSuitePinPr({ root, run: (file, args, cwd) => exec(file, args, cwd, GIT_TIMEOUT_MS) }, { repo, tag, stage: "main" });
|
|
48679
48759
|
if (pin.status !== "pending" || i >= 40) return pin;
|
|
48680
|
-
await new Promise((
|
|
48760
|
+
await new Promise((resolve8) => setTimeout(resolve8, 3e4));
|
|
48681
48761
|
}
|
|
48682
48762
|
},
|
|
48683
48763
|
suiteMapping: async (leadTag) => {
|
|
@@ -48693,7 +48773,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
48693
48773
|
if (parseSuiteMapping(body)) return;
|
|
48694
48774
|
const dir = suiteStateDir(root);
|
|
48695
48775
|
(0, import_node_fs45.mkdirSync)(dir, { recursive: true });
|
|
48696
|
-
const file = (0,
|
|
48776
|
+
const file = (0, import_node_path45.join)(dir, `notes-${leadTag}.md`);
|
|
48697
48777
|
(0, import_node_fs45.writeFileSync)(file, `${body}
|
|
48698
48778
|
|
|
48699
48779
|
${suiteMappingBlock(leadTag, mapping)}`);
|
|
@@ -48759,11 +48839,23 @@ function suiteRcDataProdDeps() {
|
|
|
48759
48839
|
const rc = facts.stages.rc;
|
|
48760
48840
|
return rc?.present ? rc.substrate ?? "an unnamed substrate" : null;
|
|
48761
48841
|
},
|
|
48762
|
-
sleep: (ms) => new Promise((
|
|
48842
|
+
sleep: (ms) => new Promise((resolve8) => setTimeout(resolve8, ms))
|
|
48763
48843
|
};
|
|
48764
48844
|
}
|
|
48765
48845
|
function registerSuiteCommands(program3) {
|
|
48766
48846
|
const suite = program3.command("suite").description("MM-Work suite status, candidate cut and release (#7262/#7263)");
|
|
48847
|
+
suite.command("member-rcand-internal", { hidden: true }).argument("<repo>").argument("<previous-rc>").option("--rc-was-absent").action(async (repo, previousRc, o) => {
|
|
48848
|
+
if (!process.send) return fail("member rcand is an internal suite child operation");
|
|
48849
|
+
try {
|
|
48850
|
+
if (repo === SUITE_REPO || (await resolveRepo())?.toLowerCase() !== repo.toLowerCase())
|
|
48851
|
+
throw new Error(`${repo}: member rcand checkout mismatch; stop`);
|
|
48852
|
+
const result = await runSuiteMemberRcand(repo, previousRc || void 0, o.rcWasAbsent);
|
|
48853
|
+
process.send({ result }, () => process.disconnect());
|
|
48854
|
+
} catch (e) {
|
|
48855
|
+
process.exitCode = 1;
|
|
48856
|
+
process.send({ error: e.message }, () => process.disconnect());
|
|
48857
|
+
}
|
|
48858
|
+
});
|
|
48767
48859
|
const leadRoot = async () => {
|
|
48768
48860
|
const repo = await resolveRepo();
|
|
48769
48861
|
if (repo?.toLowerCase() !== SUITE_REPO.toLowerCase()) throw new Error(`suite commands run only from ${SUITE_REPO} (got ${repo ?? "unknown"})`);
|
|
@@ -49005,10 +49097,10 @@ function suiteStatusDeps(github, registry2) {
|
|
|
49005
49097
|
}
|
|
49006
49098
|
|
|
49007
49099
|
// src/packages-adopt-export.ts
|
|
49008
|
-
var
|
|
49100
|
+
var import_node_child_process19 = require("node:child_process");
|
|
49009
49101
|
var import_node_fs47 = require("node:fs");
|
|
49010
49102
|
var import_node_os22 = require("node:os");
|
|
49011
|
-
var
|
|
49103
|
+
var import_node_path46 = require("node:path");
|
|
49012
49104
|
var import_node_util6 = require("node:util");
|
|
49013
49105
|
init_cli_shared();
|
|
49014
49106
|
|
|
@@ -49628,25 +49720,25 @@ function expectedFromRun(run, opts) {
|
|
|
49628
49720
|
}
|
|
49629
49721
|
async function adoptExport(opts, deps) {
|
|
49630
49722
|
if (!/^sha256:[0-9a-f]{64}$/.test(opts.digest)) throw new Error("--digest must be sha256:<64 hex>, from the export run summary");
|
|
49631
|
-
const packagePath = (0,
|
|
49632
|
-
const lockPath = (0,
|
|
49723
|
+
const packagePath = (0, import_node_path46.join)(opts.dir, "package.json");
|
|
49724
|
+
const lockPath = (0, import_node_path46.join)(opts.dir, "package-lock.json");
|
|
49633
49725
|
const packageText = (0, import_node_fs47.readFileSync)(packagePath, "utf8");
|
|
49634
49726
|
const lockText = (0, import_node_fs47.readFileSync)(lockPath, "utf8");
|
|
49635
|
-
const work = (0, import_node_fs47.mkdtempSync)((0,
|
|
49727
|
+
const work = (0, import_node_fs47.mkdtempSync)((0, import_node_path46.join)((0, import_node_os22.tmpdir)(), "mmi-adopt-export-"));
|
|
49636
49728
|
try {
|
|
49637
49729
|
const run = JSON.parse((await deps.ghApi(`repos/${EXPORT_REPO}/actions/runs/${opts.run}`)).toString("utf8"));
|
|
49638
|
-
(0, import_node_fs47.writeFileSync)((0,
|
|
49639
|
-
(0, import_node_fs47.writeFileSync)((0,
|
|
49640
|
-
(0, import_node_fs47.writeFileSync)((0,
|
|
49641
|
-
const script = (0,
|
|
49730
|
+
(0, import_node_fs47.writeFileSync)((0, import_node_path46.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
|
|
49731
|
+
(0, import_node_fs47.writeFileSync)((0, import_node_path46.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
|
|
49732
|
+
(0, import_node_fs47.writeFileSync)((0, import_node_path46.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
|
|
49733
|
+
const script = (0, import_node_path46.join)(work, "package_export.py");
|
|
49642
49734
|
(0, import_node_fs47.writeFileSync)(script, package_export_default);
|
|
49643
49735
|
await deps.python(script, ["verify", work, opts.ds, opts.screens]);
|
|
49644
|
-
const verified = (0,
|
|
49645
|
-
const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs47.readFileSync)((0,
|
|
49736
|
+
const verified = (0, import_node_path46.join)(work, "verified");
|
|
49737
|
+
const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs47.readFileSync)((0, import_node_path46.join)(verified, `${short3}.metadata.json`), "utf8"))]));
|
|
49646
49738
|
const plan = planAdoption(packageText, lockText, metadata);
|
|
49647
49739
|
for (const { name } of plan.result.adopted) {
|
|
49648
49740
|
const short3 = PACKAGES.find((p) => p.name === name).short;
|
|
49649
|
-
await deps.npm(["cache", "add", (0,
|
|
49741
|
+
await deps.npm(["cache", "add", (0, import_node_path46.join)(verified, `${short3}.tgz`)], opts.dir);
|
|
49650
49742
|
}
|
|
49651
49743
|
(0, import_node_fs47.writeFileSync)(packagePath, plan.packageText);
|
|
49652
49744
|
(0, import_node_fs47.writeFileSync)(lockPath, plan.lockText);
|
|
@@ -49662,7 +49754,7 @@ async function adoptExport(opts, deps) {
|
|
|
49662
49754
|
(0, import_node_fs47.rmSync)(work, { recursive: true, force: true });
|
|
49663
49755
|
}
|
|
49664
49756
|
}
|
|
49665
|
-
var execFileBuffer = (0, import_node_util6.promisify)(
|
|
49757
|
+
var execFileBuffer = (0, import_node_util6.promisify)(import_node_child_process19.execFile);
|
|
49666
49758
|
var MAX_OUTPUT = 200 * 1024 * 1024;
|
|
49667
49759
|
async function findPython() {
|
|
49668
49760
|
for (const bin of ["python3", "python"]) {
|
|
@@ -49788,7 +49880,7 @@ init_github_client();
|
|
|
49788
49880
|
init_cli_shared();
|
|
49789
49881
|
var import_node_fs49 = require("node:fs");
|
|
49790
49882
|
var import_node_os23 = require("node:os");
|
|
49791
|
-
var
|
|
49883
|
+
var import_node_path47 = require("node:path");
|
|
49792
49884
|
var GC_GH_TIMEOUT_MS3 = 2e4;
|
|
49793
49885
|
async function collectStatus() {
|
|
49794
49886
|
const repo = await resolveRepo();
|
|
@@ -49979,8 +50071,8 @@ async function collectOnboardStatus(opts = {}) {
|
|
|
49979
50071
|
}
|
|
49980
50072
|
const home = (0, import_node_os23.homedir)();
|
|
49981
50073
|
const plugin = onboardPluginGate({
|
|
49982
|
-
readKnown: () => readFileSyncSafe((0,
|
|
49983
|
-
readSettings: () => readFileSyncSafe((0,
|
|
50074
|
+
readKnown: () => readFileSyncSafe((0, import_node_path47.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs49.readFileSync),
|
|
50075
|
+
readSettings: () => readFileSyncSafe((0, import_node_path47.join)(home, ".claude", "settings.json"), import_node_fs49.readFileSync)
|
|
49984
50076
|
});
|
|
49985
50077
|
return {
|
|
49986
50078
|
guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
|
|
@@ -52779,7 +52871,10 @@ function buildDeployRetirePlan(input) {
|
|
|
52779
52871
|
if (!["dev", "rc", "main"].includes(input.stage)) {
|
|
52780
52872
|
throw new Error("org project deploy retire: --stage must be dev, rc, or main");
|
|
52781
52873
|
}
|
|
52782
|
-
|
|
52874
|
+
if (input.decommissioned && input.stage !== "main") {
|
|
52875
|
+
throw new Error("org project deploy retire: --decommissioned applies to --stage main only (dev/rc always retire)");
|
|
52876
|
+
}
|
|
52877
|
+
return { slug, stage: input.stage, apply: Boolean(input.apply), decommissioned: Boolean(input.decommissioned) };
|
|
52783
52878
|
}
|
|
52784
52879
|
async function runDeployRetire(input, deps) {
|
|
52785
52880
|
const plan = buildDeployRetirePlan(input);
|
|
@@ -52788,7 +52883,20 @@ async function runDeployRetire(input, deps) {
|
|
|
52788
52883
|
if (!plan.apply) {
|
|
52789
52884
|
return { slug: plan.slug, stage: plan.stage, applied: false, ok: facts !== null, existing };
|
|
52790
52885
|
}
|
|
52791
|
-
|
|
52886
|
+
if (plan.decommissioned) {
|
|
52887
|
+
const state = deps.boxServiceState ? await deps.boxServiceState(plan.stage) : "unknown";
|
|
52888
|
+
if (state !== "missing") {
|
|
52889
|
+
return {
|
|
52890
|
+
slug: plan.slug,
|
|
52891
|
+
stage: plan.stage,
|
|
52892
|
+
applied: false,
|
|
52893
|
+
ok: false,
|
|
52894
|
+
existing,
|
|
52895
|
+
error: `--decommissioned needs the box to show ${plan.stage} gone (tenant-control status serviceState=missing), got ${state} \u2014 run tenant control <repo> ${plan.stage} retire first`
|
|
52896
|
+
};
|
|
52897
|
+
}
|
|
52898
|
+
}
|
|
52899
|
+
const res = await retireDeployCoords(plan.slug, plan.stage, deps.registry, plan.decommissioned);
|
|
52792
52900
|
if (!res.ok) {
|
|
52793
52901
|
return { slug: plan.slug, stage: plan.stage, applied: true, ok: false, existing, error: writeError2(res) };
|
|
52794
52902
|
}
|
|
@@ -53537,7 +53645,7 @@ function registerSessionReport(program3) {
|
|
|
53537
53645
|
|
|
53538
53646
|
// src/stage-commands.ts
|
|
53539
53647
|
var import_node_fs51 = require("node:fs");
|
|
53540
|
-
var
|
|
53648
|
+
var import_node_path48 = require("node:path");
|
|
53541
53649
|
init_cli_shared();
|
|
53542
53650
|
init_clean_exit();
|
|
53543
53651
|
|
|
@@ -53785,8 +53893,8 @@ function registerStageCommands(program3) {
|
|
|
53785
53893
|
const repo = Array.isArray(project2?.repos) && typeof project2.repos[0] === "string" ? project2.repos[0] : slug;
|
|
53786
53894
|
const resolution = decideStage({
|
|
53787
53895
|
registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
|
|
53788
|
-
hasCompose: (0, import_node_fs51.existsSync)((0,
|
|
53789
|
-
hasEnvExample: (0, import_node_fs51.existsSync)((0,
|
|
53896
|
+
hasCompose: (0, import_node_fs51.existsSync)((0, import_node_path48.join)(process.cwd(), "docker-compose.yml")),
|
|
53897
|
+
hasEnvExample: (0, import_node_fs51.existsSync)((0, import_node_path48.join)(process.cwd(), ".env.example")),
|
|
53790
53898
|
repo
|
|
53791
53899
|
});
|
|
53792
53900
|
if (resolution.source === "derived" && resolution.derived) {
|
|
@@ -54081,7 +54189,7 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
|
|
|
54081
54189
|
var import_node_crypto17 = require("node:crypto");
|
|
54082
54190
|
var import_node_fs52 = require("node:fs");
|
|
54083
54191
|
var import_promises11 = require("node:fs/promises");
|
|
54084
|
-
var
|
|
54192
|
+
var import_node_path49 = require("node:path");
|
|
54085
54193
|
var ARTIFACT_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
54086
54194
|
var MAX_BYTES2 = 5 * 1024 * 1024 * 1024;
|
|
54087
54195
|
async function sha256File(path2) {
|
|
@@ -54091,7 +54199,7 @@ async function sha256File(path2) {
|
|
|
54091
54199
|
}
|
|
54092
54200
|
async function putTenantArtifact(repo, stage, inputPath, deps) {
|
|
54093
54201
|
if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
|
|
54094
|
-
const path2 = (0,
|
|
54202
|
+
const path2 = (0, import_node_path49.resolve)(inputPath);
|
|
54095
54203
|
const info = await (0, import_promises11.stat)(path2);
|
|
54096
54204
|
if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
|
|
54097
54205
|
if (!Number.isSafeInteger(info.size) || info.size < 1 || info.size > MAX_BYTES2) throw new Error(`tenant artifact put: file must be 1..${MAX_BYTES2} bytes`);
|
|
@@ -54281,7 +54389,7 @@ async function resolveWhoami(deps) {
|
|
|
54281
54389
|
}
|
|
54282
54390
|
|
|
54283
54391
|
// src/command-register-developer.ts
|
|
54284
|
-
var
|
|
54392
|
+
var import_node_path55 = require("node:path");
|
|
54285
54393
|
init_house_map();
|
|
54286
54394
|
init_hub_url();
|
|
54287
54395
|
|
|
@@ -54314,21 +54422,21 @@ async function executeWaveLand(plan, deps) {
|
|
|
54314
54422
|
}
|
|
54315
54423
|
|
|
54316
54424
|
// src/dist-drift.ts
|
|
54317
|
-
var
|
|
54425
|
+
var import_node_child_process20 = require("node:child_process");
|
|
54318
54426
|
var import_node_crypto19 = require("node:crypto");
|
|
54319
54427
|
var import_node_fs54 = require("node:fs");
|
|
54320
54428
|
var import_node_os24 = require("node:os");
|
|
54321
|
-
var
|
|
54429
|
+
var import_node_path51 = require("node:path");
|
|
54322
54430
|
|
|
54323
54431
|
// ../scripts/distribution-digest.mjs
|
|
54324
54432
|
var import_node_crypto18 = require("node:crypto");
|
|
54325
54433
|
var import_node_fs53 = require("node:fs");
|
|
54326
|
-
var
|
|
54434
|
+
var import_node_path50 = require("node:path");
|
|
54327
54435
|
var slash = (value) => value.replaceAll("\\", "/");
|
|
54328
54436
|
function repoPath(root, declaredPath, label) {
|
|
54329
|
-
const absoluteRoot = (0,
|
|
54330
|
-
const target = (0,
|
|
54331
|
-
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${
|
|
54437
|
+
const absoluteRoot = (0, import_node_path50.resolve)(root);
|
|
54438
|
+
const target = (0, import_node_path50.resolve)(root, declaredPath);
|
|
54439
|
+
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path50.sep}`)) {
|
|
54332
54440
|
throw new Error(`${label} ${declaredPath} escapes the repository root`);
|
|
54333
54441
|
}
|
|
54334
54442
|
return target;
|
|
@@ -54443,7 +54551,7 @@ function walkFiles(root) {
|
|
|
54443
54551
|
const files = [];
|
|
54444
54552
|
const walk2 = (directory) => {
|
|
54445
54553
|
for (const entry of (0, import_node_fs54.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
54446
|
-
const child2 = (0,
|
|
54554
|
+
const child2 = (0, import_node_path51.join)(directory, entry.name);
|
|
54447
54555
|
if (entry.isDirectory()) walk2(child2);
|
|
54448
54556
|
else files.push(child2);
|
|
54449
54557
|
}
|
|
@@ -54453,14 +54561,14 @@ function walkFiles(root) {
|
|
|
54453
54561
|
}
|
|
54454
54562
|
function bomPathFor(root) {
|
|
54455
54563
|
try {
|
|
54456
|
-
const registry2 = JSON.parse((0, import_node_fs54.readFileSync)((0,
|
|
54457
|
-
return (0,
|
|
54564
|
+
const registry2 = JSON.parse((0, import_node_fs54.readFileSync)((0, import_node_path51.join)(root, "surfaces.json"), "utf8"));
|
|
54565
|
+
return (0, import_node_path51.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
|
|
54458
54566
|
} catch {
|
|
54459
|
-
return (0,
|
|
54567
|
+
return (0, import_node_path51.join)(root, "distribution-bom.json");
|
|
54460
54568
|
}
|
|
54461
54569
|
}
|
|
54462
54570
|
function rebuildTo(packageRoot, outDir) {
|
|
54463
|
-
(0,
|
|
54571
|
+
(0, import_node_child_process20.execFileSync)(process.execPath, ["build.mjs"], {
|
|
54464
54572
|
cwd: packageRoot,
|
|
54465
54573
|
env: { ...process.env, MMI_DIST_OUTDIR: outDir },
|
|
54466
54574
|
windowsHide: true,
|
|
@@ -54469,28 +54577,28 @@ function rebuildTo(packageRoot, outDir) {
|
|
|
54469
54577
|
});
|
|
54470
54578
|
}
|
|
54471
54579
|
function runDistStatus(root) {
|
|
54472
|
-
const stage = (0, import_node_fs54.mkdtempSync)((0,
|
|
54580
|
+
const stage = (0, import_node_fs54.mkdtempSync)((0, import_node_path51.join)((0, import_node_os24.tmpdir)(), "mmi-dist-drift-"));
|
|
54473
54581
|
let overlayCount = 0;
|
|
54474
54582
|
try {
|
|
54475
|
-
const cliOut = (0,
|
|
54476
|
-
const hubOut = (0,
|
|
54477
|
-
rebuildTo((0,
|
|
54478
|
-
rebuildTo((0,
|
|
54583
|
+
const cliOut = (0, import_node_path51.join)(stage, "cli-dist");
|
|
54584
|
+
const hubOut = (0, import_node_path51.join)(stage, "hub-dist");
|
|
54585
|
+
rebuildTo((0, import_node_path51.join)(root, "cli"), cliOut);
|
|
54586
|
+
rebuildTo((0, import_node_path51.join)(root, "updater"), hubOut);
|
|
54479
54587
|
const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
|
|
54480
54588
|
const rebuilt = (path2) => {
|
|
54481
54589
|
const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
|
|
54482
|
-
return spec ? readOrNull((0,
|
|
54590
|
+
return spec ? readOrNull((0, import_node_path51.join)(outDirFor(spec.packageDir), spec.output)) : null;
|
|
54483
54591
|
};
|
|
54484
|
-
const committed = (path2) => readOrNull((0,
|
|
54485
|
-
const tree = (path2) => readOrNull((0,
|
|
54486
|
-
const distRoot = (0,
|
|
54487
|
-
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0,
|
|
54592
|
+
const committed = (path2) => readOrNull((0, import_node_path51.join)(root, path2));
|
|
54593
|
+
const tree = (path2) => readOrNull((0, import_node_path51.join)(root, path2));
|
|
54594
|
+
const distRoot = (0, import_node_path51.join)(root, "cli", "dist");
|
|
54595
|
+
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path51.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
|
|
54488
54596
|
const bom = JSON.parse((0, import_node_fs54.readFileSync)(bomPathFor(root), "utf8"));
|
|
54489
54597
|
const digest = (entries) => {
|
|
54490
|
-
const overlay = (0,
|
|
54598
|
+
const overlay = (0, import_node_path51.join)(stage, `overlay-${overlayCount++}`);
|
|
54491
54599
|
for (const entry of entries) {
|
|
54492
|
-
const target = (0,
|
|
54493
|
-
(0, import_node_fs54.mkdirSync)((0,
|
|
54600
|
+
const target = (0, import_node_path51.join)(overlay, entry.path);
|
|
54601
|
+
(0, import_node_fs54.mkdirSync)((0, import_node_path51.dirname)(target), { recursive: true });
|
|
54494
54602
|
(0, import_node_fs54.writeFileSync)(target, entry.bytes);
|
|
54495
54603
|
}
|
|
54496
54604
|
return digestPackedFiles(overlay, entries.map((entry) => entry.path));
|
|
@@ -54502,7 +54610,7 @@ function runDistStatus(root) {
|
|
|
54502
54610
|
}
|
|
54503
54611
|
|
|
54504
54612
|
// src/doc-refs-live.ts
|
|
54505
|
-
var
|
|
54613
|
+
var import_node_path52 = require("node:path");
|
|
54506
54614
|
var concrete = (value) => !!value && !/[<>{}$]/.test(value);
|
|
54507
54615
|
var liveOption = (tokens2, flag) => {
|
|
54508
54616
|
const index = tokens2.indexOf(flag);
|
|
@@ -54575,7 +54683,7 @@ async function runLiveDocRefs(root, deps, live) {
|
|
|
54575
54683
|
const offline = runDocRefs(root, { ...deps, runbooksOnly: true });
|
|
54576
54684
|
const read = deps.readFile ?? readFileOrNull;
|
|
54577
54685
|
const docs = Object.fromEntries((deps.listDocs ?? defaultListDocs)(root).flatMap((doc) => {
|
|
54578
|
-
const body = read((0,
|
|
54686
|
+
const body = read((0, import_node_path52.join)(root, doc));
|
|
54579
54687
|
return body !== null && isRunbook(doc, body) && !deps.isIgnored?.([doc]).has(doc) ? [[doc, body]] : [];
|
|
54580
54688
|
}));
|
|
54581
54689
|
const remote = await checkRunbookLive(docs, live);
|
|
@@ -54584,9 +54692,9 @@ async function runLiveDocRefs(root, deps, live) {
|
|
|
54584
54692
|
}
|
|
54585
54693
|
|
|
54586
54694
|
// src/doc-refs-live-io.ts
|
|
54587
|
-
var
|
|
54695
|
+
var import_node_child_process21 = require("node:child_process");
|
|
54588
54696
|
var import_node_util7 = require("node:util");
|
|
54589
|
-
var exec2 = (0, import_node_util7.promisify)(
|
|
54697
|
+
var exec2 = (0, import_node_util7.promisify)(import_node_child_process21.execFile);
|
|
54590
54698
|
function createRunbookLiveDeps(cliBin) {
|
|
54591
54699
|
const json = async (args) => {
|
|
54592
54700
|
const { stdout } = await exec2(process.execPath, [cliBin, ...args, "--json"], { windowsHide: true, timeout: 3e4, maxBuffer: 4 * 1024 * 1024 });
|
|
@@ -54612,7 +54720,7 @@ function createRunbookLiveDeps(cliBin) {
|
|
|
54612
54720
|
};
|
|
54613
54721
|
const first = await probe().catch(() => 599);
|
|
54614
54722
|
if (first < 500) return first;
|
|
54615
|
-
await new Promise((
|
|
54723
|
+
await new Promise((resolve8) => setTimeout(resolve8, 2e4));
|
|
54616
54724
|
return probe();
|
|
54617
54725
|
}
|
|
54618
54726
|
};
|
|
@@ -54715,7 +54823,7 @@ init_hub_auth();
|
|
|
54715
54823
|
|
|
54716
54824
|
// src/schedules-lift-command.ts
|
|
54717
54825
|
var import_promises12 = require("node:fs/promises");
|
|
54718
|
-
var
|
|
54826
|
+
var import_node_path53 = require("node:path");
|
|
54719
54827
|
init_clean_exit();
|
|
54720
54828
|
init_cli_shared();
|
|
54721
54829
|
var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
|
|
@@ -54744,7 +54852,7 @@ async function readWorkflowFiles(dir) {
|
|
|
54744
54852
|
const files = [];
|
|
54745
54853
|
for (const name of names.sort()) {
|
|
54746
54854
|
if (!/\.ya?ml$/.test(name)) continue;
|
|
54747
|
-
files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises12.readFile)((0,
|
|
54855
|
+
files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises12.readFile)((0, import_node_path53.join)(dir, name), "utf8") });
|
|
54748
54856
|
}
|
|
54749
54857
|
return files;
|
|
54750
54858
|
}
|
|
@@ -54826,9 +54934,9 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
|
|
|
54826
54934
|
}
|
|
54827
54935
|
|
|
54828
54936
|
// src/spawn-policy-core.ts
|
|
54829
|
-
var
|
|
54937
|
+
var import_node_child_process22 = require("node:child_process");
|
|
54830
54938
|
var import_node_fs55 = require("node:fs");
|
|
54831
|
-
var
|
|
54939
|
+
var import_node_path54 = require("node:path");
|
|
54832
54940
|
var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
|
|
54833
54941
|
var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
|
|
54834
54942
|
var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
|
|
@@ -54897,7 +55005,7 @@ function findViolationsInSource(raw) {
|
|
|
54897
55005
|
return found;
|
|
54898
55006
|
}
|
|
54899
55007
|
function policedFiles(root) {
|
|
54900
|
-
const r = (0,
|
|
55008
|
+
const r = (0, import_node_child_process22.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
|
|
54901
55009
|
cwd: root,
|
|
54902
55010
|
encoding: "utf8",
|
|
54903
55011
|
windowsHide: true,
|
|
@@ -54914,7 +55022,7 @@ function runSpawnPolicy(root) {
|
|
|
54914
55022
|
for (const file of files) {
|
|
54915
55023
|
let raw;
|
|
54916
55024
|
try {
|
|
54917
|
-
raw = (0, import_node_fs55.readFileSync)((0,
|
|
55025
|
+
raw = (0, import_node_fs55.readFileSync)((0, import_node_path54.join)(root, file), "utf8");
|
|
54918
55026
|
} catch {
|
|
54919
55027
|
continue;
|
|
54920
55028
|
}
|
|
@@ -54934,7 +55042,7 @@ function runSpawnPolicy(root) {
|
|
|
54934
55042
|
function registerDeveloperCommands(program3) {
|
|
54935
55043
|
const rules = program3.command("rules").description("org-managed .gitignore delivery");
|
|
54936
55044
|
rules.command("gitignore").option("--write", "upsert the managed block into .gitignore (default: check only, non-zero exit on drift)").option("--json", "machine-readable output").description("verify (or --write) this repo's org-managed .gitignore block matches the SSOT").action((opts) => {
|
|
54937
|
-
const path2 = (0,
|
|
55045
|
+
const path2 = (0, import_node_path55.join)(process.cwd(), ".gitignore");
|
|
54938
55046
|
const current = (0, import_node_fs56.existsSync)(path2) ? (0, import_node_fs56.readFileSync)(path2, "utf8") : null;
|
|
54939
55047
|
const plan = planManagedGitignore(current);
|
|
54940
55048
|
const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
|
|
@@ -55215,7 +55323,7 @@ ${r.stderr ?? ""}`).catch(() => "");
|
|
|
55215
55323
|
var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
|
|
55216
55324
|
var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
|
|
55217
55325
|
function envHealLockPath(home) {
|
|
55218
|
-
return (0,
|
|
55326
|
+
return (0, import_node_path56.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
|
|
55219
55327
|
}
|
|
55220
55328
|
async function withEnvHealLock(what, run) {
|
|
55221
55329
|
try {
|
|
@@ -55387,7 +55495,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
55387
55495
|
// has no generated routing index would
|
|
55388
55496
|
// get a permanent — demanding an artifact it never asked for.
|
|
55389
55497
|
docsIndexState: (root) => {
|
|
55390
|
-
if (!(0, import_node_fs57.existsSync)((0,
|
|
55498
|
+
if (!(0, import_node_fs57.existsSync)((0, import_node_path56.join)(root, DOCS_INDEX_PATH))) return void 0;
|
|
55391
55499
|
const real = createDocsIndexDeps(root);
|
|
55392
55500
|
let docs;
|
|
55393
55501
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -55396,7 +55504,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
55396
55504
|
},
|
|
55397
55505
|
// #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
|
|
55398
55506
|
healDocsIndex: (root) => {
|
|
55399
|
-
if (!(0, import_node_fs57.existsSync)((0,
|
|
55507
|
+
if (!(0, import_node_fs57.existsSync)((0, import_node_path56.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
|
|
55400
55508
|
const real = createDocsIndexDeps(root);
|
|
55401
55509
|
let docs;
|
|
55402
55510
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -55417,8 +55525,8 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
55417
55525
|
});
|
|
55418
55526
|
const raced = await Promise.race([
|
|
55419
55527
|
work.then((r) => ({ ...r, timedOut: false })),
|
|
55420
|
-
new Promise((
|
|
55421
|
-
ceiling = setTimeout(() =>
|
|
55528
|
+
new Promise((resolve8) => {
|
|
55529
|
+
ceiling = setTimeout(() => resolve8({ timedOut: true, scanned: 0, findings: 0, fixed: 0, failed: 0 }), BOARD_DOCTOR_TIMEOUT_MS);
|
|
55422
55530
|
})
|
|
55423
55531
|
]);
|
|
55424
55532
|
if (raced.timedOut) return { scanned: 0, findings: 0, fixed: 0, failed: 0, timedOut: true };
|
|
@@ -55451,8 +55559,8 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
55451
55559
|
incomplete: nb.incomplete,
|
|
55452
55560
|
timedOut: false
|
|
55453
55561
|
})),
|
|
55454
|
-
new Promise((
|
|
55455
|
-
ceiling = setTimeout(() =>
|
|
55562
|
+
new Promise((resolve8) => {
|
|
55563
|
+
ceiling = setTimeout(() => resolve8({ driftLines: [], incomplete: [], timedOut: true }), SCHEDULES_DRIFT_TIMEOUT_MS);
|
|
55456
55564
|
})
|
|
55457
55565
|
]);
|
|
55458
55566
|
if (!raced.timedOut && raced.incomplete.length === 0) writeSchedulesDriftCache(cachePath, raced.driftLines);
|
|
@@ -56064,7 +56172,7 @@ projectDeploy.command("doctor").description("read-only estate port scan; --box l
|
|
|
56064
56172
|
if (report.error && report.status !== 403) return failGraceful(`org project deploy doctor: ${report.error}`);
|
|
56065
56173
|
if (!report.ok && !report.error) process.exitCode = 1;
|
|
56066
56174
|
});
|
|
56067
|
-
projectDeploy.command("retire [owner/repo]").description("retire (tombstone) one stage's DEPLOY# row for a project that no longer deploys through it (#7095, master-only). --stage is required. DRY-RUN by default \u2014 pass --apply to actually write; defaults to the current repo. Refuses a tenant-container project's live main row.").addOption(new Option("--stage <stage>", "dev | rc | main (required)").choices(["dev", "rc", "main"])).option("--apply", "actually retire (default is a dry-run preview of the row that would be retired)").option("--json", "machine-readable output").action(async (repoOrSlug, o) => {
|
|
56175
|
+
projectDeploy.command("retire [owner/repo]").description("retire (tombstone) one stage's DEPLOY# row for a project that no longer deploys through it (#7095, master-only). --stage is required. DRY-RUN by default \u2014 pass --apply to actually write; defaults to the current repo. Refuses a tenant-container project's live main row.").addOption(new Option("--stage <stage>", "dev | rc | main (required)").choices(["dev", "rc", "main"])).option("--apply", "actually retire (default is a dry-run preview of the row that would be retired)").option("--decommissioned", "main only (#8148): retire a tenant-container main row after `runtime tenant control <repo> main retire`; the box must show main gone").option("--json", "machine-readable output").action(async (repoOrSlug, o) => {
|
|
56068
56176
|
const stage = projectDeploy.opts().stage;
|
|
56069
56177
|
if (!stage) return fail("org project deploy retire: --stage is required (dev | rc | main)");
|
|
56070
56178
|
const cfg = await loadConfig();
|
|
@@ -56077,8 +56185,14 @@ projectDeploy.command("retire [owner/repo]").description("retire (tombstone) one
|
|
|
56077
56185
|
let result;
|
|
56078
56186
|
try {
|
|
56079
56187
|
result = await runDeployRetire(
|
|
56080
|
-
{ target, stage, apply: Boolean(o.apply) },
|
|
56081
|
-
{
|
|
56188
|
+
{ target, stage, apply: Boolean(o.apply), decommissioned: Boolean(o.decommissioned) },
|
|
56189
|
+
{
|
|
56190
|
+
registry: registryClientDeps(cfg),
|
|
56191
|
+
boxServiceState: async (s) => {
|
|
56192
|
+
const r = await runTenantControl(trainApplyDeps(), { repo: target, stage: s, action: "status", watch: true });
|
|
56193
|
+
return r.conclusion === "success" ? r.serviceState ?? "unknown" : "error";
|
|
56194
|
+
}
|
|
56195
|
+
}
|
|
56082
56196
|
);
|
|
56083
56197
|
} catch (e) {
|
|
56084
56198
|
return fail(e.message);
|
|
@@ -56504,16 +56618,16 @@ function ciAuditDeps2() {
|
|
|
56504
56618
|
// gate re-seed step is skipped gracefully rather than failing mid-run.
|
|
56505
56619
|
readSeedFile: (path2) => {
|
|
56506
56620
|
if (!root) return null;
|
|
56507
|
-
const fullPath = (0,
|
|
56621
|
+
const fullPath = (0, import_node_path56.join)(root, path2);
|
|
56508
56622
|
return (0, import_node_fs57.existsSync)(fullPath) ? (0, import_node_fs57.readFileSync)(fullPath, "utf8") : null;
|
|
56509
56623
|
}
|
|
56510
56624
|
};
|
|
56511
56625
|
}
|
|
56512
56626
|
function hubRoot2() {
|
|
56513
|
-
const fromPkg = (0,
|
|
56627
|
+
const fromPkg = (0, import_node_path56.join)(__dirname, "..", "..");
|
|
56514
56628
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
56515
|
-
if ((0, import_node_fs57.existsSync)((0,
|
|
56516
|
-
if ((0, import_node_fs57.existsSync)((0,
|
|
56629
|
+
if ((0, import_node_fs57.existsSync)((0, import_node_path56.join)(fromPkg, marker))) return fromPkg;
|
|
56630
|
+
if ((0, import_node_fs57.existsSync)((0, import_node_path56.join)(process.cwd(), marker))) return process.cwd();
|
|
56517
56631
|
return null;
|
|
56518
56632
|
}
|
|
56519
56633
|
registerQueryCommands(program2);
|
|
@@ -56682,7 +56796,7 @@ function directoryBytes(path2) {
|
|
|
56682
56796
|
return 0;
|
|
56683
56797
|
}
|
|
56684
56798
|
for (const entry of entries) {
|
|
56685
|
-
const child2 = (0,
|
|
56799
|
+
const child2 = (0, import_node_path56.join)(path2, entry.name);
|
|
56686
56800
|
if (entry.isDirectory()) total += directoryBytes(child2);
|
|
56687
56801
|
else {
|
|
56688
56802
|
try {
|
|
@@ -56712,7 +56826,7 @@ function pluginCacheFsDeps(configRoot, dirBytes) {
|
|
|
56712
56826
|
dirBytes,
|
|
56713
56827
|
listStagingDirs: (root) => (0, import_node_fs57.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
|
|
56714
56828
|
try {
|
|
56715
|
-
return { name: d.name, mtimeMs: newestMtimeMs((0,
|
|
56829
|
+
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path56.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs57.statSync)(p).mtimeMs) };
|
|
56716
56830
|
} catch {
|
|
56717
56831
|
return { name: d.name, mtimeMs: Date.now() };
|
|
56718
56832
|
}
|
|
@@ -56726,7 +56840,7 @@ function stagingApplyFsGuard(configRoot) {
|
|
|
56726
56840
|
return {
|
|
56727
56841
|
referencedPaths: () => readInstalledPluginRefs(configRoot),
|
|
56728
56842
|
mtimeMs: (name) => {
|
|
56729
|
-
const p = (0,
|
|
56843
|
+
const p = (0, import_node_path56.join)(stagingRoot, name);
|
|
56730
56844
|
if (!(0, import_node_fs57.existsSync)(p)) return null;
|
|
56731
56845
|
try {
|
|
56732
56846
|
return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs57.statSync)(q).mtimeMs);
|
package/package.json
CHANGED