@mutmutco/cli 3.105.5 → 3.105.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 +85 -26
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -29109,6 +29109,21 @@ function derivePollState(buckets) {
|
|
|
29109
29109
|
if (anyFailure) return anyPending ? "failing" : "failure";
|
|
29110
29110
|
return anyPending ? "pending" : "success";
|
|
29111
29111
|
}
|
|
29112
|
+
function partitionByRequired(entries, requiredContexts) {
|
|
29113
|
+
if (!requiredContexts || requiredContexts.size === 0) {
|
|
29114
|
+
return { relevant: entries.map((e) => e.bucket), ignoredFailures: [] };
|
|
29115
|
+
}
|
|
29116
|
+
const relevant = [];
|
|
29117
|
+
const ignoredFailures = [];
|
|
29118
|
+
for (const entry of entries) {
|
|
29119
|
+
if (requiredContexts.has(entry.name)) {
|
|
29120
|
+
relevant.push(entry.bucket);
|
|
29121
|
+
} else if (entry.bucket === "fail") {
|
|
29122
|
+
ignoredFailures.push(entry.name);
|
|
29123
|
+
}
|
|
29124
|
+
}
|
|
29125
|
+
return { relevant, ignoredFailures };
|
|
29126
|
+
}
|
|
29112
29127
|
function parseNdjsonLines(stdout) {
|
|
29113
29128
|
return stdout.split(/\r?\n/).filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
29114
29129
|
}
|
|
@@ -29147,17 +29162,22 @@ async function fetchHeadCheckRuns(headSha, repo, gh) {
|
|
|
29147
29162
|
const runsOut = await gh(["--paginate", `repos/${repo}/commits/${headSha}/check-runs?per_page=100`, "--jq", ".check_runs[] | {id, name, status, conclusion, app_id: .app.id}"]);
|
|
29148
29163
|
return dedupeLatestCheckRuns(parseNdjsonLines(runsOut));
|
|
29149
29164
|
}
|
|
29150
|
-
async function
|
|
29165
|
+
async function fetchHeadCheckEntries(headSha, repo, gh) {
|
|
29151
29166
|
const [runs, statusesOut] = await Promise.all([
|
|
29152
29167
|
fetchHeadCheckRuns(headSha, repo, gh),
|
|
29153
29168
|
gh(["--paginate", `repos/${repo}/commits/${headSha}/status?per_page=100`, "--jq", ".statuses[] | {context, state}"])
|
|
29154
29169
|
]);
|
|
29155
29170
|
const statuses = parseNdjsonLines(statusesOut);
|
|
29156
|
-
return [
|
|
29171
|
+
return [
|
|
29172
|
+
...runs.map((run) => ({ name: run.name ?? `check-run ${run.id ?? "unknown"}`, bucket: classifyCheckRun(run) })),
|
|
29173
|
+
...statuses.map((s) => ({ name: s.context ?? "unknown-status", bucket: classifyCommitStatus(s.state) }))
|
|
29174
|
+
];
|
|
29157
29175
|
}
|
|
29158
|
-
async function pollRestPrChecks(prNumber, repo, gh = defaultGhApi) {
|
|
29176
|
+
async function pollRestPrChecks(prNumber, repo, gh = defaultGhApi, requiredContexts) {
|
|
29159
29177
|
const snapshot = await fetchRestPrSnapshot(prNumber, repo, gh);
|
|
29160
|
-
|
|
29178
|
+
const entries = await fetchHeadCheckEntries(snapshot.headSha, repo, gh);
|
|
29179
|
+
const { relevant } = partitionByRequired(entries, requiredContexts);
|
|
29180
|
+
return derivePollState(relevant);
|
|
29161
29181
|
}
|
|
29162
29182
|
async function pollRestPrMergeable(prNumber, repo, gh = defaultGhApi) {
|
|
29163
29183
|
try {
|
|
@@ -29258,6 +29278,37 @@ async function diagnoseFailedRestChecks(prNumber, repo, gh = defaultGhApi) {
|
|
|
29258
29278
|
return null;
|
|
29259
29279
|
}
|
|
29260
29280
|
}
|
|
29281
|
+
function isNotFoundError2(e) {
|
|
29282
|
+
const msg = `${e?.message ?? e} ${String(e?.stderr ?? "")}`;
|
|
29283
|
+
return /HTTP 404|Not Found|\(404\)/i.test(msg);
|
|
29284
|
+
}
|
|
29285
|
+
async function fetchRequiredCheckContexts(repo, branch, gh = defaultGhApi) {
|
|
29286
|
+
const contexts = /* @__PURE__ */ new Set();
|
|
29287
|
+
try {
|
|
29288
|
+
const raw = await gh([`repos/${repo}/branches/${encodeURIComponent(branch)}/protection/required_status_checks`]);
|
|
29289
|
+
const parsed = JSON.parse(raw);
|
|
29290
|
+
if (Array.isArray(parsed.contexts)) {
|
|
29291
|
+
for (const c of parsed.contexts) if (typeof c === "string") contexts.add(c);
|
|
29292
|
+
}
|
|
29293
|
+
} catch (e) {
|
|
29294
|
+
if (!isNotFoundError2(e)) return null;
|
|
29295
|
+
}
|
|
29296
|
+
try {
|
|
29297
|
+
const raw = await gh([`repos/${repo}/rules/branches/${encodeURIComponent(branch)}`]);
|
|
29298
|
+
const parsed = JSON.parse(raw);
|
|
29299
|
+
if (Array.isArray(parsed)) {
|
|
29300
|
+
for (const rule of parsed) {
|
|
29301
|
+
if (rule.type !== "required_status_checks") continue;
|
|
29302
|
+
for (const check of rule.parameters?.required_status_checks ?? []) {
|
|
29303
|
+
if (check.context) contexts.add(check.context);
|
|
29304
|
+
}
|
|
29305
|
+
}
|
|
29306
|
+
}
|
|
29307
|
+
} catch (e) {
|
|
29308
|
+
if (!isNotFoundError2(e)) return null;
|
|
29309
|
+
}
|
|
29310
|
+
return contexts;
|
|
29311
|
+
}
|
|
29261
29312
|
async function fetchRestCorePool(gh = defaultGhApi) {
|
|
29262
29313
|
try {
|
|
29263
29314
|
const parsed = JSON.parse(await gh(["rate_limit"]));
|
|
@@ -36786,9 +36837,10 @@ pr.command("checks-wait <number>").description(`bounded wait for PR checks; skip
|
|
|
36786
36837
|
const snapshot = await fetchRestPrSnapshot(number, repo).catch(() => null);
|
|
36787
36838
|
const baseBranch = snapshot?.baseRef ?? "development";
|
|
36788
36839
|
const ciHeadRef = snapshot && !snapshot.headIsFork && snapshot.headRef ? snapshot.headRef : void 0;
|
|
36840
|
+
const requiredContexts = await fetchRequiredCheckContexts(repo, baseBranch).catch(() => null);
|
|
36789
36841
|
const result = await waitForPrChecks({
|
|
36790
36842
|
resolvePolicy: () => resolveMergeCiPolicyForCheckout(o.repo, ciHeadRef),
|
|
36791
|
-
pollChecks: () => pollRestPrChecks(number, repo),
|
|
36843
|
+
pollChecks: () => pollRestPrChecks(number, repo, void 0, requiredContexts),
|
|
36792
36844
|
pollMergeable: () => pollRestPrMergeable(number, repo),
|
|
36793
36845
|
pollRateLimit: () => fetchRestCorePool(),
|
|
36794
36846
|
// #3388: on a confirmed red, read the failing runs' annotations so a wall-clock budget kill stops
|
|
@@ -36854,31 +36906,37 @@ pr.command("land <number>").description("agent merge path (#1440): train probe ?
|
|
|
36854
36906
|
},
|
|
36855
36907
|
fetchTrainAuthority: async (repo) => fetchTrainAuthority(repo, registryClientDeps(await loadConfig())),
|
|
36856
36908
|
resolveCiPolicy: (repo) => resolveRepoMergeCiPolicy(repo, ciAuditDeps()),
|
|
36857
|
-
waitForChecks: (prNumber, repo) =>
|
|
36858
|
-
|
|
36859
|
-
|
|
36860
|
-
|
|
36861
|
-
|
|
36862
|
-
|
|
36863
|
-
|
|
36864
|
-
|
|
36865
|
-
|
|
36866
|
-
|
|
36867
|
-
|
|
36868
|
-
|
|
36869
|
-
|
|
36870
|
-
|
|
36871
|
-
|
|
36872
|
-
|
|
36873
|
-
|
|
36874
|
-
|
|
36909
|
+
waitForChecks: async (prNumber, repo) => {
|
|
36910
|
+
const requiredContexts = await fetchRequiredCheckContexts(repo, "development").catch(() => null);
|
|
36911
|
+
return waitForPrChecks({
|
|
36912
|
+
resolvePolicy: () => resolveRepoMergeCiPolicy(repo, ciAuditDeps()),
|
|
36913
|
+
// #3024: REST-only wait loop ? runPrLand's resolveRepo already guarantees `repo` is set.
|
|
36914
|
+
pollChecks: () => pollRestPrChecks(prNumber, repo, void 0, requiredContexts),
|
|
36915
|
+
// #2970: `pr land` only ever lands PRs based on development (resolveRepo above already rejects any
|
|
36916
|
+
// other base), so the fast-fail message's base branch is always 'development' here.
|
|
36917
|
+
pollMergeable: () => pollRestPrMergeable(prNumber, repo),
|
|
36918
|
+
pollRateLimit: () => fetchRestCorePool(),
|
|
36919
|
+
// #3388: `pr land` is the batch path ? the one most likely to self-DOS the shared runner and
|
|
36920
|
+
// then read its own wall-clock kill as a broken diff.
|
|
36921
|
+
diagnoseFailure: () => diagnoseFailedRestChecks(prNumber, repo),
|
|
36922
|
+
baseBranch: "development",
|
|
36923
|
+
sleep: (ms) => new Promise((resolve5) => setTimeout(resolve5, ms)),
|
|
36924
|
+
log: (message) => console.warn(message),
|
|
36925
|
+
// `pr land` inherits the same (raised) checks budget, so it needs the same liveness ? otherwise the
|
|
36926
|
+
// 30m wait is SILENT and reads exactly like the hang #2940 was filed about, only three times longer.
|
|
36927
|
+
progress: ({ state, elapsedMs, remainingMs }) => console.warn(`pr land: waiting on checks ? ${state}, ${Math.round(elapsedMs / 1e3)}s elapsed, ${Math.round(remainingMs / 6e4)}m left`)
|
|
36928
|
+
});
|
|
36929
|
+
},
|
|
36875
36930
|
// #2425: re-probe used ONLY to decide whether a failed `gh pr merge --auto` is worth retrying ? a
|
|
36876
36931
|
// fresh read of state/mergeable/checks, independent of the merge call's own (possibly stale) error.
|
|
36932
|
+
// #4396: same required-status scoping as the wait loop above ? a non-required red must not read
|
|
36933
|
+
// as "not ready to retry" any more than it should have blocked the wait itself.
|
|
36877
36934
|
probeMergeReady: async (prNumber, repo) => {
|
|
36878
|
-
const [snapshot,
|
|
36935
|
+
const [snapshot, requiredContexts] = await Promise.all([
|
|
36879
36936
|
fetchRestPrSnapshot(prNumber, repo).catch(() => null),
|
|
36880
|
-
|
|
36937
|
+
fetchRequiredCheckContexts(repo, "development").catch(() => null)
|
|
36881
36938
|
]);
|
|
36939
|
+
const checks = await pollRestPrChecks(prNumber, repo, void 0, requiredContexts).catch(() => "error");
|
|
36882
36940
|
return {
|
|
36883
36941
|
open: snapshot?.state === "open",
|
|
36884
36942
|
mergeable: snapshot?.mergeable === "MERGEABLE",
|
|
@@ -36961,9 +37019,10 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
|
|
|
36961
37019
|
if (o.wait) {
|
|
36962
37020
|
const repo = await requireRepo(o.repo);
|
|
36963
37021
|
const baseBranch = await fetchRestPrSnapshot(number, repo).then((s) => s.baseRef).catch(() => "development");
|
|
37022
|
+
const requiredContexts = await fetchRequiredCheckContexts(repo, baseBranch).catch(() => null);
|
|
36964
37023
|
const wait = await waitForPrChecks({
|
|
36965
37024
|
resolvePolicy: () => resolveMergeCiPolicyForCheckout(o.repo, ciHeadRef),
|
|
36966
|
-
pollChecks: () => pollRestPrChecks(number, repo),
|
|
37025
|
+
pollChecks: () => pollRestPrChecks(number, repo, void 0, requiredContexts),
|
|
36967
37026
|
pollMergeable: () => pollRestPrMergeable(number, repo),
|
|
36968
37027
|
pollRateLimit: () => fetchRestCorePool(),
|
|
36969
37028
|
diagnoseFailure: () => diagnoseFailedRestChecks(number, repo),
|
package/package.json
CHANGED