@mutmutco/cli 4.3.55 → 4.3.57
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 +85 -31
- 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.57",
|
|
15881
|
+
tag: "v4.3.57",
|
|
15882
|
+
commit: "b988569fdfe3",
|
|
15883
|
+
npm: "@mutmutco/cli@4.3.57"
|
|
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.57"
|
|
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.57 and redeploy the Hub Lambda from tag v4.3.57 (b988569fdfe3); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15907
|
+
v3Target: "v4.3.57 (@mutmutco/cli@4.3.57, tag commit b988569fdfe3 \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({
|
|
@@ -26494,6 +26539,11 @@ function rcandVersionStep(targets) {
|
|
|
26494
26539
|
function trainPlan(command, options = {}) {
|
|
26495
26540
|
const isHub = options.repo?.toLowerCase() === "mutmutco/mmi-hub";
|
|
26496
26541
|
const isDirect = options.releaseTrack === "direct" || options.releaseTrack === void 0 && isHub;
|
|
26542
|
+
const authority = {
|
|
26543
|
+
label: isHub ? "verify Hub master-admin train authority" : "verify project-admin or master train authority on this repo",
|
|
26544
|
+
command: "mmi-cli oracle org access role <owner/repo> --json",
|
|
26545
|
+
gated: true
|
|
26546
|
+
};
|
|
26497
26547
|
if (command === "rcand") {
|
|
26498
26548
|
if (isDirect) {
|
|
26499
26549
|
return [
|
|
@@ -26501,7 +26551,7 @@ function trainPlan(command, options = {}) {
|
|
|
26501
26551
|
];
|
|
26502
26552
|
}
|
|
26503
26553
|
return [
|
|
26504
|
-
|
|
26554
|
+
authority,
|
|
26505
26555
|
{ label: "verify current branch is development", gated: true },
|
|
26506
26556
|
rcandVersionStep(options),
|
|
26507
26557
|
{ label: "verify registry META for this project", command: "mmi-cli oracle org project get <owner/repo>", gated: true },
|
|
@@ -26514,7 +26564,7 @@ function trainPlan(command, options = {}) {
|
|
|
26514
26564
|
if (command === "release") {
|
|
26515
26565
|
if (isDirect) {
|
|
26516
26566
|
return [
|
|
26517
|
-
|
|
26567
|
+
authority,
|
|
26518
26568
|
{ label: "verify current branch is development", gated: true },
|
|
26519
26569
|
{ label: "verify registry META for this project", command: "mmi-cli oracle org project get <owner/repo>", gated: true },
|
|
26520
26570
|
{ label: "preflight required main secret names", command: "mmi-cli vault secrets preflight --stage main --repo <owner/repo>", gated: true },
|
|
@@ -26529,7 +26579,7 @@ function trainPlan(command, options = {}) {
|
|
|
26529
26579
|
}
|
|
26530
26580
|
if (options.dev) {
|
|
26531
26581
|
return [
|
|
26532
|
-
|
|
26582
|
+
authority,
|
|
26533
26583
|
{ label: "verify current branch is development", gated: true },
|
|
26534
26584
|
{ label: "guard: refuse if origin/rc carries content not in development (a dev -> main release would drop it)", command: "git rev-list --count --right-only --cherry-pick --no-merges origin/development...origin/rc", gated: true },
|
|
26535
26585
|
{ label: "verify registry META for this project", command: "mmi-cli oracle org project get <owner/repo>", gated: true },
|
|
@@ -26545,7 +26595,7 @@ function trainPlan(command, options = {}) {
|
|
|
26545
26595
|
];
|
|
26546
26596
|
}
|
|
26547
26597
|
return [
|
|
26548
|
-
|
|
26598
|
+
authority,
|
|
26549
26599
|
{ label: "verify current branch is rc", gated: true },
|
|
26550
26600
|
{ label: "verify registry META for this project", command: "mmi-cli oracle org project get <owner/repo>", gated: true },
|
|
26551
26601
|
{ label: "preflight required main secret names", command: "mmi-cli vault secrets preflight --stage main --repo <owner/repo>", gated: true },
|
|
@@ -26560,6 +26610,7 @@ function trainPlan(command, options = {}) {
|
|
|
26560
26610
|
];
|
|
26561
26611
|
}
|
|
26562
26612
|
return [
|
|
26613
|
+
authority,
|
|
26563
26614
|
{ label: "verify the fix is merged on development (the only hotfix origin)", gated: true },
|
|
26564
26615
|
// #6068: hotfix start/release run the SAME shared preflight as release/rcand, before any git mutation.
|
|
26565
26616
|
{ label: "verify registry META for this project", command: "mmi-cli oracle org project get <owner/repo>", gated: true },
|
|
@@ -30069,7 +30120,7 @@ function buildSetDeployPatch(_slug, input) {
|
|
|
30069
30120
|
}
|
|
30070
30121
|
var DEPLOY_STAGE_BRANCH = { dev: "development", rc: "rc", main: "main" };
|
|
30071
30122
|
function filelessTransitionGuide(repo, stage) {
|
|
30072
|
-
const authority =
|
|
30123
|
+
const authority = "Authority: a project-admin may complete this for their own repo; master may also do it.";
|
|
30073
30124
|
return [
|
|
30074
30125
|
`Fileless transition for ${repo} (${stage}):`,
|
|
30075
30126
|
` ${authority}`,
|
|
@@ -43473,15 +43524,11 @@ ${decision.note}`);
|
|
|
43473
43524
|
);
|
|
43474
43525
|
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
43526
|
let releaseNote;
|
|
43476
|
-
let announceNote;
|
|
43477
43527
|
if (releaseExists) {
|
|
43478
43528
|
releaseNote = `Release ${tag} already exists \u2014 resumed without recreating`;
|
|
43479
43529
|
} else {
|
|
43480
43530
|
await deps.run("gh", ["release", "create", tag, "--repo", ctx.repo, "--target", "main", "--generate-notes", "--latest"]);
|
|
43481
43531
|
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
43532
|
}
|
|
43486
43533
|
await recordHotfixPhase(ledger, anchors, "githubRelease", { state: "complete", sha: mergedSha, note: releaseNote }, "the immutable tag, the green wall, and origin/main");
|
|
43487
43534
|
const runs = [];
|
|
@@ -43554,6 +43601,13 @@ ${decision.note}`);
|
|
|
43554
43601
|
);
|
|
43555
43602
|
await recordHotfixPhase(ledger, anchors, "deploy", ledgerInputs.deploy, "the immutable tag, the green wall, origin/main, and the GitHub Release");
|
|
43556
43603
|
await recordHotfixPhase(ledger, anchors, "publish", ledgerInputs.publish, "the immutable tag, the green wall, origin/main, the GitHub Release, and the deploy path");
|
|
43604
|
+
const announceNote = releaseExists ? void 0 : await announceShippedRelease(
|
|
43605
|
+
deps,
|
|
43606
|
+
{ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile },
|
|
43607
|
+
deployModel,
|
|
43608
|
+
ledgerInputs,
|
|
43609
|
+
"a hotfix is announced only by the run that proves it shipped, so this one stays unannounced"
|
|
43610
|
+
);
|
|
43557
43611
|
let verifyNote;
|
|
43558
43612
|
if (deployModel === "hub-serverless") {
|
|
43559
43613
|
const previousRef = clean3(await deps.run("git", ["rev-parse", "--abbrev-ref", "HEAD"]));
|
|
@@ -44525,7 +44579,7 @@ function registerTrainCommandsAndInventory(program3) {
|
|
|
44525
44579
|
}
|
|
44526
44580
|
function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
44527
44581
|
for (const commandName of ["rcand", "release"]) {
|
|
44528
|
-
const trainCmd = program3.command(commandName).description(`plan ${commandName} train operations; mutations require explicit
|
|
44582
|
+
const trainCmd = program3.command(commandName).description(`plan ${commandName} train operations; mutations require explicit project-admin or master approval`).option("--json", "machine-readable output").option("--watch", "block on the deploy/publish workflow runs and report their outcomes").option("--apply", "execute the guarded repo-authorized train after explicit approval (Hub: master only)").option("--resume", commandName === "rcand" ? "finish a candidate whose immutable public rc tag passed policy but origin/rc was not pushed (#3881)" : "finish a partial release or its protected post-release alignment without re-cutting, republishing, or redeploying (#3851/#3885)").option("--out <path>", "write the terminal result (--apply, --resume, --abort, --retry-publish) to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5983/#6068)");
|
|
44529
44583
|
const RELEASE_ONLY_FLAGS = [
|
|
44530
44584
|
{ flags: "--announce-summary-file <path>", description: "agent-curated 3-6 line release Slack summary; required for a new MMI-Hub --apply (#883/#3901) and for a product repo whose registry META sets `releaseChannel` (#6523), in its `releaseLanguage`; nothing is posted to a project channel without it" },
|
|
44531
44585
|
{ flags: "--ack <shas>", description: "comma-separated dev shas a human verified are in the candidate, overriding the hotfix-coverage guard for a conflicted port whose -x trailer was lost (#958)" },
|
|
@@ -45866,8 +45920,8 @@ ${filelessTransitionGuide(target, o.stage)}`
|
|
|
45866
45920
|
}
|
|
45867
45921
|
return reportWrite("org project set-deploy", res);
|
|
45868
45922
|
});
|
|
45869
|
-
var projectTenantTasks = project.command("tenant-tasks").description("project-admin self-declare of tenant tasks for your own repo
|
|
45870
|
-
projectTenantTasks.command("declare <name>").description(
|
|
45923
|
+
var projectTenantTasks = project.command("tenant-tasks").description("project-admin self-declare of tenant tasks for every stage of your own repo \u2014 new-task-only; editing an existing task stays master-only (`org project set --var tenantTasks=...`)");
|
|
45924
|
+
projectTenantTasks.command("declare <name>").description("register a NEW tenant task \u2014 becomes runnable via `runtime tenant control \u2026 run-task` on its declared dev/rc/main stages. Body shape {service,command[],stages[],timeoutSeconds?,artifact?}; required artifact tasks must carry {artifact} in the command argv.").option("--service <name>", "service in the tenant runtime the task runs in (required unless --var carries it)").option("--command <argv...>", "task command as argv (repeatable; required unless --var carries it)").option("--stages <list>", "comma-separated dev,rc,main stages this task may run on (required unless --var carries it)").option("--timeout-seconds <n>", "optional wall-clock ceiling 1..3600").option("--artifact <none|required>", "artifact contract (default none; required tasks must contain {artifact} in argv)").option("--var <json>", "full task object {service,command[],stages[],timeoutSeconds?,artifact?} \u2014 use instead of the individual flags").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--json", "machine-readable output").action(async (name, o) => {
|
|
45871
45925
|
const cfg = await loadConfig();
|
|
45872
45926
|
let target;
|
|
45873
45927
|
try {
|
package/package.json
CHANGED