@mutmutco/cli 4.5.34 → 4.5.35
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 +53 -15
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -16840,10 +16840,10 @@ var rollout_plan_default = {
|
|
|
16840
16840
|
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)."
|
|
16841
16841
|
},
|
|
16842
16842
|
baseline: {
|
|
16843
|
-
version: "4.5.
|
|
16844
|
-
tag: "v4.5.
|
|
16845
|
-
commit: "
|
|
16846
|
-
npm: "@mutmutco/cli@4.5.
|
|
16843
|
+
version: "4.5.35",
|
|
16844
|
+
tag: "v4.5.35",
|
|
16845
|
+
commit: "f10f5c65382f",
|
|
16846
|
+
npm: "@mutmutco/cli@4.5.35"
|
|
16847
16847
|
},
|
|
16848
16848
|
exitCriterion: "fleet-n-of-n",
|
|
16849
16849
|
hubOnlyShortcut: "forbidden",
|
|
@@ -16860,14 +16860,14 @@ var rollout_plan_default = {
|
|
|
16860
16860
|
repo: "mutmutco/mmi-hub",
|
|
16861
16861
|
role: "canary",
|
|
16862
16862
|
schedule: "train",
|
|
16863
|
-
v3Target: "v4.5.
|
|
16863
|
+
v3Target: "v4.5.35"
|
|
16864
16864
|
}
|
|
16865
16865
|
],
|
|
16866
16866
|
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.",
|
|
16867
16867
|
rollback: {
|
|
16868
16868
|
independent: true,
|
|
16869
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
16870
|
-
v3Target: "v4.5.
|
|
16869
|
+
mechanism: "npm dist-tag latest -> 4.5.35 and redeploy the Hub Lambda from tag v4.5.35 (f10f5c65382f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
16870
|
+
v3Target: "v4.5.35 (@mutmutco/cli@4.5.35, tag commit f10f5c65382f \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
16871
16871
|
}
|
|
16872
16872
|
},
|
|
16873
16873
|
{
|
|
@@ -34313,12 +34313,13 @@ var import_node_crypto11 = require("node:crypto");
|
|
|
34313
34313
|
var SCHEMA = "mmi-suite-cut/v1";
|
|
34314
34314
|
var SHA2 = /^[a-f0-9]{40}$/i;
|
|
34315
34315
|
var RC_TAG = /^v\d+\.\d+\.\d+-rc\.\d+$/;
|
|
34316
|
+
var RELEASE_TAG = /^v\d+\.\d+\.\d+$/;
|
|
34316
34317
|
function suitePins(record) {
|
|
34317
|
-
return record.members.map((m) =>
|
|
34318
|
+
return record.members.map((m) => m.carried ? { module: m.id, rc: m.rcPin, main: m.mainPin } : {
|
|
34318
34319
|
module: m.id,
|
|
34319
34320
|
rc: `https://${m.id === "katip" ? m.rcHost ?? m.host : m.host}/${m.id === "katip" ? "" : "rc/"}module.js?v=${m.tag}`,
|
|
34320
34321
|
main: `https://${m.host}/module.js?v=${suiteReleaseTag(m.tag)}`
|
|
34321
|
-
})
|
|
34322
|
+
});
|
|
34322
34323
|
}
|
|
34323
34324
|
function suiteReleaseTag(rc) {
|
|
34324
34325
|
if (!RC_TAG.test(rc)) throw new Error(`invalid rc tag ${rc}`);
|
|
@@ -34338,7 +34339,7 @@ function readSuiteCut(path2) {
|
|
|
34338
34339
|
} catch {
|
|
34339
34340
|
throw new Error(`suite cut record unreadable at ${path2}; repair it, never recut`);
|
|
34340
34341
|
}
|
|
34341
|
-
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.pinMerged !== void 0 && (record.pinMerged !== true && record.pinMerged !== false || !record.pinPr) || 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"].includes(record.announcement) || !record.leadReleased) || 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.backendAfterRelease !== void 0 && (!m.released || typeof m.backendAfterRelease !== "string")))
|
|
34342
|
+
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.pinMerged !== void 0 && (record.pinMerged !== true && record.pinMerged !== false || !record.pinPr) || 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"].includes(record.announcement) || !record.leadReleased) || 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.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)))
|
|
34342
34343
|
throw new Error(`suite cut record has unknown or invalid state at ${path2}; repair it, never recut`);
|
|
34343
34344
|
return record;
|
|
34344
34345
|
}
|
|
@@ -34352,6 +34353,27 @@ function writeSuiteCut(path2, record) {
|
|
|
34352
34353
|
throw new Error(`suite cut record write failed at ${path2}: ${e.message}; stop, verify the file before retrying`);
|
|
34353
34354
|
}
|
|
34354
34355
|
}
|
|
34356
|
+
function isPin(url) {
|
|
34357
|
+
return typeof url === "string" && url.startsWith("https://");
|
|
34358
|
+
}
|
|
34359
|
+
function pinVersion(url) {
|
|
34360
|
+
try {
|
|
34361
|
+
return url ? new URL(url).searchParams.get("v") ?? "" : "";
|
|
34362
|
+
} catch {
|
|
34363
|
+
return "";
|
|
34364
|
+
}
|
|
34365
|
+
}
|
|
34366
|
+
async function carriedPins(deps, member, bundles) {
|
|
34367
|
+
const main = bundles.main;
|
|
34368
|
+
if (!main || !RELEASE_TAG.test(pinVersion(main))) throw new Error(`${member.repo}: nothing new since rc, but its MM-Work main pin ${main ?? "(none)"} has no ?v=vX.Y.Z release; pin it before the suite cut`);
|
|
34369
|
+
for (const url of [bundles.rc, main]) {
|
|
34370
|
+
const tag = pinVersion(url);
|
|
34371
|
+
if (!RC_TAG.test(tag) && !RELEASE_TAG.test(tag)) continue;
|
|
34372
|
+
const sha = await deps.tagSha(member.repo, tag);
|
|
34373
|
+
if (sha && await deps.contains(member.repo, member.development, sha)) return { rcPin: url, mainPin: main };
|
|
34374
|
+
}
|
|
34375
|
+
throw new Error(`${member.repo}: nothing new since rc, but no pinned MM-Work bundle carries development ${member.development.slice(0, 12)}; pin it before the suite cut`);
|
|
34376
|
+
}
|
|
34355
34377
|
async function suiteRcand(deps, opts) {
|
|
34356
34378
|
if (!opts.ownerGo) throw new Error("suite rcand requires --owner-go (rc uses live data); nothing was written");
|
|
34357
34379
|
const members = suiteMembers(await deps.registry());
|
|
@@ -34364,8 +34386,6 @@ async function suiteRcand(deps, opts) {
|
|
|
34364
34386
|
if (opts.dryRun) return { plan };
|
|
34365
34387
|
let record = readSuiteCut(deps.recordPath);
|
|
34366
34388
|
if (record?.announcement === "sent" && record.leadReleased) {
|
|
34367
|
-
const heads = await Promise.all(modules.map(async (m) => [await deps.head(m.repo, "development"), await deps.head(m.repo, "rc")]));
|
|
34368
|
-
if (heads.some(([dev, rc]) => dev === rc)) throw new Error("a member has no new development commits since rc; no new suite cut started");
|
|
34369
34389
|
const archive = `${deps.recordPath}.${record.leadRcTag}.json`;
|
|
34370
34390
|
if ((0, import_node_fs29.existsSync)(archive)) throw new Error(`suite cut archive already exists at ${archive}; inspect before a new cut`);
|
|
34371
34391
|
(0, import_node_fs29.renameSync)(deps.recordPath, archive);
|
|
@@ -34390,9 +34410,22 @@ async function suiteRcand(deps, opts) {
|
|
|
34390
34410
|
if (!record) throw new Error("suite cut record unavailable after initialization");
|
|
34391
34411
|
if (record.members.length !== modules.length || modules.some((m) => !record.members.some((r) => r.repo === m.repo && r.id === m.id)))
|
|
34392
34412
|
throw new Error("suite roster changed since cut began; refuse to omit or add a member");
|
|
34413
|
+
const quiet = [];
|
|
34414
|
+
for (const member of record.members) {
|
|
34415
|
+
if (!member.tag && !member.carried && await deps.contains(member.repo, member.development, member.previousRc)) quiet.push(member);
|
|
34416
|
+
}
|
|
34417
|
+
if (record.members.every((m) => m.carried || quiet.includes(m))) {
|
|
34418
|
+
(0, import_node_fs29.rmSync)(deps.recordPath, { force: true });
|
|
34419
|
+
throw new Error("nothing to promote: no MM-Work module has new development commits since its rc; no suite cut started");
|
|
34420
|
+
}
|
|
34421
|
+
for (const member of quiet) {
|
|
34422
|
+
Object.assign(member, { carried: true }, await carriedPins(deps, member, modules.find((m) => m.repo === member.repo).bundles));
|
|
34423
|
+
writeSuiteCut(deps.recordPath, record);
|
|
34424
|
+
}
|
|
34393
34425
|
for (const member of record.members) {
|
|
34394
34426
|
if ((await deps.head(member.repo, "development"))?.toLowerCase() !== member.development.toLowerCase())
|
|
34395
34427
|
throw new Error(`${member.repo}: development moved after the cut snapshot; refuse to add untested code`);
|
|
34428
|
+
if (member.carried) continue;
|
|
34396
34429
|
if (!member.tag) {
|
|
34397
34430
|
const cut = await deps.rcand(member.repo, member.previousRc, member.rcWasAbsent);
|
|
34398
34431
|
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`);
|
|
@@ -34443,6 +34476,11 @@ async function suiteRelease(deps, ownerGo) {
|
|
|
34443
34476
|
if (members.length !== record.members.length || members.some((m) => !record.members.some((r) => r.repo === m.repo && r.id === m.id))) throw new Error("suite roster changed after the cut; release refused");
|
|
34444
34477
|
await deps.verifyPins(suitePins(record));
|
|
34445
34478
|
for (const member of record.members) {
|
|
34479
|
+
if (member.carried) {
|
|
34480
|
+
const live2 = await deps.backend({ repo: member.repo, id: member.id, bundles: {} });
|
|
34481
|
+
if (live2.version !== member.backend) throw new Error(`${member.repo}: live backend changed after the cut (${member.backend} \u2192 ${live2.version}); release refused`);
|
|
34482
|
+
continue;
|
|
34483
|
+
}
|
|
34446
34484
|
const [sha, live, rcHead] = await Promise.all([deps.tagSha(member.repo, member.tag), deps.backend({ repo: member.repo, id: member.id, bundles: {} }), deps.head(member.repo, "rc")]);
|
|
34447
34485
|
if (!sha || sha.toLowerCase() !== member.sha?.toLowerCase() || !member.released && rcHead?.toLowerCase() !== member.sha?.toLowerCase()) throw new Error(`${member.repo}: rc tag/branch ${member.tag} changed after the cut; release refused`);
|
|
34448
34486
|
const katipReleaseSha = member.id === "katip" ? await deps.tagSha(member.repo, suiteReleaseTag(member.tag)) : void 0;
|
|
@@ -34452,7 +34490,7 @@ async function suiteRelease(deps, ownerGo) {
|
|
|
34452
34490
|
}
|
|
34453
34491
|
if ((await deps.tagSha(SUITE_REPO, record.leadRcTag))?.toLowerCase() !== record.leadRcSha?.toLowerCase()) throw new Error("MM-Work rc tag changed after the cut; release refused");
|
|
34454
34492
|
for (const member of record.members) {
|
|
34455
|
-
if (member.released) continue;
|
|
34493
|
+
if (member.released || member.carried) continue;
|
|
34456
34494
|
await deps.release(member.repo, suiteReleaseTag(member.tag), member.sha);
|
|
34457
34495
|
if (member.id === "katip") {
|
|
34458
34496
|
const expected = await deps.tagSha(member.repo, suiteReleaseTag(member.tag));
|
|
@@ -44471,7 +44509,7 @@ function registerSuiteCommands(program3) {
|
|
|
44471
44509
|
console.log(o.json ? JSON.stringify(result, null, 2) : [
|
|
44472
44510
|
`suite rcand ${o.dryRun ? "dry-run" : "receipt"}:`,
|
|
44473
44511
|
...result.plan.map((line) => ` - ${line}`),
|
|
44474
|
-
...result.record?.members.map((m) => ` - ${m.repo}: ${m.tag} (${m.sha?.slice(0, 12)}) ${m.published ? "served" : "pending"}`) ?? [],
|
|
44512
|
+
...result.record?.members.map((m) => m.carried ? ` - ${m.repo}: carried (nothing new) at ${m.mainPin}` : ` - ${m.repo}: ${m.tag} (${m.sha?.slice(0, 12)}) ${m.published ? "served" : "pending"}`) ?? [],
|
|
44475
44513
|
...result.record ? [` - pin PR ${result.record.pinPr}: merged; MM-Work ${result.record.leadRcTag}`] : []
|
|
44476
44514
|
].join("\n"));
|
|
44477
44515
|
} catch (e) {
|
|
@@ -44494,7 +44532,7 @@ function registerSuiteCommands(program3) {
|
|
|
44494
44532
|
}
|
|
44495
44533
|
console.log(o.json ? JSON.stringify(result, null, 2) : [
|
|
44496
44534
|
`suite release: ${result.leadRcTag} \u2192 main`,
|
|
44497
|
-
...result.members.map((m) => ` - ${m.repo}: ${m.tag} \u2192 main ${m.released ? "released" : "pending"}`),
|
|
44535
|
+
...result.members.map((m) => m.carried ? ` - ${m.repo}: carried, untouched` : ` - ${m.repo}: ${m.tag} \u2192 main ${m.released ? "released" : "pending"}`),
|
|
44498
44536
|
` - MM-Work: ${result.leadReleased ? "released" : "pending"}; announcement: ${result.announcement}`
|
|
44499
44537
|
].join("\n"));
|
|
44500
44538
|
} catch (e) {
|
package/package.json
CHANGED