@mutmutco/cli 4.3.55 → 4.3.56
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 +71 -23
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -15877,10 +15877,10 @@ var rollout_plan_default = {
|
|
|
15877
15877
|
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)."
|
|
15878
15878
|
},
|
|
15879
15879
|
baseline: {
|
|
15880
|
-
version: "4.3.
|
|
15881
|
-
tag: "v4.3.
|
|
15882
|
-
commit: "
|
|
15883
|
-
npm: "@mutmutco/cli@4.3.
|
|
15880
|
+
version: "4.3.56",
|
|
15881
|
+
tag: "v4.3.56",
|
|
15882
|
+
commit: "497a375fabfc",
|
|
15883
|
+
npm: "@mutmutco/cli@4.3.56"
|
|
15884
15884
|
},
|
|
15885
15885
|
exitCriterion: "fleet-n-of-n",
|
|
15886
15886
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15897,14 +15897,14 @@ var rollout_plan_default = {
|
|
|
15897
15897
|
repo: "mutmutco/mmi-hub",
|
|
15898
15898
|
role: "canary",
|
|
15899
15899
|
schedule: "train",
|
|
15900
|
-
v3Target: "v4.3.
|
|
15900
|
+
v3Target: "v4.3.56"
|
|
15901
15901
|
}
|
|
15902
15902
|
],
|
|
15903
15903
|
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.",
|
|
15904
15904
|
rollback: {
|
|
15905
15905
|
independent: true,
|
|
15906
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15907
|
-
v3Target: "v4.3.
|
|
15906
|
+
mechanism: "npm dist-tag latest -> 4.3.56 and redeploy the Hub Lambda from tag v4.3.56 (497a375fabfc); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15907
|
+
v3Target: "v4.3.56 (@mutmutco/cli@4.3.56, tag commit 497a375fabfc \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15908
15908
|
}
|
|
15909
15909
|
},
|
|
15910
15910
|
{
|
|
@@ -18916,6 +18916,21 @@ function prodReleaseTargets(model) {
|
|
|
18916
18916
|
if (model === "registry-publish") return [{ workflow: "publish.yml", event: "release" }];
|
|
18917
18917
|
return [];
|
|
18918
18918
|
}
|
|
18919
|
+
function trainObservesShipment(model) {
|
|
18920
|
+
return isCentralDispatchModel(model) || prodReleaseTargets(model).length > 0;
|
|
18921
|
+
}
|
|
18922
|
+
function shipLegsGreen(deploy, publish) {
|
|
18923
|
+
const green = (s) => s === "complete" || s === "skipped";
|
|
18924
|
+
return green(deploy?.state) && green(publish?.state);
|
|
18925
|
+
}
|
|
18926
|
+
async function announceShippedRelease(deps, args, model, legs, deferred) {
|
|
18927
|
+
if (!deps.announce) return void 0;
|
|
18928
|
+
if (trainObservesShipment(model) && !shipLegsGreen(legs.deploy, legs.publish)) {
|
|
18929
|
+
const failed = legs.deploy.state === "failed" || legs.publish.state === "failed";
|
|
18930
|
+
return `not announced: deploy/publish ${failed ? "FAILED" : "not proven green"} \u2014 ${deferred}`;
|
|
18931
|
+
}
|
|
18932
|
+
return (await deps.announce(args)).note;
|
|
18933
|
+
}
|
|
18919
18934
|
async function listTargetRun(deps, repo, target, headSha) {
|
|
18920
18935
|
let rows;
|
|
18921
18936
|
try {
|
|
@@ -22836,6 +22851,9 @@ async function recordRcandDeployLegs(ledger, deps, anchors, deployModel, d, opts
|
|
|
22836
22851
|
await recordPhase(ledger, deps, anchors, "alignment", phaseEntry({ state: "skipped", sha, note: "rcand aligns no branch \u2014 alignment rides the release" }), { ...opts, landed });
|
|
22837
22852
|
return dispatch;
|
|
22838
22853
|
}
|
|
22854
|
+
function releaseAnnounceDeferral(model, summaryFile) {
|
|
22855
|
+
return prodReleaseTargets(model).length > 0 ? `\`mmi-cli devops release --resume --watch${summaryFile ? ` --announce-summary-file ${summaryFile}` : ""}\` announces it once they are green` : "a central deploy is proven only under --watch, so this release stays unannounced";
|
|
22856
|
+
}
|
|
22839
22857
|
async function completeMainRelease(deps, ctx, meta, deployModel, watch, options, tag, releaseSha, startBranch, preFold, tagProbe, branchHints, ledger, alignEarly) {
|
|
22840
22858
|
const resumeCommand = options.dev ? "mmi-cli devops release --dev --apply" : "mmi-cli devops release --apply";
|
|
22841
22859
|
const ledgerAnchors = { repo: ctx.repo, tag, tagSha: releaseSha };
|
|
@@ -22940,13 +22958,12 @@ ${recovery.note}`), recoveryInput);
|
|
|
22940
22958
|
throw partialTrainRecoveryError(e, recoveryInput);
|
|
22941
22959
|
}
|
|
22942
22960
|
await recordPhase(ledger, deps, ledgerAnchors, "promotion", phaseEntry({ state: "complete", sha: releaseSha, note: `immutable ${tag} pushed at ${releaseSha.slice(0, 12)}; origin/main fast-forwarded to it` }), { landed: "the immutable tag and the green required-check wall" });
|
|
22943
|
-
deps.warn?.("Release: Creating the
|
|
22961
|
+
deps.warn?.("Release: Creating the GitHub Release");
|
|
22962
|
+
const autoRunSince = (deps.now ?? Date.now)();
|
|
22944
22963
|
const releaseUrl = clean2(await deps.run("gh", ["release", "create", tag, "--target", "main", "--generate-notes", "--latest", "--repo", ctx.repo])) || void 0;
|
|
22945
22964
|
await verifyPublishedRelease(deps, ctx.repo, tag, "main", releaseSha);
|
|
22946
22965
|
await recordPhase(ledger, deps, ledgerAnchors, "githubRelease", phaseEntry({ state: "complete", sha: releaseSha, runUrl: releaseUrl, note: `verified GitHub Release ${tag} against ${releaseSha.slice(0, 12)}` }), { landed: "the immutable tag, the green required-check wall, and the origin/main fast-forward" });
|
|
22947
|
-
const announceNote = deps.announce ? (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note : void 0;
|
|
22948
22966
|
let alignment = alignEarly ? await alignEarly() : void 0;
|
|
22949
|
-
const autoRunSince = (deps.now ?? Date.now)();
|
|
22950
22967
|
const deployDispatch0 = await dispatchDeploy(deps, ctx, "main", "main", deployModel, watch, autoRunSince, releaseSha, "report", meta.publishDir);
|
|
22951
22968
|
const deployRunRepo = releaseRunRepoFor(deployModel, ctx.repo);
|
|
22952
22969
|
const failedReleaseRun = deployDispatch0.workflowRuns?.find((run) => run.conclusion === "failure");
|
|
@@ -22965,7 +22982,8 @@ ${recovery.note}`), recoveryInput);
|
|
|
22965
22982
|
}
|
|
22966
22983
|
);
|
|
22967
22984
|
const deployDispatch = await appendJervGatewayReleaseDeploy(deps, ctx.repo, tag, releaseSha, recoveredDeployDispatch);
|
|
22968
|
-
|
|
22985
|
+
const deployLeg = phaseEntry(deployPhaseInput(deployModel, deployDispatch, { releaseSha }));
|
|
22986
|
+
await recordPhase(ledger, deps, ledgerAnchors, "deploy", deployLeg, {
|
|
22969
22987
|
landed: "the immutable tag, the green required-check wall, the origin/main fast-forward, and the verified GitHub Release"
|
|
22970
22988
|
});
|
|
22971
22989
|
const publishDispatch0 = deployDispatch.deployStatus === "success" ? await dispatchPublishIfRequired(deps, ctx, meta, deployModel, "main", tag, watch, "report") : null;
|
|
@@ -22981,21 +22999,30 @@ ${recovery.note}`), recoveryInput);
|
|
|
22981
22999
|
if (!publishDispatch && deployDispatch.deployStatus !== "success" && meta.publishRequired && (deployModel === "tenant-container" || deployModel === "solo-container")) {
|
|
22982
23000
|
publishSkipNote = deployDispatch.deployStatus === "failure" ? "box deploy failed - redeploy the box before publishing" : "box deploy not confirmed (run with --watch) - publish after the box deploy lands";
|
|
22983
23001
|
}
|
|
22984
|
-
|
|
23002
|
+
const publishLeg = phaseEntry(publishPhaseInput(deployModel, deployDispatch, publishDispatch, meta.publishRequired === true, {
|
|
22985
23003
|
releaseSha,
|
|
22986
23004
|
repo: ctx.repo,
|
|
22987
23005
|
...publishSkipNote !== void 0 ? { skipPublishNote: publishSkipNote } : {}
|
|
22988
|
-
}))
|
|
23006
|
+
}));
|
|
23007
|
+
await recordPhase(ledger, deps, ledgerAnchors, "publish", publishLeg, {
|
|
22989
23008
|
landed: "the immutable tag, the green required-check wall, origin/main, the verified GitHub Release, and the dispatched deploy path"
|
|
22990
23009
|
});
|
|
22991
23010
|
let dispatch = appendPublishDispatch(deployDispatch, publishDispatch);
|
|
22992
23011
|
if (publishSkipNote) dispatch = { ...dispatch, note: `${dispatch.note}; tenant-publish.yml skipped (${publishSkipNote})` };
|
|
23012
|
+
const announcing = announceShippedRelease(
|
|
23013
|
+
deps,
|
|
23014
|
+
{ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile },
|
|
23015
|
+
deployModel,
|
|
23016
|
+
{ deploy: deployLeg, publish: publishLeg },
|
|
23017
|
+
releaseAnnounceDeferral(deployModel, options.announceSummaryFile)
|
|
23018
|
+
);
|
|
22993
23019
|
if (watch && alignment) {
|
|
22994
23020
|
alignment = {
|
|
22995
23021
|
dev: await awaitAlignmentLanded(deps, ctx, alignment.dev, "development"),
|
|
22996
23022
|
...alignment.rc ? { rc: await awaitAlignmentLanded(deps, ctx, alignment.rc, "rc") } : {}
|
|
22997
23023
|
};
|
|
22998
23024
|
}
|
|
23025
|
+
const announceNote = await announcing;
|
|
22999
23026
|
return { checks, releaseUrl, announceNote, dispatch, ledgerAnchors, ...alignment ? { alignment } : {} };
|
|
23000
23027
|
}
|
|
23001
23028
|
function resumeStateOf(status) {
|
|
@@ -23243,6 +23270,7 @@ async function runReleaseResumePipeline(deps, options, prepared) {
|
|
|
23243
23270
|
Live origin/tag/Release proof stays authoritative; nothing was written. Inspect ${ledger.path} before retrying.`
|
|
23244
23271
|
);
|
|
23245
23272
|
}
|
|
23273
|
+
const shippedBefore = shipLegsGreen(persisted?.phases.deploy, persisted?.phases.publish);
|
|
23246
23274
|
if (persisted?.lane && persisted.lane !== "release") {
|
|
23247
23275
|
throw new Error(`release --resume refused: the ${tag} ledger belongs to the ${persisted.lane} lane \u2014 finish it with ${ledgerLaneResumeCommand(persisted)} (#6068). Nothing was written.`);
|
|
23248
23276
|
}
|
|
@@ -23299,8 +23327,8 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23299
23327
|
deployStatus: historicalDeploy,
|
|
23300
23328
|
workflowRuns: historicalRows
|
|
23301
23329
|
});
|
|
23330
|
+
const phaseInputs = phaseInputsFromRunRows(deployModel, dispatch2.workflowRuns ?? historicalRows, tagSha, { repo: ctx.repo });
|
|
23302
23331
|
if (persisted) {
|
|
23303
|
-
const phaseInputs = phaseInputsFromRunRows(deployModel, dispatch2.workflowRuns ?? historicalRows, tagSha, { repo: ctx.repo });
|
|
23304
23332
|
if (persisted.phases.deploy.superseded !== true) {
|
|
23305
23333
|
await recordPhase(ledger, deps, anchors, "deploy", phaseEntry(phaseInputs.deploy), { strict: true, landed: "the verified GitHub Release and origin/main at the immutable tag SHA" });
|
|
23306
23334
|
}
|
|
@@ -23309,6 +23337,13 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23309
23337
|
await recordPhase(ledger, deps, anchors, "promotion", phaseEntry({ state: "complete", sha: tagSha, note: "re-verified live: origin/main contains the immutable tag SHA" }), { strict: true, landed: "nothing beyond the already-public release" });
|
|
23310
23338
|
}
|
|
23311
23339
|
if (isJervHubRepo(ctx.repo)) steps2.push(dispatch2.note);
|
|
23340
|
+
const announceNote2 = persisted && !shippedBefore && persisted.phases.deploy.superseded !== true && prodReleaseTargets(deployModel).length > 0 ? await announceShippedRelease(
|
|
23341
|
+
deps,
|
|
23342
|
+
{ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile },
|
|
23343
|
+
deployModel,
|
|
23344
|
+
phaseInputs,
|
|
23345
|
+
releaseAnnounceDeferral(deployModel, options.announceSummaryFile)
|
|
23346
|
+
) : void 0;
|
|
23312
23347
|
if (persisted) {
|
|
23313
23348
|
await recordPhase(ledger, deps, anchors, "alignment", phaseEntry(alignmentPhaseEntry(devRollForward2, rcAlignment2)), { strict: true, landed: "the released, verified, deploy-resolved release (alignment PRs reused/landed)" });
|
|
23314
23349
|
}
|
|
@@ -23326,6 +23361,7 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23326
23361
|
state: state2,
|
|
23327
23362
|
resumed: true,
|
|
23328
23363
|
steps: steps2,
|
|
23364
|
+
...announceNote2 ? { announceNote: announceNote2 } : {},
|
|
23329
23365
|
devRollForward: devRollForward2,
|
|
23330
23366
|
rcAlignment: rcAlignment2,
|
|
23331
23367
|
dispatch: dispatch2,
|
|
@@ -23382,16 +23418,15 @@ ${recovery.note}`), recoveryInput);
|
|
|
23382
23418
|
await runGitPush(deps, ["push", "origin", `${tagSha}:refs/heads/main`]);
|
|
23383
23419
|
steps.push(`pushed ${tagSha.slice(0, 12)} to origin/main`);
|
|
23384
23420
|
await recordPhase(ledger, deps, anchors, "promotion", phaseEntry({ state: "complete", sha: tagSha, note: `resumed: ${tagSha.slice(0, 12)} pushed to origin/main (tag preserved, never re-cut)` }), { strict: ledgerMode === "strict", landed: "the immutable tag and the re-proven required-check wall" });
|
|
23385
|
-
deps.warn?.("Release: Creating the
|
|
23421
|
+
deps.warn?.("Release: Creating the GitHub Release");
|
|
23422
|
+
const autoRunSince = (deps.now ?? Date.now)();
|
|
23386
23423
|
const releaseUrl = clean2(await deps.run("gh", ["release", "create", tag, "--target", "main", "--generate-notes", "--latest", "--repo", ctx.repo])) || void 0;
|
|
23387
23424
|
steps.push(`created the GitHub Release for ${tag}`);
|
|
23388
23425
|
await verifyPublishedRelease(deps, ctx.repo, tag, "main", tagSha);
|
|
23389
23426
|
steps.push("verified the Release published against the tagged commit");
|
|
23390
23427
|
await recordPhase(ledger, deps, anchors, "githubRelease", phaseEntry({ state: "complete", sha: tagSha, runUrl: releaseUrl, note: "verified the Release published against the tagged commit" }), { strict: ledgerMode === "strict", landed: "the immutable tag, the re-proven wall, and the origin/main push" });
|
|
23391
|
-
const announceNote = deps.announce ? (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note : void 0;
|
|
23392
23428
|
let devRollForward = await rollDevelopmentForward(deps, ctx, tag);
|
|
23393
23429
|
let rcAlignment = !directTrack && branchHints.hasRcBranch ? await alignRcForward(deps, ctx, tag) : void 0;
|
|
23394
|
-
const autoRunSince = (deps.now ?? Date.now)();
|
|
23395
23430
|
const deployDispatch0 = await dispatchDeploy(deps, ctx, "main", "main", deployModel, watch, autoRunSince, tagSha, "report", meta.publishDir);
|
|
23396
23431
|
const recoveredDeployDispatch = await recoverFailedDispatchPhase(
|
|
23397
23432
|
deps,
|
|
@@ -23408,7 +23443,8 @@ ${recovery.note}`), recoveryInput);
|
|
|
23408
23443
|
);
|
|
23409
23444
|
const deployDispatch = await appendJervGatewayReleaseDeploy(deps, ctx.repo, tag, tagSha, recoveredDeployDispatch);
|
|
23410
23445
|
steps.push(`dispatched the ${deployModel} deploy path`);
|
|
23411
|
-
|
|
23446
|
+
const deployLeg = phaseEntry(deployPhaseInput(deployModel, deployDispatch, { releaseSha: tagSha }));
|
|
23447
|
+
await recordPhase(ledger, deps, anchors, "deploy", deployLeg, {
|
|
23412
23448
|
strict: ledgerMode === "strict",
|
|
23413
23449
|
landed: "the immutable tag, the re-proven wall, the origin/main push, and the verified GitHub Release"
|
|
23414
23450
|
});
|
|
@@ -23421,15 +23457,24 @@ ${recovery.note}`), recoveryInput);
|
|
|
23421
23457
|
publishDispatch0,
|
|
23422
23458
|
{ repo: releaseRunRepoFor(deployModel, ctx.repo), sha: tagSha, watched: isCentralDispatchModel(deployModel), workflow: isCentralDispatchModel(deployModel) ? "tenant-publish.yml" : "publish.yml" }
|
|
23423
23459
|
) : null;
|
|
23424
|
-
|
|
23460
|
+
const publishLeg = phaseEntry(publishPhaseInput(deployModel, deployDispatch, publishDispatch, meta.publishRequired === true, { releaseSha: tagSha, repo: ctx.repo }));
|
|
23461
|
+
await recordPhase(ledger, deps, anchors, "publish", publishLeg, {
|
|
23425
23462
|
strict: ledgerMode === "strict",
|
|
23426
23463
|
landed: "the immutable tag, the re-proven wall, origin/main, the verified GitHub Release, and the dispatched deploy path"
|
|
23427
23464
|
});
|
|
23428
23465
|
const dispatch = appendPublishDispatch(deployDispatch, publishDispatch);
|
|
23466
|
+
const announcing = announceShippedRelease(
|
|
23467
|
+
deps,
|
|
23468
|
+
{ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile },
|
|
23469
|
+
deployModel,
|
|
23470
|
+
{ deploy: deployLeg, publish: publishLeg },
|
|
23471
|
+
releaseAnnounceDeferral(deployModel, options.announceSummaryFile)
|
|
23472
|
+
);
|
|
23429
23473
|
if (watch) {
|
|
23430
23474
|
devRollForward = await awaitAlignmentLanded(deps, ctx, devRollForward, "development");
|
|
23431
23475
|
if (rcAlignment) rcAlignment = await awaitAlignmentLanded(deps, ctx, rcAlignment, "rc");
|
|
23432
23476
|
}
|
|
23477
|
+
const announceNote = await announcing;
|
|
23433
23478
|
steps.push(`development roll-forward: ${devRollForward.status}`);
|
|
23434
23479
|
if (rcAlignment) steps.push(`rc alignment: ${rcAlignment.status}`);
|
|
23435
23480
|
const followUp = deriveTrainFollowUpStatus({
|
|
@@ -43473,15 +43518,11 @@ ${decision.note}`);
|
|
|
43473
43518
|
);
|
|
43474
43519
|
await recordHotfixPhase(ledger, anchors, "promotion", { state: "complete", sha: mergedSha, note: `immutable ${tag} pushed at ${mergedSha.slice(0, 12)}; origin/main already carries it (merged hotfix PR #${pr.number})` }, "the immutable tag and the green required-check wall");
|
|
43475
43520
|
let releaseNote;
|
|
43476
|
-
let announceNote;
|
|
43477
43521
|
if (releaseExists) {
|
|
43478
43522
|
releaseNote = `Release ${tag} already exists \u2014 resumed without recreating`;
|
|
43479
43523
|
} else {
|
|
43480
43524
|
await deps.run("gh", ["release", "create", tag, "--repo", ctx.repo, "--target", "main", "--generate-notes", "--latest"]);
|
|
43481
43525
|
releaseNote = `Release ${tag} created (target main)`;
|
|
43482
|
-
if (deps.announce) {
|
|
43483
|
-
announceNote = (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note;
|
|
43484
|
-
}
|
|
43485
43526
|
}
|
|
43486
43527
|
await recordHotfixPhase(ledger, anchors, "githubRelease", { state: "complete", sha: mergedSha, note: releaseNote }, "the immutable tag, the green wall, and origin/main");
|
|
43487
43528
|
const runs = [];
|
|
@@ -43554,6 +43595,13 @@ ${decision.note}`);
|
|
|
43554
43595
|
);
|
|
43555
43596
|
await recordHotfixPhase(ledger, anchors, "deploy", ledgerInputs.deploy, "the immutable tag, the green wall, origin/main, and the GitHub Release");
|
|
43556
43597
|
await recordHotfixPhase(ledger, anchors, "publish", ledgerInputs.publish, "the immutable tag, the green wall, origin/main, the GitHub Release, and the deploy path");
|
|
43598
|
+
const announceNote = releaseExists ? void 0 : await announceShippedRelease(
|
|
43599
|
+
deps,
|
|
43600
|
+
{ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile },
|
|
43601
|
+
deployModel,
|
|
43602
|
+
ledgerInputs,
|
|
43603
|
+
"a hotfix is announced only by the run that proves it shipped, so this one stays unannounced"
|
|
43604
|
+
);
|
|
43557
43605
|
let verifyNote;
|
|
43558
43606
|
if (deployModel === "hub-serverless") {
|
|
43559
43607
|
const previousRef = clean3(await deps.run("git", ["rev-parse", "--abbrev-ref", "HEAD"]));
|
package/package.json
CHANGED