@mutmutco/cli 2.28.0 → 2.28.1
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 +55 -12
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -7597,6 +7597,51 @@ async function discoverRequiredCheckContexts(deps, ctx, branch) {
|
|
|
7597
7597
|
}
|
|
7598
7598
|
return [...contexts];
|
|
7599
7599
|
}
|
|
7600
|
+
async function findOpenAlignmentPr(deps, ctx) {
|
|
7601
|
+
const out = clean(await deps.run("gh", ["pr", "list", "--repo", ctx.repo, "--base", "development", "--head", "main", "--state", "open", "--json", "number,url"]));
|
|
7602
|
+
if (!out) return void 0;
|
|
7603
|
+
const rows = JSON.parse(out);
|
|
7604
|
+
const row = rows.find((r) => typeof r.number === "number" && typeof r.url === "string");
|
|
7605
|
+
return row ? { number: row.number, url: row.url } : void 0;
|
|
7606
|
+
}
|
|
7607
|
+
function parsePrNumber(url) {
|
|
7608
|
+
const n = Number.parseInt(url.split("/").pop() ?? "", 10);
|
|
7609
|
+
return Number.isFinite(n) ? n : void 0;
|
|
7610
|
+
}
|
|
7611
|
+
async function rollDevelopmentForward(deps, ctx, tag) {
|
|
7612
|
+
const required = await discoverRequiredCheckContexts(deps, ctx, "development");
|
|
7613
|
+
if (required.length === 0) {
|
|
7614
|
+
await deps.run("git", ["checkout", "development"]);
|
|
7615
|
+
await deps.run("git", ["pull", "--ff-only", "origin", "development"]);
|
|
7616
|
+
await deps.run("git", ["merge", "main", "--no-edit"]);
|
|
7617
|
+
await deps.run("git", ["push", "origin", "development"]);
|
|
7618
|
+
return { status: "pushed", note: "development rolled forward to the released main (development has no required checks)" };
|
|
7619
|
+
}
|
|
7620
|
+
const existing = await findOpenAlignmentPr(deps, ctx);
|
|
7621
|
+
if (existing) {
|
|
7622
|
+
return {
|
|
7623
|
+
status: "pr-pending",
|
|
7624
|
+
prNumber: existing.number,
|
|
7625
|
+
prUrl: existing.url,
|
|
7626
|
+
note: `alignment PR already open: ${existing.url} \u2014 land it with \`gh pr merge ${existing.number} --merge\``
|
|
7627
|
+
};
|
|
7628
|
+
}
|
|
7629
|
+
const ahead = clean(await deps.run("git", ["rev-list", "--count", "origin/development..main"]));
|
|
7630
|
+
if (ahead === "0") {
|
|
7631
|
+
return { status: "aligned", note: "development already contains the released main; nothing to roll forward" };
|
|
7632
|
+
}
|
|
7633
|
+
const body = `Carries the ${tag} release (including the version fold) from \`main\` back to \`development\`.
|
|
7634
|
+
|
|
7635
|
+
\`development\` requires status checks, so the release train opens this alignment PR instead of a direct push of the un-checked merge commit (#1143). Land it with a **true merge** (\`gh pr merge --merge\`, not squash) so the merge parentage survives and the misalignment guard stays satisfied.`;
|
|
7636
|
+
const url = clean(await deps.run("gh", ["pr", "create", "--repo", ctx.repo, "--base", "development", "--head", "main", "--title", `chore(release): align development to ${tag}`, "--body", body]));
|
|
7637
|
+
const number = parsePrNumber(url);
|
|
7638
|
+
return {
|
|
7639
|
+
status: "pr-pending",
|
|
7640
|
+
prNumber: number,
|
|
7641
|
+
prUrl: url || void 0,
|
|
7642
|
+
note: `development requires checks (${required.join(", ")}); opened alignment PR ${url || "(url unavailable)"} \u2014 land it with \`gh pr merge ${number ?? "<number>"} --merge\``
|
|
7643
|
+
};
|
|
7644
|
+
}
|
|
7600
7645
|
function resolveContextState(context, checkRuns, statuses) {
|
|
7601
7646
|
let sawFailure = false;
|
|
7602
7647
|
for (const r of checkRuns) {
|
|
@@ -7855,10 +7900,7 @@ async function runTrainApply(command, deps, options = {}) {
|
|
|
7855
7900
|
const announceNote2 = deps.announce ? (await deps.announce({ repo: ctx.repo, tag: tag2, summaryFile: options.announceSummaryFile })).note : void 0;
|
|
7856
7901
|
const autoRunSince2 = (deps.now ?? Date.now)();
|
|
7857
7902
|
const d2 = await dispatchDeploy(deps, ctx, "main", "main", deployModel2, watch, autoRunSince2, releaseSha2, "report");
|
|
7858
|
-
await deps
|
|
7859
|
-
await deps.run("git", ["pull", "--ff-only", "origin", "development"]);
|
|
7860
|
-
await deps.run("git", ["merge", "main", "--no-edit"]);
|
|
7861
|
-
await deps.run("git", ["push", "origin", "development"]);
|
|
7903
|
+
const devRollForward2 = await rollDevelopmentForward(deps, ctx, tag2);
|
|
7862
7904
|
return {
|
|
7863
7905
|
...ctx,
|
|
7864
7906
|
command,
|
|
@@ -7876,6 +7918,7 @@ async function runTrainApply(command, deps, options = {}) {
|
|
|
7876
7918
|
deployStatus: d2.deployStatus,
|
|
7877
7919
|
rcRetirement: "not-applicable",
|
|
7878
7920
|
rcRetirementNote: "direct-track release skips rc; no rc runtime to retire",
|
|
7921
|
+
devRollForward: devRollForward2,
|
|
7879
7922
|
announceNote: announceNote2,
|
|
7880
7923
|
// #1062: --dev on a direct-track repo is a friendly no-op — it already releases from development.
|
|
7881
7924
|
devNote: options.dev ? "--dev is a no-op on a direct-track repo \u2014 it already releases development -> main" : void 0,
|
|
@@ -7927,10 +7970,7 @@ async function runTrainApply(command, deps, options = {}) {
|
|
|
7927
7970
|
const autoRunSince2 = (deps.now ?? Date.now)();
|
|
7928
7971
|
const d2 = await dispatchDeploy(deps, ctx, "main", "main", deployModel2, watch, autoRunSince2, releaseSha2, "report");
|
|
7929
7972
|
const retirement2 = await retireRcRuntime(deps, ctx, deployModel2, d2.deployStatus, rcShaAtRelease);
|
|
7930
|
-
await deps
|
|
7931
|
-
await deps.run("git", ["pull", "--ff-only", "origin", "development"]);
|
|
7932
|
-
await deps.run("git", ["merge", "main", "--no-edit"]);
|
|
7933
|
-
await deps.run("git", ["push", "origin", "development"]);
|
|
7973
|
+
const devRollForward2 = await rollDevelopmentForward(deps, ctx, tag2);
|
|
7934
7974
|
let rcAlignment2;
|
|
7935
7975
|
try {
|
|
7936
7976
|
await deps.run("git", ["push", "origin", "main:rc"]);
|
|
@@ -7958,6 +7998,7 @@ async function runTrainApply(command, deps, options = {}) {
|
|
|
7958
7998
|
rcRetirementNote: retirement2.note,
|
|
7959
7999
|
rcRetirementCategory: retirement2.category,
|
|
7960
8000
|
rcAlignment: rcAlignment2,
|
|
8001
|
+
devRollForward: devRollForward2,
|
|
7961
8002
|
announceNote: announceNote2,
|
|
7962
8003
|
devNote: "released development -> main (--dev), skipping the rc candidate",
|
|
7963
8004
|
release: { tag: tag2, url: releaseUrl2, targetSha: releaseSha2 },
|
|
@@ -8007,10 +8048,7 @@ async function runTrainApply(command, deps, options = {}) {
|
|
|
8007
8048
|
const announceNote = deps.announce ? (await deps.announce({ repo: ctx.repo, tag, summaryFile: options.announceSummaryFile })).note : void 0;
|
|
8008
8049
|
const d = await dispatchDeploy(deps, ctx, "main", "main", deployModel, watch, autoRunSince, releaseSha, "report");
|
|
8009
8050
|
const retirement = await retireRcRuntime(deps, ctx, deployModel, d.deployStatus, releasedRcSha);
|
|
8010
|
-
await deps
|
|
8011
|
-
await deps.run("git", ["pull", "--ff-only", "origin", "development"]);
|
|
8012
|
-
await deps.run("git", ["merge", "main", "--no-edit"]);
|
|
8013
|
-
await deps.run("git", ["push", "origin", "development"]);
|
|
8051
|
+
const devRollForward = await rollDevelopmentForward(deps, ctx, tag);
|
|
8014
8052
|
let rcAlignment;
|
|
8015
8053
|
try {
|
|
8016
8054
|
await deps.run("git", ["push", "origin", "main:rc"]);
|
|
@@ -8038,6 +8076,7 @@ async function runTrainApply(command, deps, options = {}) {
|
|
|
8038
8076
|
rcRetirementNote: retirement.note,
|
|
8039
8077
|
rcRetirementCategory: retirement.category,
|
|
8040
8078
|
rcAlignment,
|
|
8079
|
+
devRollForward,
|
|
8041
8080
|
announceNote,
|
|
8042
8081
|
release: { tag, url: releaseUrl, targetSha: releaseSha },
|
|
8043
8082
|
environments
|
|
@@ -13212,6 +13251,10 @@ function renderTrainApply(commandName, r) {
|
|
|
13212
13251
|
if (r.resumeNote) base = `${base}; ${r.resumeNote}`;
|
|
13213
13252
|
if (r.devNote) base = `${base}; ${r.devNote}`;
|
|
13214
13253
|
if (r.rcRetirement) base = `${base}; rc retirement: ${r.rcRetirement.toUpperCase()} (${r.rcRetirementNote ?? ""})`;
|
|
13254
|
+
if (r.devRollForward) {
|
|
13255
|
+
const f = r.devRollForward;
|
|
13256
|
+
base = f.status === "pr-pending" ? `${base}; dev roll-forward: ALIGNMENT PR PENDING \u2014 land it with \`gh pr merge ${f.prNumber ?? "<number>"} --merge\`${f.prUrl ? ` (${f.prUrl})` : ""}` : `${base}; dev roll-forward: ${f.note}`;
|
|
13257
|
+
}
|
|
13215
13258
|
return r.announceNote ? `${base}; announce: ${r.announceNote}` : base;
|
|
13216
13259
|
}
|
|
13217
13260
|
function renderTenantRedeploy(r) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutmutco/cli",
|
|
3
|
-
"version": "2.28.
|
|
3
|
+
"version": "2.28.1",
|
|
4
4
|
"description": "MMI Future CLI — delivers the org rules (whole-file), plus saga and KB access. The cross-IDE engine the plugin's SessionStart hook drives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|