@mutmutco/cli 3.107.1 → 3.107.3
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 -11
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -11982,6 +11982,7 @@ async function runPluginHeal(surface = detectSurface(process.env)) {
|
|
|
11982
11982
|
}
|
|
11983
11983
|
|
|
11984
11984
|
// src/train-apply.ts
|
|
11985
|
+
var TRAIN_BUMP_INTENTS = ["major", "minor", "patch"];
|
|
11985
11986
|
function isCentralDispatchModel(model) {
|
|
11986
11987
|
return model === "tenant-container" || model === "solo-container" || model === "static-cdn";
|
|
11987
11988
|
}
|
|
@@ -13981,15 +13982,62 @@ async function runTrainApplyPipeline(mode, input) {
|
|
|
13981
13982
|
environments
|
|
13982
13983
|
};
|
|
13983
13984
|
}
|
|
13985
|
+
async function latestLocalReleaseTag(deps) {
|
|
13986
|
+
const tags = clean2(await deps.run("git", ["tag", "--list", "v*"])).split("\n");
|
|
13987
|
+
let latest = { major: 0, minor: 0, patch: 0 };
|
|
13988
|
+
for (const tag of tags) {
|
|
13989
|
+
const m = /^v(\d+)\.(\d+)\.(\d+)$/.exec(tag.trim());
|
|
13990
|
+
if (!m) continue;
|
|
13991
|
+
const v = { major: +m[1], minor: +m[2], patch: +m[3] };
|
|
13992
|
+
const delta = v.major - latest.major || v.minor - latest.minor || v.patch - latest.patch;
|
|
13993
|
+
if (delta > 0) latest = v;
|
|
13994
|
+
}
|
|
13995
|
+
return latest;
|
|
13996
|
+
}
|
|
13997
|
+
async function resolveTrainBumpIntent(deps, env = process.env) {
|
|
13998
|
+
const explicitIntent = (env.MMI_BUMP_INTENT ?? "").trim();
|
|
13999
|
+
if (explicitIntent) {
|
|
14000
|
+
if (!TRAIN_BUMP_INTENTS.includes(explicitIntent)) {
|
|
14001
|
+
throw new Error("MMI_BUMP_INTENT must be one of major|minor|patch");
|
|
14002
|
+
}
|
|
14003
|
+
return explicitIntent;
|
|
14004
|
+
}
|
|
14005
|
+
const explicitVersion = (env.MMI_RELEASE_VERSION ?? "").trim();
|
|
14006
|
+
if (explicitVersion) {
|
|
14007
|
+
const m = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(explicitVersion);
|
|
14008
|
+
if (!m) throw new Error(`MMI_RELEASE_VERSION must be X.Y.Z (got ${explicitVersion})`);
|
|
14009
|
+
const explicit = { major: +m[1], minor: +m[2], patch: +m[3] };
|
|
14010
|
+
const latest = await latestLocalReleaseTag(deps);
|
|
14011
|
+
const delta = explicit.major - latest.major || explicit.minor - latest.minor || explicit.patch - latest.patch;
|
|
14012
|
+
if (delta <= 0) {
|
|
14013
|
+
throw new Error(
|
|
14014
|
+
`MMI_RELEASE_VERSION ${explicitVersion} must be ahead of the latest release v${latest.major}.${latest.minor}.${latest.patch}`
|
|
14015
|
+
);
|
|
14016
|
+
}
|
|
14017
|
+
return explicit.major > latest.major ? "major" : explicit.minor > latest.minor ? "minor" : "patch";
|
|
14018
|
+
}
|
|
14019
|
+
try {
|
|
14020
|
+
return requireValue(
|
|
14021
|
+
clean2(await deps.run("node", ["scripts/next-version.mjs", "intent"])),
|
|
14022
|
+
"release bump intent"
|
|
14023
|
+
);
|
|
14024
|
+
} catch (e) {
|
|
14025
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
14026
|
+
const usage = /usage: next-version\.mjs <([^>]+)>/.exec(message);
|
|
14027
|
+
if (usage && !usage[1].split("|").includes("intent")) {
|
|
14028
|
+
throw new Error(
|
|
14029
|
+
`release bump intent: this repo's seeded scripts/next-version.mjs predates the \`intent\` verb (its usage lists <${usage[1]}>), so unset-intent derivation cannot run here. Declare the intent explicitly and rerun \u2014 MMI_BUMP_INTENT=major|minor|patch (or MMI_RELEASE_VERSION=X.Y.Z for an exact target); the train then resolves it in the CLI without shelling this script. The durable fix is refreshing the seeded script from the Hub via seed propagation.`
|
|
14030
|
+
);
|
|
14031
|
+
}
|
|
14032
|
+
throw e;
|
|
14033
|
+
}
|
|
14034
|
+
}
|
|
13984
14035
|
async function runTrainApply(command, deps, options = {}) {
|
|
13985
14036
|
const watch = options.watch ?? false;
|
|
13986
14037
|
const ctx = await buildTrainApplyContext(deps);
|
|
13987
14038
|
await requireCleanTree(deps);
|
|
13988
14039
|
await runGitRemoteRead(deps, ["fetch", "origin"]);
|
|
13989
|
-
const bumpIntent =
|
|
13990
|
-
clean2(await deps.run("node", ["scripts/next-version.mjs", "intent"])),
|
|
13991
|
-
"release bump intent"
|
|
13992
|
-
);
|
|
14040
|
+
const bumpIntent = await resolveTrainBumpIntent(deps);
|
|
13993
14041
|
const meta = requireProjectMetaForTrain(await loadProjectMeta(deps, ctx), ctx.repo);
|
|
13994
14042
|
const branchHints = await loadReleaseTrackBranchHints(deps);
|
|
13995
14043
|
const directTrack = isHubControlRepo(ctx.repo) || resolveReleaseTrack(meta, branchHints) === "direct";
|
|
@@ -22447,7 +22495,7 @@ async function runHotfixStart(deps, options) {
|
|
|
22447
22495
|
if (!sources.some((s) => s.sha === resolved.sha)) sources.push(resolved);
|
|
22448
22496
|
}
|
|
22449
22497
|
const label = sources.map((s) => s.label).join(", ");
|
|
22450
|
-
const foldPaths =
|
|
22498
|
+
const foldPaths = await resolveFoldPaths(deps, deployModel);
|
|
22451
22499
|
const pickTolerated = deployModel === "hub-serverless" || deployModel === "registry-publish" ? [...foldPaths, ...HOTFIX_SKILL_TOLERATED_ROOTS] : foldPaths;
|
|
22452
22500
|
if (deployModel === "hub-serverless") {
|
|
22453
22501
|
await deps.run("node", ["scripts/release-distribution.mjs", "verify-deps"]);
|
|
@@ -22491,15 +22539,15 @@ async function runHotfixStart(deps, options) {
|
|
|
22491
22539
|
} else {
|
|
22492
22540
|
notes.push("distribution prepare produced no changes \u2014 nothing extra committed");
|
|
22493
22541
|
}
|
|
22494
|
-
} else if (
|
|
22542
|
+
} else if (foldPaths.length > 0) {
|
|
22495
22543
|
const foldNote = await foldReleaseVersion(deps, deployModel, tag, foldPaths);
|
|
22496
22544
|
notes.push(foldNote);
|
|
22497
22545
|
} else {
|
|
22498
|
-
notes.push(`
|
|
22546
|
+
notes.push(`version fold skipped (deployModel=${deployModel} carries no version manifest \u2014 the tag is the version)`);
|
|
22499
22547
|
}
|
|
22500
22548
|
await deps.run("git", ["push", "-u", "origin", branch]);
|
|
22501
22549
|
}
|
|
22502
|
-
const bumpNote = deployModel === "hub-serverless" ? " with the locked distribution bump" :
|
|
22550
|
+
const bumpNote = deployModel === "hub-serverless" ? " with the locked distribution bump" : foldPaths.length > 0 ? " with the package version bump" : "";
|
|
22503
22551
|
const prUrl = clean3(await deps.run("gh", [
|
|
22504
22552
|
"pr",
|
|
22505
22553
|
"create",
|
|
@@ -22562,6 +22610,15 @@ async function watchReleaseRun(deps, ctx, workflow, sha) {
|
|
|
22562
22610
|
function devFoldBranch(tag) {
|
|
22563
22611
|
return `hotfix-fold/${tag}`;
|
|
22564
22612
|
}
|
|
22613
|
+
function devFoldScratchBranch(tag, deps) {
|
|
22614
|
+
return `${devFoldBranch(tag)}--port-${(deps.now ?? Date.now)().toString(36)}`;
|
|
22615
|
+
}
|
|
22616
|
+
async function reapFoldScratchBranches(deps) {
|
|
22617
|
+
const listed = await deps.run("git", ["branch", "--list", "hotfix-fold/*--port-*", "--format=%(refname:short)"]).catch(() => "");
|
|
22618
|
+
for (const name of listed.split("\n").map((s) => s.trim()).filter(Boolean)) {
|
|
22619
|
+
await deps.run("git", ["branch", "-D", name]).catch(() => void 0);
|
|
22620
|
+
}
|
|
22621
|
+
}
|
|
22565
22622
|
async function portFoldToDevelopment(deps, ctx, deployModel, tag) {
|
|
22566
22623
|
const foldPaths = deployModel === "hub-serverless" || deployModel === "registry-publish" ? await resolveFoldPaths(deps, deployModel) : [];
|
|
22567
22624
|
if (foldPaths.length === 0) return `fold port skipped (deployModel=${deployModel} folds no version manifest)`;
|
|
@@ -22585,14 +22642,16 @@ async function portFoldToDevelopment(deps, ctx, deployModel, tag) {
|
|
|
22585
22642
|
const existing = JSON.parse(listed || "[]").filter((r) => r.state === "OPEN" || r.state === "MERGED").sort((a, b) => (b.number ?? 0) - (a.number ?? 0))[0];
|
|
22586
22643
|
if (existing) return `development fold PR #${existing.number} for ${tag} is ${existing.state} \u2014 reused`;
|
|
22587
22644
|
const previousRef = clean3(await deps.run("git", ["rev-parse", "--abbrev-ref", "HEAD"]));
|
|
22645
|
+
await reapFoldScratchBranches(deps);
|
|
22646
|
+
const scratch = devFoldScratchBranch(tag, deps);
|
|
22588
22647
|
try {
|
|
22589
22648
|
await deps.run("git", ["fetch", "origin", "development"]);
|
|
22590
|
-
await deps.run("git", ["checkout", "-B",
|
|
22649
|
+
await deps.run("git", ["checkout", "-B", scratch, "origin/development"]);
|
|
22591
22650
|
const durableSource = clean3(await deps.run("git", ["merge-base", "HEAD", "origin/development"]));
|
|
22592
22651
|
const foldNote = await foldReleaseVersion(deps, deployModel, tag, foldPaths, durableSource, false);
|
|
22593
22652
|
const committed = clean3(await deps.run("git", ["rev-list", "--count", "origin/development..HEAD"]));
|
|
22594
22653
|
if (committed === "0") return `development already carries ${tag} \u2014 no fold PR needed (${foldNote})`;
|
|
22595
|
-
await deps.run("git", ["push", "
|
|
22654
|
+
await deps.run("git", ["push", "origin", `${scratch}:refs/heads/${branch}`]);
|
|
22596
22655
|
const prUrl = clean3(await deps.run("gh", [
|
|
22597
22656
|
"pr",
|
|
22598
22657
|
"create",
|
|
@@ -22612,6 +22671,7 @@ Generated by \`mmi-cli hotfix release\` \u2014 no main-parented commit is merged
|
|
|
22612
22671
|
return `opened development fold PR ${prUrl} (${foldNote})`;
|
|
22613
22672
|
} finally {
|
|
22614
22673
|
if (previousRef && previousRef !== "HEAD") await deps.run("git", ["checkout", previousRef]).catch(() => void 0);
|
|
22674
|
+
await deps.run("git", ["branch", "-D", scratch]).catch(() => void 0);
|
|
22615
22675
|
}
|
|
22616
22676
|
}
|
|
22617
22677
|
async function runHotfixRelease(deps, versionInput, options = {}) {
|
|
@@ -22743,7 +22803,7 @@ async function runHotfixRelease(deps, versionInput, options = {}) {
|
|
|
22743
22803
|
try {
|
|
22744
22804
|
foldNote = await portFoldToDevelopment(deps, ctx, deployModel, tag);
|
|
22745
22805
|
} catch (e) {
|
|
22746
|
-
foldNote = `development fold port FAILED: ${e.message ?? e} \u2014 the release stands; port it by hand: git checkout -B ${devFoldBranch(tag)} origin/development && node scripts/release-distribution.mjs prepare ${version}, then open a development-base PR`;
|
|
22806
|
+
foldNote = `development fold port FAILED: ${e.message ?? e} \u2014 the release stands; port it by hand on a fresh branch: git checkout -B ${devFoldBranch(tag)}-manual origin/development && node scripts/release-distribution.mjs prepare ${version}, then push it as the canonical head (git push origin ${devFoldBranch(tag)}-manual:refs/heads/${devFoldBranch(tag)}) and open a development-base PR`;
|
|
22747
22807
|
}
|
|
22748
22808
|
return {
|
|
22749
22809
|
...ctx,
|
package/package.json
CHANGED