@mutmutco/claude-plugin 4.5.163 → 4.5.165
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/.claude-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +75 -23
- package/cli/package.json +1 -1
- package/package.json +1 -1
package/cli/dist/main.cjs
CHANGED
|
@@ -14631,6 +14631,15 @@ function latestClaimMarker(comments) {
|
|
|
14631
14631
|
}
|
|
14632
14632
|
return void 0;
|
|
14633
14633
|
}
|
|
14634
|
+
function latestClaimRelease(comments) {
|
|
14635
|
+
for (let i = comments.length - 1; i >= 0; i -= 1) {
|
|
14636
|
+
const body = comments[i].body;
|
|
14637
|
+
const releases = parseClaimReleases(body);
|
|
14638
|
+
if (!parseClaimMarkers(body).length && !releases.length) continue;
|
|
14639
|
+
return latestClaimMarker([comments[i]]) ? void 0 : releases[releases.length - 1];
|
|
14640
|
+
}
|
|
14641
|
+
return void 0;
|
|
14642
|
+
}
|
|
14634
14643
|
function formatClaimAge(ageMs) {
|
|
14635
14644
|
if (ageMs === void 0 || !Number.isFinite(ageMs) || ageMs < 0) return "unknown age";
|
|
14636
14645
|
const minutes = Math.floor(ageMs / 6e4);
|
|
@@ -14838,6 +14847,7 @@ async function gatherClaimLiveness(client, repo, number, fetchOpenPulls) {
|
|
|
14838
14847
|
const comments = await client.restPaginate(`repos/${repo}/issues/${number}/comments`);
|
|
14839
14848
|
const rows = comments.map((comment) => ({ body: comment.body ?? "", login: comment.user?.login ?? void 0 }));
|
|
14840
14849
|
out.marker = latestClaimMarker(rows);
|
|
14850
|
+
if (!out.marker) out.releasedAt = latestClaimRelease(rows)?.ts;
|
|
14841
14851
|
for (let i = comments.length - 1; i >= 0; i -= 1) {
|
|
14842
14852
|
if (comments[i].created_at && !latestClaimMarker([rows[i]])) {
|
|
14843
14853
|
out.lastCommentAt = comments[i].created_at;
|
|
@@ -14919,8 +14929,9 @@ function liveEvidenceLines(evidence, repo) {
|
|
|
14919
14929
|
live.push(evidence.lastCommentAt && Date.parse(evidence.lastCommentAt) > Date.parse(evidence.marker.ts) ? `claim marker from ${marker} is ${formatClaimAge(evidence.markerAgeMs)} old but the issue was commented ${formatClaimAge(idleMs)} ago (session not locally probeable)` : `claim marker from ${marker} is only ${formatClaimAge(evidence.markerAgeMs)} old (session not locally probeable)`);
|
|
14920
14930
|
}
|
|
14921
14931
|
}
|
|
14922
|
-
|
|
14923
|
-
if (evidence.
|
|
14932
|
+
const sinceRelease = (at) => !evidence.releasedAt || at === void 0 || Date.parse(at) > Date.parse(evidence.releasedAt);
|
|
14933
|
+
if (evidence.openPr && workIsLive(evidence.openPrAt) && sinceRelease(evidence.openPrAt)) live.push(evidence.openPr);
|
|
14934
|
+
if (evidence.branch && workIsLive(evidence.branchAt) && sinceRelease(evidence.branchAt)) live.push(`live branch ${evidence.branch} on ${repo}`);
|
|
14924
14935
|
return live;
|
|
14925
14936
|
}
|
|
14926
14937
|
function staleWorkLines(evidence) {
|
|
@@ -19051,10 +19062,10 @@ var rollout_plan_default = {
|
|
|
19051
19062
|
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)."
|
|
19052
19063
|
},
|
|
19053
19064
|
baseline: {
|
|
19054
|
-
version: "4.5.
|
|
19055
|
-
tag: "v4.5.
|
|
19056
|
-
commit: "
|
|
19057
|
-
npm: "@mutmutco/cli@4.5.
|
|
19065
|
+
version: "4.5.165",
|
|
19066
|
+
tag: "v4.5.165",
|
|
19067
|
+
commit: "e50afbd193c3",
|
|
19068
|
+
npm: "@mutmutco/cli@4.5.165"
|
|
19058
19069
|
},
|
|
19059
19070
|
exitCriterion: "fleet-n-of-n",
|
|
19060
19071
|
hubOnlyShortcut: "forbidden",
|
|
@@ -19071,14 +19082,14 @@ var rollout_plan_default = {
|
|
|
19071
19082
|
repo: "mutmutco/mmi-hub",
|
|
19072
19083
|
role: "canary",
|
|
19073
19084
|
schedule: "train",
|
|
19074
|
-
v3Target: "v4.5.
|
|
19085
|
+
v3Target: "v4.5.165"
|
|
19075
19086
|
}
|
|
19076
19087
|
],
|
|
19077
19088
|
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.",
|
|
19078
19089
|
rollback: {
|
|
19079
19090
|
independent: true,
|
|
19080
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
19081
|
-
v3Target: "v4.5.
|
|
19091
|
+
mechanism: "npm dist-tag latest -> 4.5.165 and redeploy the Hub Lambda from tag v4.5.165 (e50afbd193c3); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
19092
|
+
v3Target: "v4.5.165 (@mutmutco/cli@4.5.165, tag commit e50afbd193c3 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
19082
19093
|
}
|
|
19083
19094
|
},
|
|
19084
19095
|
{
|
|
@@ -33317,7 +33328,7 @@ function parseGateVar(raw) {
|
|
|
33317
33328
|
}
|
|
33318
33329
|
var SECRET_OUTPUT_PATH_RE = /^\/[A-Za-z0-9._/-]+$/;
|
|
33319
33330
|
var SECRET_OUTPUT_REPO_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*\/[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
33320
|
-
var SECRET_OUTPUT_KEY_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
33331
|
+
var SECRET_OUTPUT_KEY_RE = /^(?:(?:dev|rc|main)\/)?[A-Z][A-Z0-9_]*$/;
|
|
33321
33332
|
function parseTenantTaskSecretOutput(raw, label) {
|
|
33322
33333
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
33323
33334
|
throw new Error(`org project set: ${label} must be an object {path,vault:{repo,key},overwrite?}`);
|
|
@@ -33341,7 +33352,7 @@ function parseTenantTaskSecretOutput(raw, label) {
|
|
|
33341
33352
|
throw new Error(`org project set: ${label}.vault.repo must be owner/name`);
|
|
33342
33353
|
}
|
|
33343
33354
|
if (typeof vaultMap.key !== "string" || !SECRET_OUTPUT_KEY_RE.test(vaultMap.key)) {
|
|
33344
|
-
throw new Error(`org project set: ${label}.vault.key must be UPPER_SNAKE`);
|
|
33355
|
+
throw new Error(`org project set: ${label}.vault.key must be UPPER_SNAKE or <dev|rc|main>/UPPER_SNAKE`);
|
|
33345
33356
|
}
|
|
33346
33357
|
if (value.overwrite !== void 0 && typeof value.overwrite !== "boolean") {
|
|
33347
33358
|
throw new Error(`org project set: ${label}.overwrite must be true or false`);
|
|
@@ -40963,13 +40974,30 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
40963
40974
|
}
|
|
40964
40975
|
const ciPolicy = await deps.resolveCiPolicy(repo);
|
|
40965
40976
|
base.ciPolicy = ciPolicy;
|
|
40977
|
+
const pinned = options.expectHead;
|
|
40978
|
+
if (pinned) base.pinnedHead = { expected: pinned };
|
|
40979
|
+
const headDrift = async (stage) => {
|
|
40980
|
+
if (!pinned) return void 0;
|
|
40981
|
+
if (!deps.readHeadSha) throw new Error("pinned head reader unavailable");
|
|
40982
|
+
const observed = await deps.readHeadSha(prNumber, repo);
|
|
40983
|
+
base.pinnedHead = { expected: pinned, observed };
|
|
40984
|
+
if (observed === pinned) return void 0;
|
|
40985
|
+
return {
|
|
40986
|
+
...base,
|
|
40987
|
+
pinnedHead: { ...base.pinnedHead, refused: "drift" },
|
|
40988
|
+
error: `pr land #${prNumber}: head ${observed} is not the pinned ${pinned} (${stage}) \u2014 refusing to land a head that was not checked (--expect-head)`
|
|
40989
|
+
};
|
|
40990
|
+
};
|
|
40991
|
+
const drift = await headDrift("before landing");
|
|
40992
|
+
if (drift) return drift;
|
|
40966
40993
|
const hasQueue = await deps.hasMergeQueue?.(repo, resolved.base) ?? false;
|
|
40967
40994
|
let queueSnapshot;
|
|
40995
|
+
const queued = { base: resolved.base, state: "queued" };
|
|
40968
40996
|
if (hasQueue) {
|
|
40969
|
-
base.mergeQueue = { base: resolved.base, state: "queued" };
|
|
40970
40997
|
if (!deps.readMergeQueue) throw new Error("merge queue reader unavailable");
|
|
40971
40998
|
queueSnapshot = await deps.readMergeQueue(prNumber, repo);
|
|
40972
40999
|
if (queueSnapshot.isInMergeQueue || queueSnapshot.state === "MERGED") {
|
|
41000
|
+
base.mergeQueue = queued;
|
|
40973
41001
|
base.mergeStatus = "auto-merge-enqueued";
|
|
40974
41002
|
return pollPrMergeQueue(prNumber, options, deps, base, queueSnapshot);
|
|
40975
41003
|
}
|
|
@@ -40986,7 +41014,16 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
40986
41014
|
base.checksWait = await deps.waitForChecks(prNumber, repo);
|
|
40987
41015
|
const waitError = checksWaitError(base.checksWait);
|
|
40988
41016
|
if (waitError) return { ...base, error: waitError };
|
|
41017
|
+
const driftAfterChecks = await headDrift("after checks");
|
|
41018
|
+
if (driftAfterChecks) return driftAfterChecks;
|
|
40989
41019
|
let prState = await deps.readPrState(prNumber, repo);
|
|
41020
|
+
if (pinned && prState.mergeStateStatus === "BEHIND") {
|
|
41021
|
+
return {
|
|
41022
|
+
...base,
|
|
41023
|
+
pinnedHead: { ...base.pinnedHead, refused: "behind" },
|
|
41024
|
+
error: `pr land #${prNumber}: head is BEHIND ${resolved.base} and pinned by --expect-head \u2014 refusing to update it. Update and re-check the head yourself, then land with the new SHA`
|
|
41025
|
+
};
|
|
41026
|
+
}
|
|
40990
41027
|
if (prState.mergeStateStatus === "BEHIND" && deps.updateBranch) {
|
|
40991
41028
|
try {
|
|
40992
41029
|
base.branchUpdated = await deps.updateBranch(prNumber, repo);
|
|
@@ -41010,6 +41047,7 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
41010
41047
|
return { ...base, error: merge.error ?? "merge failed" };
|
|
41011
41048
|
}
|
|
41012
41049
|
if (hasQueue) {
|
|
41050
|
+
base.mergeQueue = queued;
|
|
41013
41051
|
if (merge.mergeStatus === "merged") {
|
|
41014
41052
|
return queueMerged(base, deps);
|
|
41015
41053
|
}
|
|
@@ -41080,6 +41118,7 @@ async function pollPrMergeQueue(pr, options, deps, base, snapshot, deadlineMs) {
|
|
|
41080
41118
|
const result2 = {
|
|
41081
41119
|
...base,
|
|
41082
41120
|
mergeQueue: { ...base.mergeQueue, state: "ejected", ...run ? { ejectedRun: run } : {} },
|
|
41121
|
+
...base.pinnedHead ? { pinnedHead: { ...base.pinnedHead, refused: "ejected" } } : {},
|
|
41083
41122
|
error: `merge queue ejected PR #${pr} \u2014 ${run ? `merge_group run ${run.id} ${run.conclusion} ${run.url}` : "merge_group run not found"}`
|
|
41084
41123
|
};
|
|
41085
41124
|
deps.queueProgress?.(result2);
|
|
@@ -41105,7 +41144,7 @@ async function landMany(prs, landOne, cleanup, hooks) {
|
|
|
41105
41144
|
const safe = async (pr) => landOne(pr).catch((e) => ({ status: "failed", repo: "", pr, base: "", error: e.message }));
|
|
41106
41145
|
return Promise.all(prs.map(async (pr) => {
|
|
41107
41146
|
let result = await safe(pr);
|
|
41108
|
-
if (prLandOutcome(result) === "ejected") {
|
|
41147
|
+
if (prLandOutcome(result) === "ejected" && !result.pinnedHead) {
|
|
41109
41148
|
hooks?.onRetry?.(pr, result);
|
|
41110
41149
|
result = { ...await safe(pr), retriedAfterEjection: true };
|
|
41111
41150
|
}
|
|
@@ -41985,6 +42024,7 @@ function buildPrMergeArgs(input) {
|
|
|
41985
42024
|
const args = ["pr", "merge", input.number, ...input.repoArgs, input.method];
|
|
41986
42025
|
if (input.deleteBranch !== false) args.push("--delete-branch");
|
|
41987
42026
|
if (input.bodyFile) args.push("--body-file", input.bodyFile);
|
|
42027
|
+
if (input.matchHeadCommit) args.push("--match-head-commit", input.matchHeadCommit);
|
|
41988
42028
|
if (input.auto) args.push("--auto");
|
|
41989
42029
|
return args;
|
|
41990
42030
|
}
|
|
@@ -42226,12 +42266,12 @@ async function ghMergeAutoEnqueue(prNumber, repo, method, extra) {
|
|
|
42226
42266
|
bodyText: method === "--squash" ? extra?.bodyText : void 0
|
|
42227
42267
|
});
|
|
42228
42268
|
try {
|
|
42229
|
-
return await mergeAutoEnqueueWithBody(prNumber, args, method, io, overrideBody?.path, extra?.mergeQueue);
|
|
42269
|
+
return await mergeAutoEnqueueWithBody(prNumber, args, method, io, overrideBody?.path, extra?.mergeQueue, extra?.matchHeadCommit);
|
|
42230
42270
|
} finally {
|
|
42231
42271
|
overrideBody?.cleanup();
|
|
42232
42272
|
}
|
|
42233
42273
|
}
|
|
42234
|
-
async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, mergeQueue = false) {
|
|
42274
|
+
async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, mergeQueue = false, matchHeadCommit) {
|
|
42235
42275
|
const headRef = (await io.gh(["pr", "view", prNumber, ...args, "--json", "headRefName", "--jq", ".headRefName"], GC_GH_TIMEOUT_MS).catch(() => "")).trim();
|
|
42236
42276
|
const deleteBranch = !mergeQueue && !isProtectedBranch(headRef);
|
|
42237
42277
|
const readMergeState = () => readGhPrStateWithRetry(
|
|
@@ -42251,7 +42291,7 @@ async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, me
|
|
|
42251
42291
|
return s.ok && s.state === "MERGED";
|
|
42252
42292
|
},
|
|
42253
42293
|
reEnqueue: async () => {
|
|
42254
|
-
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch, bodyFile }), GH_MUTATION_TIMEOUT_MS);
|
|
42294
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch, bodyFile, matchHeadCommit }), GH_MUTATION_TIMEOUT_MS);
|
|
42255
42295
|
}
|
|
42256
42296
|
});
|
|
42257
42297
|
if (confirmation === "merged") return { mergeStatus: "merged" };
|
|
@@ -42259,7 +42299,7 @@ async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, me
|
|
|
42259
42299
|
return { mergeStatus: "failed", error: "auto-merge did not stick \u2014 GitHub reported no autoMergeRequest after enqueue; retry once the PR has a pending check" };
|
|
42260
42300
|
};
|
|
42261
42301
|
try {
|
|
42262
|
-
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch, bodyFile }), GH_MUTATION_TIMEOUT_MS);
|
|
42302
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch, bodyFile, matchHeadCommit }), GH_MUTATION_TIMEOUT_MS);
|
|
42263
42303
|
} catch (e) {
|
|
42264
42304
|
const message2 = String(e.message || "");
|
|
42265
42305
|
if (/already been merged/i.test(message2)) return { mergeStatus: "merged" };
|
|
@@ -42267,7 +42307,7 @@ async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, me
|
|
|
42267
42307
|
if (note) return { mergeStatus: "failed", error: note };
|
|
42268
42308
|
if (mergeAutoRejectedPrAlreadyClean(message2)) {
|
|
42269
42309
|
try {
|
|
42270
|
-
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: false, deleteBranch, bodyFile }), GH_MUTATION_TIMEOUT_MS);
|
|
42310
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: false, deleteBranch, bodyFile, matchHeadCommit }), GH_MUTATION_TIMEOUT_MS);
|
|
42271
42311
|
} catch (e2) {
|
|
42272
42312
|
const m2 = String(e2.message || "");
|
|
42273
42313
|
if (/already been merged/i.test(m2)) return { mergeStatus: "merged" };
|
|
@@ -42278,7 +42318,7 @@ async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, me
|
|
|
42278
42318
|
return { mergeStatus: "failed", error: `could not confirm PR state after clean-status fallback: ${afterDirect.error}` };
|
|
42279
42319
|
}
|
|
42280
42320
|
try {
|
|
42281
|
-
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch, bodyFile }), GH_MUTATION_TIMEOUT_MS);
|
|
42321
|
+
await io.gh(buildPrMergeArgs({ number: prNumber, repoArgs: args, method, auto: true, deleteBranch, bodyFile, matchHeadCommit }), GH_MUTATION_TIMEOUT_MS);
|
|
42282
42322
|
} catch (e3) {
|
|
42283
42323
|
const m3 = String(e3.message || "");
|
|
42284
42324
|
if (/already been merged/i.test(m3)) return { mergeStatus: "merged" };
|
|
@@ -47844,9 +47884,14 @@ ${list}`);
|
|
|
47844
47884
|
}
|
|
47845
47885
|
class PrHeadBehindBaseError extends Error {
|
|
47846
47886
|
}
|
|
47847
|
-
pr.command("land <numbers...>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only. Several PR numbers land together (#8322): all are enqueued, waited on together, a queue-ejected PR is updated and re-enqueued once, a queue merge is followed by worktree/branch cleanup and board Done, and one table (or --json) reports each outcome").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").option("--enqueue-only", "return once queue membership is confirmed; without a merge queue, land normally").option("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "acknowledge and land past a remaining prunable/severe scratch housekeeping block (advisory kept plans/ never blocks, #3012) or a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal").option("--without-review <reason>", "compatibility option; shared merge helpers do not require a review verdict").option("--timeout <minutes>", `merge-queue wait per PR (default ${PR_LAND_QUEUE_TIMEOUT_MS / 6e4} minutes, one window per ${PR_LAND_QUEUE_BATCH_SIZE} PRs \u2014 the queue's own check timeout is 60)`).option("--preserve-worktree", "after a queue merge keep the local worktree and branch (skips the post-merge cleanup)").action(async (numbers, opts) => {
|
|
47887
|
+
pr.command("land <numbers...>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only. Several PR numbers land together (#8322): all are enqueued, waited on together, a queue-ejected PR is updated and re-enqueued once, a queue merge is followed by worktree/branch cleanup and board Done, and one table (or --json) reports each outcome").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").option("--enqueue-only", "return once queue membership is confirmed; without a merge queue, land normally").option("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "acknowledge and land past a remaining prunable/severe scratch housekeeping block (advisory kept plans/ never blocks, #3012) or a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal").option("--without-review <reason>", "compatibility option; shared merge helpers do not require a review verdict").option("--timeout <minutes>", `merge-queue wait per PR (default ${PR_LAND_QUEUE_TIMEOUT_MS / 6e4} minutes, one window per ${PR_LAND_QUEUE_BATCH_SIZE} PRs \u2014 the queue's own check timeout is 60)`).option("--preserve-worktree", "after a queue merge keep the local worktree and branch (skips the post-merge cleanup)").option("--expect-head <sha>", "pin the PR head to this full 40-hex SHA (#8456): checked before landing, after checks and by GitHub at enqueue (--match-head-commit); never updates a BEHIND head and never retries an ejection \u2014 it stops with pinnedHead.refused instead. One PR only").action(async (numbers, opts) => {
|
|
47848
47888
|
const timeoutMinutes = opts.timeout === void 0 ? void 0 : Number(opts.timeout);
|
|
47849
47889
|
if (timeoutMinutes !== void 0 && !(timeoutMinutes > 0)) return fail("pr land: --timeout must be a positive number of minutes");
|
|
47890
|
+
if (opts.expectHead !== void 0) {
|
|
47891
|
+
if (!/^[0-9a-f]{40}$/i.test(opts.expectHead)) return fail("pr land: --expect-head needs the full 40-hex head SHA");
|
|
47892
|
+
if (numbers.length !== 1) return fail("pr land: --expect-head pins one PR head; land one PR per call");
|
|
47893
|
+
opts.expectHead = opts.expectHead.toLowerCase();
|
|
47894
|
+
}
|
|
47850
47895
|
const queueTimeoutMs = timeoutMinutes !== void 0 ? Math.round(timeoutMinutes * 6e4) : PR_LAND_QUEUE_TIMEOUT_MS * Math.ceil(numbers.length / PR_LAND_QUEUE_BATCH_SIZE);
|
|
47851
47896
|
let inFlight = numbers.length;
|
|
47852
47897
|
const landOne = async (numberArg) => {
|
|
@@ -47887,7 +47932,12 @@ ${list}`);
|
|
|
47887
47932
|
}
|
|
47888
47933
|
if (landClosingGuardVerdict.message) console.warn(landClosingGuardVerdict.message);
|
|
47889
47934
|
let mergeQueueEnabled = false;
|
|
47890
|
-
const result = await runPrLand(number, { repo: o.repo, requireTrain: o.requireTrain !== false, enqueueOnly: o.enqueueOnly, queueTimeoutMs }, {
|
|
47935
|
+
const result = await runPrLand(number, { repo: o.repo, requireTrain: o.requireTrain !== false, enqueueOnly: o.enqueueOnly, queueTimeoutMs, expectHead: o.expectHead }, {
|
|
47936
|
+
readHeadSha: async (prNumber, repo) => {
|
|
47937
|
+
const sha = (await fetchRestPrSnapshot(prNumber, repo)).headSha;
|
|
47938
|
+
if (!sha) throw new Error(`pr land: could not read the head SHA of PR #${prNumber}`);
|
|
47939
|
+
return sha.toLowerCase();
|
|
47940
|
+
},
|
|
47891
47941
|
pollDelayMs: (attempt) => prLandPollDelayMs(attempt, inFlight),
|
|
47892
47942
|
hasMergeQueue: async (repo, base) => mergeQueueEnabled = await hasPrMergeQueue(repo, base),
|
|
47893
47943
|
readMergeQueue: readPrMergeQueue,
|
|
@@ -47985,9 +48035,11 @@ ${list}`);
|
|
|
47985
48035
|
mergeAuto: (prNumber, repo) => ghMergeAutoEnqueue(prNumber, repo, "--squash", {
|
|
47986
48036
|
allowedClosing: landClosingGuardInput?.closing,
|
|
47987
48037
|
bodyText: landSquashBody,
|
|
47988
|
-
mergeQueue: mergeQueueEnabled
|
|
48038
|
+
mergeQueue: mergeQueueEnabled,
|
|
48039
|
+
matchHeadCommit: o.expectHead
|
|
47989
48040
|
}),
|
|
47990
|
-
|
|
48041
|
+
// #8456: a pinned land has no update lane at all.
|
|
48042
|
+
...o.expectHead ? {} : { updateBranch: (prNumber, repo) => prLandUpdateBranch(prNumber, repo, Boolean(o.repo)) },
|
|
47991
48043
|
pollMerged: async (prNumber, repo, deadlineMs) => {
|
|
47992
48044
|
let lastFailure;
|
|
47993
48045
|
while (Date.now() < deadlineMs) {
|
package/cli/package.json
CHANGED