@mutmutco/cli 4.3.54 → 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 +96 -29
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -4777,7 +4777,22 @@ async function isFastForward(run, ancestor, descendant) {
|
|
|
4777
4777
|
return false;
|
|
4778
4778
|
}
|
|
4779
4779
|
}
|
|
4780
|
-
async function
|
|
4780
|
+
async function checkedOutWorktrees(run) {
|
|
4781
|
+
const map = /* @__PURE__ */ new Map();
|
|
4782
|
+
let out = "";
|
|
4783
|
+
try {
|
|
4784
|
+
out = await run("git", ["worktree", "list", "--porcelain"]);
|
|
4785
|
+
} catch {
|
|
4786
|
+
return map;
|
|
4787
|
+
}
|
|
4788
|
+
let path2 = "";
|
|
4789
|
+
for (const line of out.split(/\r?\n/)) {
|
|
4790
|
+
if (line.startsWith("worktree ")) path2 = line.slice("worktree ".length);
|
|
4791
|
+
else if (line.startsWith("branch refs/heads/") && path2) map.set(line.slice("branch refs/heads/".length), path2);
|
|
4792
|
+
}
|
|
4793
|
+
return map;
|
|
4794
|
+
}
|
|
4795
|
+
async function syncOneBranch(run, branch, currentBranch2, worktrees, warn) {
|
|
4781
4796
|
const localSha = await revParse(run, `refs/heads/${branch}`);
|
|
4782
4797
|
if (!localSha) {
|
|
4783
4798
|
return { branch, status: "skipped", reason: "no-local-branch", note: `${branch}: no local branch \u2014 skipped` };
|
|
@@ -4794,13 +4809,16 @@ async function syncOneBranch(run, branch, currentBranch2, warn) {
|
|
|
4794
4809
|
warn?.(note);
|
|
4795
4810
|
return { branch, status: "skipped", reason: "diverged", note };
|
|
4796
4811
|
}
|
|
4812
|
+
const linked = branch === currentBranch2 ? void 0 : worktrees.get(branch);
|
|
4813
|
+
const inTree = linked ? ["-C", linked] : [];
|
|
4797
4814
|
try {
|
|
4798
|
-
if (branch === currentBranch2) {
|
|
4799
|
-
const porcelain = await run("git", ["status", "--porcelain"]);
|
|
4815
|
+
if (branch === currentBranch2 || linked) {
|
|
4816
|
+
const porcelain = await run("git", [...inTree, "status", "--porcelain"]);
|
|
4800
4817
|
if (porcelainHasBlockingChanges(porcelain)) {
|
|
4801
|
-
|
|
4818
|
+
const where = linked ? ` in worktree ${linked}` : "";
|
|
4819
|
+
return { branch, status: "skipped", reason: "current-dirty", note: `${branch}: checked out${where} with local changes \u2014 skipped (commit/stash, then rerun)` };
|
|
4802
4820
|
}
|
|
4803
|
-
await run("git", ["merge", "--ff-only", `origin/${branch}`]);
|
|
4821
|
+
await run("git", [...inTree, "merge", "--ff-only", `origin/${branch}`]);
|
|
4804
4822
|
} else {
|
|
4805
4823
|
await run("git", ["fetch", "origin", `${branch}:${branch}`]);
|
|
4806
4824
|
}
|
|
@@ -4828,9 +4846,10 @@ async function syncLocalTrainBranches(run, options = {}) {
|
|
|
4828
4846
|
} catch {
|
|
4829
4847
|
currentBranch2 = "";
|
|
4830
4848
|
}
|
|
4849
|
+
const worktrees = await checkedOutWorktrees(run);
|
|
4831
4850
|
const results = [];
|
|
4832
4851
|
for (const branch of branches) {
|
|
4833
|
-
results.push(await syncOneBranch(run, branch, currentBranch2, options.warn));
|
|
4852
|
+
results.push(await syncOneBranch(run, branch, currentBranch2, worktrees, options.warn));
|
|
4834
4853
|
}
|
|
4835
4854
|
return { branches: results, changed: results.some((r) => r.status === "synced") };
|
|
4836
4855
|
}
|
|
@@ -15858,10 +15877,10 @@ var rollout_plan_default = {
|
|
|
15858
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)."
|
|
15859
15878
|
},
|
|
15860
15879
|
baseline: {
|
|
15861
|
-
version: "4.3.
|
|
15862
|
-
tag: "v4.3.
|
|
15863
|
-
commit: "
|
|
15864
|
-
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"
|
|
15865
15884
|
},
|
|
15866
15885
|
exitCriterion: "fleet-n-of-n",
|
|
15867
15886
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15878,14 +15897,14 @@ var rollout_plan_default = {
|
|
|
15878
15897
|
repo: "mutmutco/mmi-hub",
|
|
15879
15898
|
role: "canary",
|
|
15880
15899
|
schedule: "train",
|
|
15881
|
-
v3Target: "v4.3.
|
|
15900
|
+
v3Target: "v4.3.56"
|
|
15882
15901
|
}
|
|
15883
15902
|
],
|
|
15884
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.",
|
|
15885
15904
|
rollback: {
|
|
15886
15905
|
independent: true,
|
|
15887
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15888
|
-
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)"
|
|
15889
15908
|
}
|
|
15890
15909
|
},
|
|
15891
15910
|
{
|
|
@@ -18897,6 +18916,21 @@ function prodReleaseTargets(model) {
|
|
|
18897
18916
|
if (model === "registry-publish") return [{ workflow: "publish.yml", event: "release" }];
|
|
18898
18917
|
return [];
|
|
18899
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
|
+
}
|
|
18900
18934
|
async function listTargetRun(deps, repo, target, headSha) {
|
|
18901
18935
|
let rows;
|
|
18902
18936
|
try {
|
|
@@ -22817,6 +22851,9 @@ async function recordRcandDeployLegs(ledger, deps, anchors, deployModel, d, opts
|
|
|
22817
22851
|
await recordPhase(ledger, deps, anchors, "alignment", phaseEntry({ state: "skipped", sha, note: "rcand aligns no branch \u2014 alignment rides the release" }), { ...opts, landed });
|
|
22818
22852
|
return dispatch;
|
|
22819
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
|
+
}
|
|
22820
22857
|
async function completeMainRelease(deps, ctx, meta, deployModel, watch, options, tag, releaseSha, startBranch, preFold, tagProbe, branchHints, ledger, alignEarly) {
|
|
22821
22858
|
const resumeCommand = options.dev ? "mmi-cli devops release --dev --apply" : "mmi-cli devops release --apply";
|
|
22822
22859
|
const ledgerAnchors = { repo: ctx.repo, tag, tagSha: releaseSha };
|
|
@@ -22921,13 +22958,12 @@ ${recovery.note}`), recoveryInput);
|
|
|
22921
22958
|
throw partialTrainRecoveryError(e, recoveryInput);
|
|
22922
22959
|
}
|
|
22923
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" });
|
|
22924
|
-
deps.warn?.("Release: Creating the
|
|
22961
|
+
deps.warn?.("Release: Creating the GitHub Release");
|
|
22962
|
+
const autoRunSince = (deps.now ?? Date.now)();
|
|
22925
22963
|
const releaseUrl = clean2(await deps.run("gh", ["release", "create", tag, "--target", "main", "--generate-notes", "--latest", "--repo", ctx.repo])) || void 0;
|
|
22926
22964
|
await verifyPublishedRelease(deps, ctx.repo, tag, "main", releaseSha);
|
|
22927
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" });
|
|
22928
|
-
const announceNote = deps.announce ? (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note : void 0;
|
|
22929
22966
|
let alignment = alignEarly ? await alignEarly() : void 0;
|
|
22930
|
-
const autoRunSince = (deps.now ?? Date.now)();
|
|
22931
22967
|
const deployDispatch0 = await dispatchDeploy(deps, ctx, "main", "main", deployModel, watch, autoRunSince, releaseSha, "report", meta.publishDir);
|
|
22932
22968
|
const deployRunRepo = releaseRunRepoFor(deployModel, ctx.repo);
|
|
22933
22969
|
const failedReleaseRun = deployDispatch0.workflowRuns?.find((run) => run.conclusion === "failure");
|
|
@@ -22946,7 +22982,8 @@ ${recovery.note}`), recoveryInput);
|
|
|
22946
22982
|
}
|
|
22947
22983
|
);
|
|
22948
22984
|
const deployDispatch = await appendJervGatewayReleaseDeploy(deps, ctx.repo, tag, releaseSha, recoveredDeployDispatch);
|
|
22949
|
-
|
|
22985
|
+
const deployLeg = phaseEntry(deployPhaseInput(deployModel, deployDispatch, { releaseSha }));
|
|
22986
|
+
await recordPhase(ledger, deps, ledgerAnchors, "deploy", deployLeg, {
|
|
22950
22987
|
landed: "the immutable tag, the green required-check wall, the origin/main fast-forward, and the verified GitHub Release"
|
|
22951
22988
|
});
|
|
22952
22989
|
const publishDispatch0 = deployDispatch.deployStatus === "success" ? await dispatchPublishIfRequired(deps, ctx, meta, deployModel, "main", tag, watch, "report") : null;
|
|
@@ -22962,21 +22999,30 @@ ${recovery.note}`), recoveryInput);
|
|
|
22962
22999
|
if (!publishDispatch && deployDispatch.deployStatus !== "success" && meta.publishRequired && (deployModel === "tenant-container" || deployModel === "solo-container")) {
|
|
22963
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";
|
|
22964
23001
|
}
|
|
22965
|
-
|
|
23002
|
+
const publishLeg = phaseEntry(publishPhaseInput(deployModel, deployDispatch, publishDispatch, meta.publishRequired === true, {
|
|
22966
23003
|
releaseSha,
|
|
22967
23004
|
repo: ctx.repo,
|
|
22968
23005
|
...publishSkipNote !== void 0 ? { skipPublishNote: publishSkipNote } : {}
|
|
22969
|
-
}))
|
|
23006
|
+
}));
|
|
23007
|
+
await recordPhase(ledger, deps, ledgerAnchors, "publish", publishLeg, {
|
|
22970
23008
|
landed: "the immutable tag, the green required-check wall, origin/main, the verified GitHub Release, and the dispatched deploy path"
|
|
22971
23009
|
});
|
|
22972
23010
|
let dispatch = appendPublishDispatch(deployDispatch, publishDispatch);
|
|
22973
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
|
+
);
|
|
22974
23019
|
if (watch && alignment) {
|
|
22975
23020
|
alignment = {
|
|
22976
23021
|
dev: await awaitAlignmentLanded(deps, ctx, alignment.dev, "development"),
|
|
22977
23022
|
...alignment.rc ? { rc: await awaitAlignmentLanded(deps, ctx, alignment.rc, "rc") } : {}
|
|
22978
23023
|
};
|
|
22979
23024
|
}
|
|
23025
|
+
const announceNote = await announcing;
|
|
22980
23026
|
return { checks, releaseUrl, announceNote, dispatch, ledgerAnchors, ...alignment ? { alignment } : {} };
|
|
22981
23027
|
}
|
|
22982
23028
|
function resumeStateOf(status) {
|
|
@@ -23224,6 +23270,7 @@ async function runReleaseResumePipeline(deps, options, prepared) {
|
|
|
23224
23270
|
Live origin/tag/Release proof stays authoritative; nothing was written. Inspect ${ledger.path} before retrying.`
|
|
23225
23271
|
);
|
|
23226
23272
|
}
|
|
23273
|
+
const shippedBefore = shipLegsGreen(persisted?.phases.deploy, persisted?.phases.publish);
|
|
23227
23274
|
if (persisted?.lane && persisted.lane !== "release") {
|
|
23228
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.`);
|
|
23229
23276
|
}
|
|
@@ -23280,8 +23327,8 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23280
23327
|
deployStatus: historicalDeploy,
|
|
23281
23328
|
workflowRuns: historicalRows
|
|
23282
23329
|
});
|
|
23330
|
+
const phaseInputs = phaseInputsFromRunRows(deployModel, dispatch2.workflowRuns ?? historicalRows, tagSha, { repo: ctx.repo });
|
|
23283
23331
|
if (persisted) {
|
|
23284
|
-
const phaseInputs = phaseInputsFromRunRows(deployModel, dispatch2.workflowRuns ?? historicalRows, tagSha, { repo: ctx.repo });
|
|
23285
23332
|
if (persisted.phases.deploy.superseded !== true) {
|
|
23286
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" });
|
|
23287
23334
|
}
|
|
@@ -23290,6 +23337,13 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23290
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" });
|
|
23291
23338
|
}
|
|
23292
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;
|
|
23293
23347
|
if (persisted) {
|
|
23294
23348
|
await recordPhase(ledger, deps, anchors, "alignment", phaseEntry(alignmentPhaseEntry(devRollForward2, rcAlignment2)), { strict: true, landed: "the released, verified, deploy-resolved release (alignment PRs reused/landed)" });
|
|
23295
23349
|
}
|
|
@@ -23307,6 +23361,7 @@ Nothing was written. Inspect ${ledger.path} (or clear it only after proving the
|
|
|
23307
23361
|
state: state2,
|
|
23308
23362
|
resumed: true,
|
|
23309
23363
|
steps: steps2,
|
|
23364
|
+
...announceNote2 ? { announceNote: announceNote2 } : {},
|
|
23310
23365
|
devRollForward: devRollForward2,
|
|
23311
23366
|
rcAlignment: rcAlignment2,
|
|
23312
23367
|
dispatch: dispatch2,
|
|
@@ -23363,16 +23418,15 @@ ${recovery.note}`), recoveryInput);
|
|
|
23363
23418
|
await runGitPush(deps, ["push", "origin", `${tagSha}:refs/heads/main`]);
|
|
23364
23419
|
steps.push(`pushed ${tagSha.slice(0, 12)} to origin/main`);
|
|
23365
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" });
|
|
23366
|
-
deps.warn?.("Release: Creating the
|
|
23421
|
+
deps.warn?.("Release: Creating the GitHub Release");
|
|
23422
|
+
const autoRunSince = (deps.now ?? Date.now)();
|
|
23367
23423
|
const releaseUrl = clean2(await deps.run("gh", ["release", "create", tag, "--target", "main", "--generate-notes", "--latest", "--repo", ctx.repo])) || void 0;
|
|
23368
23424
|
steps.push(`created the GitHub Release for ${tag}`);
|
|
23369
23425
|
await verifyPublishedRelease(deps, ctx.repo, tag, "main", tagSha);
|
|
23370
23426
|
steps.push("verified the Release published against the tagged commit");
|
|
23371
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" });
|
|
23372
|
-
const announceNote = deps.announce ? (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note : void 0;
|
|
23373
23428
|
let devRollForward = await rollDevelopmentForward(deps, ctx, tag);
|
|
23374
23429
|
let rcAlignment = !directTrack && branchHints.hasRcBranch ? await alignRcForward(deps, ctx, tag) : void 0;
|
|
23375
|
-
const autoRunSince = (deps.now ?? Date.now)();
|
|
23376
23430
|
const deployDispatch0 = await dispatchDeploy(deps, ctx, "main", "main", deployModel, watch, autoRunSince, tagSha, "report", meta.publishDir);
|
|
23377
23431
|
const recoveredDeployDispatch = await recoverFailedDispatchPhase(
|
|
23378
23432
|
deps,
|
|
@@ -23389,7 +23443,8 @@ ${recovery.note}`), recoveryInput);
|
|
|
23389
23443
|
);
|
|
23390
23444
|
const deployDispatch = await appendJervGatewayReleaseDeploy(deps, ctx.repo, tag, tagSha, recoveredDeployDispatch);
|
|
23391
23445
|
steps.push(`dispatched the ${deployModel} deploy path`);
|
|
23392
|
-
|
|
23446
|
+
const deployLeg = phaseEntry(deployPhaseInput(deployModel, deployDispatch, { releaseSha: tagSha }));
|
|
23447
|
+
await recordPhase(ledger, deps, anchors, "deploy", deployLeg, {
|
|
23393
23448
|
strict: ledgerMode === "strict",
|
|
23394
23449
|
landed: "the immutable tag, the re-proven wall, the origin/main push, and the verified GitHub Release"
|
|
23395
23450
|
});
|
|
@@ -23402,15 +23457,24 @@ ${recovery.note}`), recoveryInput);
|
|
|
23402
23457
|
publishDispatch0,
|
|
23403
23458
|
{ repo: releaseRunRepoFor(deployModel, ctx.repo), sha: tagSha, watched: isCentralDispatchModel(deployModel), workflow: isCentralDispatchModel(deployModel) ? "tenant-publish.yml" : "publish.yml" }
|
|
23404
23459
|
) : null;
|
|
23405
|
-
|
|
23460
|
+
const publishLeg = phaseEntry(publishPhaseInput(deployModel, deployDispatch, publishDispatch, meta.publishRequired === true, { releaseSha: tagSha, repo: ctx.repo }));
|
|
23461
|
+
await recordPhase(ledger, deps, anchors, "publish", publishLeg, {
|
|
23406
23462
|
strict: ledgerMode === "strict",
|
|
23407
23463
|
landed: "the immutable tag, the re-proven wall, origin/main, the verified GitHub Release, and the dispatched deploy path"
|
|
23408
23464
|
});
|
|
23409
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
|
+
);
|
|
23410
23473
|
if (watch) {
|
|
23411
23474
|
devRollForward = await awaitAlignmentLanded(deps, ctx, devRollForward, "development");
|
|
23412
23475
|
if (rcAlignment) rcAlignment = await awaitAlignmentLanded(deps, ctx, rcAlignment, "rc");
|
|
23413
23476
|
}
|
|
23477
|
+
const announceNote = await announcing;
|
|
23414
23478
|
steps.push(`development roll-forward: ${devRollForward.status}`);
|
|
23415
23479
|
if (rcAlignment) steps.push(`rc alignment: ${rcAlignment.status}`);
|
|
23416
23480
|
const followUp = deriveTrainFollowUpStatus({
|
|
@@ -43454,15 +43518,11 @@ ${decision.note}`);
|
|
|
43454
43518
|
);
|
|
43455
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");
|
|
43456
43520
|
let releaseNote;
|
|
43457
|
-
let announceNote;
|
|
43458
43521
|
if (releaseExists) {
|
|
43459
43522
|
releaseNote = `Release ${tag} already exists \u2014 resumed without recreating`;
|
|
43460
43523
|
} else {
|
|
43461
43524
|
await deps.run("gh", ["release", "create", tag, "--repo", ctx.repo, "--target", "main", "--generate-notes", "--latest"]);
|
|
43462
43525
|
releaseNote = `Release ${tag} created (target main)`;
|
|
43463
|
-
if (deps.announce) {
|
|
43464
|
-
announceNote = (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note;
|
|
43465
|
-
}
|
|
43466
43526
|
}
|
|
43467
43527
|
await recordHotfixPhase(ledger, anchors, "githubRelease", { state: "complete", sha: mergedSha, note: releaseNote }, "the immutable tag, the green wall, and origin/main");
|
|
43468
43528
|
const runs = [];
|
|
@@ -43535,6 +43595,13 @@ ${decision.note}`);
|
|
|
43535
43595
|
);
|
|
43536
43596
|
await recordHotfixPhase(ledger, anchors, "deploy", ledgerInputs.deploy, "the immutable tag, the green wall, origin/main, and the GitHub Release");
|
|
43537
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
|
+
);
|
|
43538
43605
|
let verifyNote;
|
|
43539
43606
|
if (deployModel === "hub-serverless") {
|
|
43540
43607
|
const previousRef = clean3(await deps.run("git", ["rev-parse", "--abbrev-ref", "HEAD"]));
|
package/package.json
CHANGED