@mutmutco/cli 3.45.0 → 3.46.0
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 +66 -32
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -20428,13 +20428,46 @@ async function pollGhPrChecks(prNumber, repoArgs) {
|
|
|
20428
20428
|
}
|
|
20429
20429
|
return state;
|
|
20430
20430
|
}
|
|
20431
|
-
|
|
20431
|
+
function ghFailureReason(e) {
|
|
20432
|
+
const err = e;
|
|
20433
|
+
const head = String(err?.message ?? "").split("\n")[0]?.trim() ?? "";
|
|
20434
|
+
const detail = `${err?.stderr ?? ""}
|
|
20435
|
+
${err?.stdout ?? ""}`.split("\n").map((line) => line.trim()).find((line) => line.length > 0);
|
|
20436
|
+
if (detail && head) return `${head} \u2014 ${detail}`;
|
|
20437
|
+
return detail || head || "unknown error";
|
|
20438
|
+
}
|
|
20439
|
+
var defaultGhMergeAutoIo = {
|
|
20440
|
+
gh: async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout
|
|
20441
|
+
};
|
|
20442
|
+
async function ghMergeAutoEnqueue(prNumber, repo, method, io = defaultGhMergeAutoIo) {
|
|
20432
20443
|
const args = repo ? ["--repo", repo] : [];
|
|
20433
|
-
const headRef = (await
|
|
20444
|
+
const headRef = (await io.gh(["pr", "view", prNumber, ...args, "--json", "headRefName", "--jq", ".headRefName"], GC_GH_TIMEOUT_MS2).catch(() => "")).trim();
|
|
20434
20445
|
const deleteBranch = !isProtectedBranch(headRef);
|
|
20435
|
-
const readMergeState = () => readGhPrStateWithRetry(
|
|
20446
|
+
const readMergeState = () => readGhPrStateWithRetry(
|
|
20447
|
+
() => io.gh(["pr", "view", prNumber, ...args, "--json", "state", "--jq", ".state"], GC_GH_TIMEOUT_MS2)
|
|
20448
|
+
);
|
|
20449
|
+
const confirmEnqueueOutcome = async () => {
|
|
20450
|
+
const stateRead = await readMergeState();
|
|
20451
|
+
if (!stateRead.ok) {
|
|
20452
|
+
return { mergeStatus: "failed", error: `could not read PR state after merge: ${stateRead.error}` };
|
|
20453
|
+
}
|
|
20454
|
+
if (stateRead.state === "MERGED") return { mergeStatus: "merged" };
|
|
20455
|
+
const confirmation = await confirmAutoMergeEnqueued({
|
|
20456
|
+
readAutoMergeRequest: async () => io.gh(["pr", "view", prNumber, ...args, "--json", "autoMergeRequest", "--jq", '.autoMergeRequest // ""'], GC_GH_TIMEOUT_MS2),
|
|
20457
|
+
readMerged: async () => {
|
|
20458
|
+
const s = await readMergeState();
|
|
20459
|
+
return s.ok && s.state === "MERGED";
|
|
20460
|
+
},
|
|
20461
|
+
reEnqueue: async () => {
|
|
20462
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch }), GH_MUTATION_TIMEOUT_MS);
|
|
20463
|
+
}
|
|
20464
|
+
});
|
|
20465
|
+
if (confirmation === "merged") return { mergeStatus: "merged" };
|
|
20466
|
+
if (confirmation === "enqueued") return { mergeStatus: "auto-merge-enqueued" };
|
|
20467
|
+
return { mergeStatus: "failed", error: "auto-merge did not stick \u2014 GitHub reported no autoMergeRequest after enqueue; retry once the PR has a pending check" };
|
|
20468
|
+
};
|
|
20436
20469
|
try {
|
|
20437
|
-
await
|
|
20470
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch }), GH_MUTATION_TIMEOUT_MS);
|
|
20438
20471
|
} catch (e) {
|
|
20439
20472
|
const message = String(e.message || "");
|
|
20440
20473
|
if (/already been merged/i.test(message)) return { mergeStatus: "merged" };
|
|
@@ -20442,50 +20475,51 @@ async function ghMergeAutoEnqueue(prNumber, repo, method) {
|
|
|
20442
20475
|
if (note) return { mergeStatus: "failed", error: note };
|
|
20443
20476
|
if (mergeAutoRejectedPrAlreadyClean(message)) {
|
|
20444
20477
|
try {
|
|
20445
|
-
await
|
|
20478
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: false, deleteBranch }), GH_MUTATION_TIMEOUT_MS);
|
|
20446
20479
|
} catch (e2) {
|
|
20447
20480
|
const m2 = String(e2.message || "");
|
|
20448
20481
|
if (/already been merged/i.test(m2)) return { mergeStatus: "merged" };
|
|
20449
|
-
if (!ghPrMergeLocalBranchDeleteWarning(m2))
|
|
20482
|
+
if (!ghPrMergeLocalBranchDeleteWarning(m2)) {
|
|
20483
|
+
const afterDirect = await readMergeState();
|
|
20484
|
+
if (afterDirect.ok && afterDirect.state === "MERGED") return { mergeStatus: "merged" };
|
|
20485
|
+
if (!afterDirect.ok) {
|
|
20486
|
+
return { mergeStatus: "failed", error: `could not confirm PR state after clean-status fallback: ${afterDirect.error}` };
|
|
20487
|
+
}
|
|
20488
|
+
try {
|
|
20489
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch }), GH_MUTATION_TIMEOUT_MS);
|
|
20490
|
+
} catch (e3) {
|
|
20491
|
+
const m3 = String(e3.message || "");
|
|
20492
|
+
if (/already been merged/i.test(m3)) return { mergeStatus: "merged" };
|
|
20493
|
+
const afterRetry = await readMergeState();
|
|
20494
|
+
if (afterRetry.ok && afterRetry.state === "MERGED") return { mergeStatus: "merged" };
|
|
20495
|
+
const stuck = (await io.gh(["pr", "view", prNumber, ...args, "--json", "autoMergeRequest", "--jq", '.autoMergeRequest // ""'], GC_GH_TIMEOUT_MS2).catch(() => "")).trim();
|
|
20496
|
+
if (stuck) return { mergeStatus: "auto-merge-enqueued" };
|
|
20497
|
+
return { mergeStatus: "failed", error: `${ghFailureReason(e2)} (re-enqueue also failed: ${ghFailureReason(e3)})` };
|
|
20498
|
+
}
|
|
20499
|
+
return confirmEnqueueOutcome();
|
|
20500
|
+
}
|
|
20450
20501
|
}
|
|
20451
|
-
const
|
|
20452
|
-
if (
|
|
20502
|
+
const stateRead = await readMergeState();
|
|
20503
|
+
if (stateRead.ok && stateRead.state === "MERGED") return { mergeStatus: "merged" };
|
|
20453
20504
|
return {
|
|
20454
20505
|
mergeStatus: "failed",
|
|
20455
|
-
error:
|
|
20506
|
+
error: stateRead.ok ? "direct merge did not land after clean-status fallback" : `could not confirm PR state after clean-status fallback: ${stateRead.error}`
|
|
20456
20507
|
};
|
|
20457
20508
|
}
|
|
20458
20509
|
if (ghPrMergeLocalBranchDeleteWarning(message)) {
|
|
20459
|
-
const
|
|
20460
|
-
if (
|
|
20510
|
+
const stateRead = await readMergeState();
|
|
20511
|
+
if (stateRead.ok && stateRead.state === "MERGED") return { mergeStatus: "merged" };
|
|
20461
20512
|
return {
|
|
20462
20513
|
mergeStatus: "failed",
|
|
20463
|
-
error:
|
|
20514
|
+
error: stateRead.ok ? message.split("\n")[0] : `could not confirm PR state after local branch cleanup warning: ${stateRead.error}`
|
|
20464
20515
|
};
|
|
20465
20516
|
}
|
|
20466
20517
|
if (!basePolicyBlocksImmediateMerge(message)) {
|
|
20467
|
-
return { mergeStatus: "failed", error:
|
|
20518
|
+
return { mergeStatus: "failed", error: ghFailureReason(e) };
|
|
20468
20519
|
}
|
|
20469
|
-
return { mergeStatus: "failed", error: `merge blocked: ${
|
|
20470
|
-
}
|
|
20471
|
-
const stateRead = await readMergeState();
|
|
20472
|
-
if (!stateRead.ok) {
|
|
20473
|
-
return { mergeStatus: "failed", error: `could not read PR state after merge: ${stateRead.error}` };
|
|
20520
|
+
return { mergeStatus: "failed", error: `merge blocked: ${ghFailureReason(e)} \u2014 ensure checks are green` };
|
|
20474
20521
|
}
|
|
20475
|
-
|
|
20476
|
-
const confirmation = await confirmAutoMergeEnqueued({
|
|
20477
|
-
readAutoMergeRequest: async () => (await execFileP2("gh", ["pr", "view", prNumber, ...args, "--json", "autoMergeRequest", "--jq", '.autoMergeRequest // ""'], { timeout: GC_GH_TIMEOUT_MS2 })).stdout,
|
|
20478
|
-
readMerged: async () => {
|
|
20479
|
-
const s = await readMergeState();
|
|
20480
|
-
return s.ok && s.state === "MERGED";
|
|
20481
|
-
},
|
|
20482
|
-
reEnqueue: async () => {
|
|
20483
|
-
await execFileP2("gh", buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch }), { timeout: GH_MUTATION_TIMEOUT_MS });
|
|
20484
|
-
}
|
|
20485
|
-
});
|
|
20486
|
-
if (confirmation === "merged") return { mergeStatus: "merged" };
|
|
20487
|
-
if (confirmation === "enqueued") return { mergeStatus: "auto-merge-enqueued" };
|
|
20488
|
-
return { mergeStatus: "failed", error: "auto-merge did not stick \u2014 GitHub reported no autoMergeRequest after enqueue; retry once the PR has a pending check" };
|
|
20522
|
+
return confirmEnqueueOutcome();
|
|
20489
20523
|
}
|
|
20490
20524
|
async function remoteBranchExists2(branch, options = {}) {
|
|
20491
20525
|
return checkRemoteBranchExists(branch, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutmutco/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.46.0",
|
|
4
4
|
"description": "MMI Future CLI — the org dev toolbox (board, registry, keyless secrets, release train, bootstrap, doctor) and the cross-IDE engine the plugin's session-start hook drives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|