@mutmutco/cli 4.2.6 → 4.2.7
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 +52 -18
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -11830,10 +11830,10 @@ var rollout_plan_default = {
|
|
|
11830
11830
|
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)."
|
|
11831
11831
|
},
|
|
11832
11832
|
baseline: {
|
|
11833
|
-
version: "4.2.
|
|
11834
|
-
tag: "v4.2.
|
|
11835
|
-
commit: "
|
|
11836
|
-
npm: "@mutmutco/cli@4.2.
|
|
11833
|
+
version: "4.2.7",
|
|
11834
|
+
tag: "v4.2.7",
|
|
11835
|
+
commit: "bb37250e186c",
|
|
11836
|
+
npm: "@mutmutco/cli@4.2.7"
|
|
11837
11837
|
},
|
|
11838
11838
|
exitCriterion: "fleet-n-of-n",
|
|
11839
11839
|
hubOnlyShortcut: "forbidden",
|
|
@@ -11850,14 +11850,14 @@ var rollout_plan_default = {
|
|
|
11850
11850
|
repo: "mutmutco/mmi-hub",
|
|
11851
11851
|
role: "canary",
|
|
11852
11852
|
schedule: "train",
|
|
11853
|
-
v3Target: "v4.2.
|
|
11853
|
+
v3Target: "v4.2.7"
|
|
11854
11854
|
}
|
|
11855
11855
|
],
|
|
11856
11856
|
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.",
|
|
11857
11857
|
rollback: {
|
|
11858
11858
|
independent: true,
|
|
11859
|
-
mechanism: "npm dist-tag latest -> 4.2.
|
|
11860
|
-
v3Target: "v4.2.
|
|
11859
|
+
mechanism: "npm dist-tag latest -> 4.2.7 and redeploy the Hub Lambda from tag v4.2.7 (bb37250e186c); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
11860
|
+
v3Target: "v4.2.7 (@mutmutco/cli@4.2.7, tag commit bb37250e186c \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
11861
11861
|
}
|
|
11862
11862
|
},
|
|
11863
11863
|
{
|
|
@@ -15880,15 +15880,35 @@ function parseGateNpmVersionPins(workflowBody) {
|
|
|
15880
15880
|
if (!/runner-node-toolchain/.test(workflowBody)) return [];
|
|
15881
15881
|
return [...workflowBody.matchAll(/^\s*npm-version:\s*['"]?(\d+(?:\.\d+\.\d+)?)/gm)].map((m) => m[1]);
|
|
15882
15882
|
}
|
|
15883
|
+
function parseGateNpmInstallPins(workflowBody) {
|
|
15884
|
+
return [...workflowBody.matchAll(/npm\s+install\s+-g\s+npm@(\d+(?:\.\d+\.\d+)?)/g)].map((m) => m[1]);
|
|
15885
|
+
}
|
|
15886
|
+
function gateDeclaredNpmPins(gateFiles) {
|
|
15887
|
+
const files = gateFiles ?? [];
|
|
15888
|
+
return [
|
|
15889
|
+
...files.flatMap((file) => parseGateNpmVersionPins(file.body)),
|
|
15890
|
+
...files.flatMap((file) => parseGateNpmInstallPins(file.body))
|
|
15891
|
+
];
|
|
15892
|
+
}
|
|
15893
|
+
function publishWorkflowNpm(files) {
|
|
15894
|
+
const publish = files?.find((f) => /(?:^|\/)publish\.ya?ml$/i.test(f.path));
|
|
15895
|
+
return publish ? parsePublishWorkflowNpmPin(publish.body) : void 0;
|
|
15896
|
+
}
|
|
15883
15897
|
function resolveExpectedCiNpmFromWorkflows(gateFiles, allFiles) {
|
|
15884
|
-
const declared = gateFiles
|
|
15898
|
+
const declared = gateDeclaredNpmPins(gateFiles);
|
|
15885
15899
|
if (declared.length) return declared[0];
|
|
15886
15900
|
const fromGate = resolveGreenGateNpmFromGateWorkflows(gateFiles);
|
|
15887
15901
|
if (fromGate) return fromGate;
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
15902
|
+
return publishWorkflowNpm(allFiles ?? gateFiles);
|
|
15903
|
+
}
|
|
15904
|
+
function detectNpmPinDisagreement(gateFiles, allFiles) {
|
|
15905
|
+
const gateNpm = gateDeclaredNpmPins(gateFiles)[0];
|
|
15906
|
+
const publishNpm = publishWorkflowNpm(allFiles ?? gateFiles);
|
|
15907
|
+
if (!gateNpm || !publishNpm) return null;
|
|
15908
|
+
const gateMajor = npmMajor(gateNpm);
|
|
15909
|
+
const publishMajor = npmMajor(publishNpm);
|
|
15910
|
+
if (gateMajor === void 0 || publishMajor === void 0) return null;
|
|
15911
|
+
return gateMajor === publishMajor ? null : { gateNpm, publishNpm };
|
|
15892
15912
|
}
|
|
15893
15913
|
function npmMajor(version) {
|
|
15894
15914
|
const match = /^(\d+)/.exec(version.trim());
|
|
@@ -15903,7 +15923,7 @@ function assertNpmMajorPreflight(opts) {
|
|
|
15903
15923
|
if (localMajor === void 0 || expectedMajor === void 0) return;
|
|
15904
15924
|
if (localMajor === expectedMajor) return;
|
|
15905
15925
|
throw new Error(
|
|
15906
|
-
`${opts.repo}: Step 0a npm-major preflight failed \u2014 local npm ${localNpm} (major ${localMajor}) \u2260 CI npm ${expectedNpm} (major ${expectedMajor}). Supported repair (preserves Node): \`npm install -g npm@${expectedNpm}\`; then verify with \`node -v && npm -v\` and rerun the same release command. This is an npm-major mismatch (#5666/#5616/#4578), not a lockfile or publish-surface problem.
|
|
15926
|
+
`${opts.repo}: Step 0a npm-major preflight failed \u2014 local npm ${localNpm} (major ${localMajor}) \u2260 CI npm ${expectedNpm} (major ${expectedMajor}). Supported repair (preserves Node): \`npm install -g npm@${expectedNpm}\`; then verify with \`node -v && npm -v\` and rerun the same release command. This is an npm-major mismatch (#5666/#5616/#4578), not a lockfile or publish-surface problem. The expected npm is the gate's own declared npm \u2014 an \`npm-version:\` input or an explicit \`npm install -g npm@X\` step (#5893) \u2014 and only a gate that declares neither falls back to a bundled-npm mapping or the publish workflow's pin; otherwise compare \`npm -v\` with the green gate log's toolchain-preflight line (#3446).`
|
|
15907
15927
|
);
|
|
15908
15928
|
}
|
|
15909
15929
|
async function assertNpmMajorPreflightFromWorkflows(deps, repo) {
|
|
@@ -15915,6 +15935,12 @@ async function assertNpmMajorPreflightFromWorkflows(deps, repo) {
|
|
|
15915
15935
|
} catch {
|
|
15916
15936
|
return;
|
|
15917
15937
|
}
|
|
15938
|
+
const disagreement = detectNpmPinDisagreement(gateFiles, allFiles);
|
|
15939
|
+
if (disagreement) {
|
|
15940
|
+
(deps.warn ?? ((m) => console.warn(m)))(
|
|
15941
|
+
`${repo}: repo defect \u2014 the gate declares npm ${disagreement.gateNpm} while the publish workflow pins npm ${disagreement.publishNpm}. The gate's declaration wins this preflight, but the publish lane will still run npm ${disagreement.publishNpm}. Align both pins in one PR.`
|
|
15942
|
+
);
|
|
15943
|
+
}
|
|
15918
15944
|
assertNpmMajorPreflight({
|
|
15919
15945
|
repo,
|
|
15920
15946
|
localNpm,
|
|
@@ -31344,11 +31370,14 @@ async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile) {
|
|
|
31344
31370
|
}
|
|
31345
31371
|
return confirmEnqueueOutcome();
|
|
31346
31372
|
}
|
|
31373
|
+
function cleanupGitArgs(cwd, args) {
|
|
31374
|
+
return cwd ? ["-C", cwd, ...args] : args;
|
|
31375
|
+
}
|
|
31347
31376
|
async function remoteBranchExists2(branch, options = {}) {
|
|
31348
31377
|
if (!branch) return void 0;
|
|
31349
31378
|
try {
|
|
31350
|
-
if (options.prune) await execFileP2("git", ["fetch", "origin", "--prune"], { timeout: GIT_TIMEOUT_MS });
|
|
31351
|
-
return (await execFileP2("git", ["ls-remote", "--heads", "origin", branch], { timeout: GIT_TIMEOUT_MS })).stdout.trim().length > 0;
|
|
31379
|
+
if (options.prune) await execFileP2("git", cleanupGitArgs(options.cwd, ["fetch", "origin", "--prune"]), { timeout: GIT_TIMEOUT_MS });
|
|
31380
|
+
return (await execFileP2("git", cleanupGitArgs(options.cwd, ["ls-remote", "--heads", "origin", branch]), { timeout: GIT_TIMEOUT_MS })).stdout.trim().length > 0;
|
|
31352
31381
|
} catch {
|
|
31353
31382
|
return void 0;
|
|
31354
31383
|
}
|
|
@@ -40864,7 +40893,10 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
|
|
|
40864
40893
|
gcAcknowledged: o.gc,
|
|
40865
40894
|
expectedHeadOid: headRefOid,
|
|
40866
40895
|
pathExists: (p) => (0, import_node_fs43.existsSync)(p),
|
|
40867
|
-
|
|
40896
|
+
// #5899: pin cleanup git calls to the main checkout — the task worktree this process may be
|
|
40897
|
+
// standing in is removed mid-cleanup, so a cwd-relative invocation fails with
|
|
40898
|
+
// 'fatal: not a git repository' and leaves a spurious partial-cleanup exit.
|
|
40899
|
+
execGit: async (args) => (await execFileP2("git", cleanupGitArgs(primaryRoot, args), { timeout: GIT_TIMEOUT_MS })).stdout
|
|
40868
40900
|
});
|
|
40869
40901
|
} catch (e) {
|
|
40870
40902
|
localCleanup = {
|
|
@@ -40879,8 +40911,10 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
|
|
|
40879
40911
|
const remoteBranch = await deleteMergedRemoteBranch({
|
|
40880
40912
|
branch: headRef,
|
|
40881
40913
|
existedBefore: remoteBefore,
|
|
40882
|
-
|
|
40883
|
-
|
|
40914
|
+
// #5899: this leg runs after worktree teardown — anchor it to the main checkout so a cwd inside
|
|
40915
|
+
// the removed worktree cannot turn the delete into 'fatal: not a git repository' + manual remediation.
|
|
40916
|
+
execGit: async (args) => (await execFileP2("git", cleanupGitArgs(primaryRoot, args), { timeout: GIT_TIMEOUT_MS })).stdout,
|
|
40917
|
+
branchExists: (b) => remoteBranchExists2(b, { cwd: primaryRoot })
|
|
40884
40918
|
});
|
|
40885
40919
|
const worktreePartial = localCleanup?.worktree?.path && localCleanup.worktree.status !== "removed" ? {
|
|
40886
40920
|
kind: "worktree-directory",
|
package/package.json
CHANGED