@mutmutco/codex-plugin 4.5.135 → 4.5.137
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/.codex-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +166 -18
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/skills/bootstrap/seeds/gate.template.yml +4 -2
- package/skills/bootstrap/seeds/suite-gate.template.yml +4 -2
- package/skills/bootstrap/seeds/suite-screens.template.yml +2 -0
package/cli/dist/main.cjs
CHANGED
|
@@ -14682,7 +14682,9 @@ async function claimOneBoardItem(ctx, selector, options) {
|
|
|
14682
14682
|
const wouldWrite = flatItem.assignees.length === 0 && (flatItem.status === "Todo" || flatItem.status === "In Progress" || flatItem.status === "In Review");
|
|
14683
14683
|
if (wouldWrite && !ctx.writable.has(flatItem.repository.toLowerCase())) {
|
|
14684
14684
|
throw new NotClaimableError(
|
|
14685
|
-
|
|
14685
|
+
// #8245: name the real source. With a Hub snapshot the probe is the Hub's server-side check for the
|
|
14686
|
+
// session login, not the local gh token, so `gh repo view --json viewerPermission` can disagree.
|
|
14687
|
+
`${flatItem.ref} is not claimable: no write access to ${flatItem.repository} for @${report.viewer} (read from the Hub board snapshot's access probe when one was used, else the token from ${describeTokenSource()})`,
|
|
14686
14688
|
{ ref: flatItem.ref }
|
|
14687
14689
|
);
|
|
14688
14690
|
}
|
|
@@ -17509,6 +17511,7 @@ function assertGitBashOnWindowsForJervHubRelease(repo, platform2 = process.platf
|
|
|
17509
17511
|
|
|
17510
17512
|
// src/train-apply-correlation.ts
|
|
17511
17513
|
var import_node_fs19 = require("node:fs");
|
|
17514
|
+
init_github_quota();
|
|
17512
17515
|
var import_node_path17 = require("node:path");
|
|
17513
17516
|
|
|
17514
17517
|
// src/fleet-lockstep-enforce.ts
|
|
@@ -18274,10 +18277,10 @@ var rollout_plan_default = {
|
|
|
18274
18277
|
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)."
|
|
18275
18278
|
},
|
|
18276
18279
|
baseline: {
|
|
18277
|
-
version: "4.5.
|
|
18278
|
-
tag: "v4.5.
|
|
18279
|
-
commit: "
|
|
18280
|
-
npm: "@mutmutco/cli@4.5.
|
|
18280
|
+
version: "4.5.137",
|
|
18281
|
+
tag: "v4.5.137",
|
|
18282
|
+
commit: "5d0403299d67",
|
|
18283
|
+
npm: "@mutmutco/cli@4.5.137"
|
|
18281
18284
|
},
|
|
18282
18285
|
exitCriterion: "fleet-n-of-n",
|
|
18283
18286
|
hubOnlyShortcut: "forbidden",
|
|
@@ -18294,14 +18297,14 @@ var rollout_plan_default = {
|
|
|
18294
18297
|
repo: "mutmutco/mmi-hub",
|
|
18295
18298
|
role: "canary",
|
|
18296
18299
|
schedule: "train",
|
|
18297
|
-
v3Target: "v4.5.
|
|
18300
|
+
v3Target: "v4.5.137"
|
|
18298
18301
|
}
|
|
18299
18302
|
],
|
|
18300
18303
|
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.",
|
|
18301
18304
|
rollback: {
|
|
18302
18305
|
independent: true,
|
|
18303
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
18304
|
-
v3Target: "v4.5.
|
|
18306
|
+
mechanism: "npm dist-tag latest -> 4.5.137 and redeploy the Hub Lambda from tag v4.5.137 (5d0403299d67); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
18307
|
+
v3Target: "v4.5.137 (@mutmutco/cli@4.5.137, tag commit 5d0403299d67 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
18305
18308
|
}
|
|
18306
18309
|
},
|
|
18307
18310
|
{
|
|
@@ -20419,11 +20422,22 @@ async function loadReleaseTrackBranchHints(deps) {
|
|
|
20419
20422
|
]);
|
|
20420
20423
|
return { hasDevelopmentBranch, hasMainBranch, hasRcBranch };
|
|
20421
20424
|
}
|
|
20425
|
+
async function readTrainLogin(deps, waitMs = 18e4, attempts = 5) {
|
|
20426
|
+
for (let i = 1; ; i++) {
|
|
20427
|
+
try {
|
|
20428
|
+
return requireValue(clean2(await deps.run("gh", ["api", "user", "--jq", ".login"])), "GitHub login");
|
|
20429
|
+
} catch (e) {
|
|
20430
|
+
if (i >= attempts || !isRateLimitText(e instanceof Error ? e.message : String(e))) throw e;
|
|
20431
|
+
deps.warn?.(`GitHub login read rate-limited; retrying in ${waitMs / 6e4} min (${i}/${attempts - 1})`);
|
|
20432
|
+
await resolveSleep(deps)(waitMs);
|
|
20433
|
+
}
|
|
20434
|
+
}
|
|
20435
|
+
}
|
|
20422
20436
|
async function buildTrainApplyContext(deps) {
|
|
20423
20437
|
const repo = requireValue(clean2(await deps.run("gh", ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"])), "repo");
|
|
20424
20438
|
const [owner, name] = repo.split("/");
|
|
20425
20439
|
if (!owner || !name) throw new Error(`repo must be owner/name, got ${repo}`);
|
|
20426
|
-
const login =
|
|
20440
|
+
const login = await readTrainLogin(deps);
|
|
20427
20441
|
const verdict = await deps.trainAuthority(repo);
|
|
20428
20442
|
if (!verdict.ok) throw new Error(`${commandAuthorityLabel(owner)}: train authority could not be verified (${verdict.error})`);
|
|
20429
20443
|
if (!verdict.train) {
|
|
@@ -22443,7 +22457,7 @@ async function runTenantRedeploy(deps, options) {
|
|
|
22443
22457
|
const repo = options.repo;
|
|
22444
22458
|
const [owner, name] = repo.split("/");
|
|
22445
22459
|
if (!owner || !name) throw new Error(`repo must be owner/name, got ${repo}`);
|
|
22446
|
-
const login =
|
|
22460
|
+
const login = await readTrainLogin(deps);
|
|
22447
22461
|
const verdict = await deps.trainAuthority(repo);
|
|
22448
22462
|
if (!verdict.ok) throw new Error(`${commandAuthorityLabel(owner)}: train authority could not be verified (${verdict.error})`);
|
|
22449
22463
|
if (!verdict.train) throw new Error(`${commandAuthorityLabel(owner)}: @${login} is ${verdict.role} \u2014 no train authority on ${repo}`);
|
|
@@ -39845,6 +39859,7 @@ function boardAdvanceFailureMessage(result) {
|
|
|
39845
39859
|
}
|
|
39846
39860
|
|
|
39847
39861
|
// src/pr-land.ts
|
|
39862
|
+
var PR_LAND_QUEUE_TIMEOUT_MS = 45 * 6e4;
|
|
39848
39863
|
function prHeadBehindBase(input) {
|
|
39849
39864
|
if ((input.mergeStateStatus ?? "").toUpperCase() === "BEHIND") return true;
|
|
39850
39865
|
return /out[- ]of[- ]date|not up to date|up to date with the base|update (?:the|your) branch/i.test(input.message ?? "");
|
|
@@ -39968,6 +39983,17 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
39968
39983
|
}
|
|
39969
39984
|
const ciPolicy = await deps.resolveCiPolicy(repo);
|
|
39970
39985
|
base.ciPolicy = ciPolicy;
|
|
39986
|
+
const hasQueue = await deps.hasMergeQueue?.(repo, resolved.base) ?? false;
|
|
39987
|
+
let queueSnapshot;
|
|
39988
|
+
if (hasQueue) {
|
|
39989
|
+
base.mergeQueue = { base: resolved.base, state: "queued" };
|
|
39990
|
+
if (!deps.readMergeQueue) throw new Error("merge queue reader unavailable");
|
|
39991
|
+
queueSnapshot = await deps.readMergeQueue(prNumber, repo);
|
|
39992
|
+
if (queueSnapshot.isInMergeQueue || queueSnapshot.state === "MERGED") {
|
|
39993
|
+
base.mergeStatus = "auto-merge-enqueued";
|
|
39994
|
+
return pollPrMergeQueue(prNumber, options, deps, base, queueSnapshot);
|
|
39995
|
+
}
|
|
39996
|
+
}
|
|
39971
39997
|
const checksWaitError = (checksWait) => {
|
|
39972
39998
|
if (checksWait.status === "conflicting") {
|
|
39973
39999
|
return `checks-wait conflicting: ${checksWait.reason ?? "PR is conflicting with the base branch"}`;
|
|
@@ -40003,6 +40029,14 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
40003
40029
|
if (merge.mergeStatus === "failed") {
|
|
40004
40030
|
return { ...base, error: merge.error ?? "merge failed" };
|
|
40005
40031
|
}
|
|
40032
|
+
if (hasQueue) {
|
|
40033
|
+
if (merge.mergeStatus === "merged") {
|
|
40034
|
+
return queueMerged(base, deps);
|
|
40035
|
+
}
|
|
40036
|
+
const deadline = (deps.now ?? (() => Date.now()))() + PR_LAND_QUEUE_TIMEOUT_MS;
|
|
40037
|
+
await (deps.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms))))(PR_LAND_POLL_MS);
|
|
40038
|
+
return pollPrMergeQueue(prNumber, options, deps, base, void 0, deadline);
|
|
40039
|
+
}
|
|
40006
40040
|
if (merge.mergeStatus === "merged") {
|
|
40007
40041
|
return {
|
|
40008
40042
|
...base,
|
|
@@ -40025,6 +40059,53 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
40025
40059
|
error: "auto-merge enqueued but PR did not reach MERGED within timeout \u2014 poll manually with gh pr view"
|
|
40026
40060
|
};
|
|
40027
40061
|
}
|
|
40062
|
+
function queueMerged(base, deps) {
|
|
40063
|
+
const result = {
|
|
40064
|
+
...base,
|
|
40065
|
+
status: "merged-via-queue",
|
|
40066
|
+
mergeStatus: "merged",
|
|
40067
|
+
mergeQueue: { ...base.mergeQueue, state: "merged" },
|
|
40068
|
+
branchFinality: prLandedBranchFinality(base.pr, base.base)
|
|
40069
|
+
};
|
|
40070
|
+
deps.queueProgress?.(result);
|
|
40071
|
+
return result;
|
|
40072
|
+
}
|
|
40073
|
+
async function pollPrMergeQueue(pr, options, deps, base, snapshot, deadlineMs) {
|
|
40074
|
+
const now = deps.now ?? (() => Date.now());
|
|
40075
|
+
const sleep2 = deps.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
40076
|
+
const deadline = deadlineMs ?? now() + PR_LAND_QUEUE_TIMEOUT_MS;
|
|
40077
|
+
while (now() < deadline) {
|
|
40078
|
+
const read = snapshot ?? await deps.readMergeQueue(pr, base.repo);
|
|
40079
|
+
snapshot = void 0;
|
|
40080
|
+
if (read.state === "MERGED") return queueMerged(base, deps);
|
|
40081
|
+
if (read.isInMergeQueue) {
|
|
40082
|
+
base.mergeQueue = {
|
|
40083
|
+
base: base.base,
|
|
40084
|
+
state: "queued",
|
|
40085
|
+
...read.mergeQueueEntry ? { position: read.mergeQueueEntry.position, entryState: read.mergeQueueEntry.state } : {}
|
|
40086
|
+
};
|
|
40087
|
+
deps.queueProgress?.(base);
|
|
40088
|
+
if (options.enqueueOnly) return { ...base, status: "queued" };
|
|
40089
|
+
} else if (read.state === "OPEN" && !read.autoMergeRequest) {
|
|
40090
|
+
const run = await deps.findMergeGroupRun(pr, base.repo, base.base);
|
|
40091
|
+
const result2 = {
|
|
40092
|
+
...base,
|
|
40093
|
+
mergeQueue: { ...base.mergeQueue, state: "ejected", ...run ? { ejectedRun: run } : {} },
|
|
40094
|
+
error: `merge queue ejected PR #${pr} \u2014 ${run ? `merge_group run ${run.id} ${run.conclusion} ${run.url}` : "merge_group run not found"}`
|
|
40095
|
+
};
|
|
40096
|
+
deps.queueProgress?.(result2);
|
|
40097
|
+
return result2;
|
|
40098
|
+
}
|
|
40099
|
+
await sleep2(PR_LAND_POLL_MS);
|
|
40100
|
+
}
|
|
40101
|
+
const result = {
|
|
40102
|
+
...base,
|
|
40103
|
+
mergeQueue: { ...base.mergeQueue, state: "timeout" },
|
|
40104
|
+
error: "merge queue did not reach MERGED within 45 minutes \u2014 rerun pr land to resume polling"
|
|
40105
|
+
};
|
|
40106
|
+
deps.queueProgress?.(result);
|
|
40107
|
+
return result;
|
|
40108
|
+
}
|
|
40028
40109
|
|
|
40029
40110
|
// src/test-policy-core.ts
|
|
40030
40111
|
var import_node_child_process13 = require("node:child_process");
|
|
@@ -41085,18 +41166,19 @@ async function ghMergeAutoEnqueue(prNumber, repo, method, extra) {
|
|
|
41085
41166
|
bodyText: method === "--squash" ? extra?.bodyText : void 0
|
|
41086
41167
|
});
|
|
41087
41168
|
try {
|
|
41088
|
-
return await mergeAutoEnqueueWithBody(prNumber, args, method, io, overrideBody?.path);
|
|
41169
|
+
return await mergeAutoEnqueueWithBody(prNumber, args, method, io, overrideBody?.path, extra?.mergeQueue);
|
|
41089
41170
|
} finally {
|
|
41090
41171
|
overrideBody?.cleanup();
|
|
41091
41172
|
}
|
|
41092
41173
|
}
|
|
41093
|
-
async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile) {
|
|
41174
|
+
async function mergeAutoEnqueueWithBody(prNumber, args, method, io, bodyFile, mergeQueue = false) {
|
|
41094
41175
|
const headRef = (await io.gh(["pr", "view", prNumber, ...args, "--json", "headRefName", "--jq", ".headRefName"], GC_GH_TIMEOUT_MS).catch(() => "")).trim();
|
|
41095
41176
|
const deleteBranch = !isProtectedBranch(headRef);
|
|
41096
41177
|
const readMergeState = () => readGhPrStateWithRetry(
|
|
41097
41178
|
() => io.gh(["pr", "view", prNumber, ...args, "--json", "state", "--jq", ".state"], GC_GH_TIMEOUT_MS)
|
|
41098
41179
|
);
|
|
41099
41180
|
const confirmEnqueueOutcome = async () => {
|
|
41181
|
+
if (mergeQueue) return { mergeStatus: "auto-merge-enqueued" };
|
|
41100
41182
|
const stateRead = await readMergeState();
|
|
41101
41183
|
if (!stateRead.ok) {
|
|
41102
41184
|
return { mergeStatus: "failed", error: `could not read PR state after merge: ${stateRead.error}` };
|
|
@@ -41872,6 +41954,57 @@ function applyChecklistCheck(body, query, checked) {
|
|
|
41872
41954
|
return { ok: true, edit: setChecklistMarker(body, sel.item, checked), item: sel.item };
|
|
41873
41955
|
}
|
|
41874
41956
|
|
|
41957
|
+
// src/pr-merge-queue.ts
|
|
41958
|
+
init_cli_shared();
|
|
41959
|
+
var readApi = async (args) => {
|
|
41960
|
+
const env = await ghReadEnv();
|
|
41961
|
+
return (await execFileP("gh", ["api", ...args], {
|
|
41962
|
+
timeout: 2e4,
|
|
41963
|
+
...env ? { env } : {}
|
|
41964
|
+
})).stdout;
|
|
41965
|
+
};
|
|
41966
|
+
async function queueGraphql(repo, fields, gh2) {
|
|
41967
|
+
const [owner, name] = repo.split("/");
|
|
41968
|
+
const response = JSON.parse(await gh2(["graphql", "-f", `query=query { repository(owner:${JSON.stringify(owner)},name:${JSON.stringify(name)}) { ${fields} } }`]));
|
|
41969
|
+
if (response.errors?.length) throw new Error(response.errors.map((e) => e.message).join("; "));
|
|
41970
|
+
if (!response.data?.repository) throw new Error("merge queue repository read failed");
|
|
41971
|
+
return response.data.repository;
|
|
41972
|
+
}
|
|
41973
|
+
async function hasPrMergeQueue(repo, base, gh2 = readApi) {
|
|
41974
|
+
const result = await queueGraphql(repo, `mergeQueue(branch:${JSON.stringify(base)}) { id }`, gh2);
|
|
41975
|
+
return result.mergeQueue !== null;
|
|
41976
|
+
}
|
|
41977
|
+
async function readPrMergeQueue(pr, repo, gh2 = readApi) {
|
|
41978
|
+
if (!/^\d+$/.test(pr)) throw new Error("merge queue read requires a PR number");
|
|
41979
|
+
const result = await queueGraphql(
|
|
41980
|
+
repo,
|
|
41981
|
+
`pullRequest(number:${pr}) { state isInMergeQueue mergeQueueEntry { state position } autoMergeRequest { enabledAt } }`,
|
|
41982
|
+
gh2
|
|
41983
|
+
);
|
|
41984
|
+
if (!result.pullRequest) throw new Error(`merge queue PR #${pr} not found`);
|
|
41985
|
+
return result.pullRequest;
|
|
41986
|
+
}
|
|
41987
|
+
async function findPrMergeGroupRun(pr, repo, base, gh2 = readApi) {
|
|
41988
|
+
const pages = JSON.parse(await gh2([`repos/${repo}/actions/runs?event=merge_group&per_page=100`, "--paginate", "--slurp"]));
|
|
41989
|
+
const prefix = `gh-readonly-queue/${base}/pr-${pr}-`;
|
|
41990
|
+
const run = pages.flatMap((page) => page.workflow_runs).filter((run2) => run2.head_branch?.startsWith(prefix)).sort((a, b) => b.created_at.localeCompare(a.created_at) || b.id - a.id)[0];
|
|
41991
|
+
return run ? { id: run.id, url: run.html_url, conclusion: run.conclusion } : void 0;
|
|
41992
|
+
}
|
|
41993
|
+
function prMergeQueueLine(result) {
|
|
41994
|
+
const queue = result.mergeQueue;
|
|
41995
|
+
if (!queue) return void 0;
|
|
41996
|
+
switch (queue.state) {
|
|
41997
|
+
case "queued":
|
|
41998
|
+
return `pr land: PR #${result.pr} queued on ${queue.base}${queue.position === void 0 ? "" : ` (position ${queue.position})`}`;
|
|
41999
|
+
case "merged":
|
|
42000
|
+
return `pr land: PR #${result.pr} merged via merge queue`;
|
|
42001
|
+
case "ejected":
|
|
42002
|
+
return `pr land: PR #${result.pr} ejected from merge queue \u2014 ${queue.ejectedRun ? `merge_group run ${queue.ejectedRun.id} ${queue.ejectedRun.conclusion} ${queue.ejectedRun.url}` : "merge_group run not found"}`;
|
|
42003
|
+
case "timeout":
|
|
42004
|
+
return `pr land: PR #${result.pr} merge queue timeout on ${queue.base}`;
|
|
42005
|
+
}
|
|
42006
|
+
}
|
|
42007
|
+
|
|
41875
42008
|
// src/command-register-collaboration.ts
|
|
41876
42009
|
init_github_client();
|
|
41877
42010
|
init_github_quota();
|
|
@@ -46819,7 +46952,7 @@ ${list}`);
|
|
|
46819
46952
|
}
|
|
46820
46953
|
class PrHeadBehindBaseError extends Error {
|
|
46821
46954
|
}
|
|
46822
|
-
pr.command("land <number>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").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").action(async (number, o) => {
|
|
46955
|
+
pr.command("land <number>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only").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").action(async (number, o) => {
|
|
46823
46956
|
if (/^(?:[^/]+\/[^/]+)?#\d+$/.test(number.trim())) {
|
|
46824
46957
|
try {
|
|
46825
46958
|
const parsed = parseIssueRef(number, o.repo);
|
|
@@ -46854,7 +46987,14 @@ ${list}`);
|
|
|
46854
46987
|
return;
|
|
46855
46988
|
}
|
|
46856
46989
|
if (landClosingGuardVerdict.message) console.warn(landClosingGuardVerdict.message);
|
|
46857
|
-
|
|
46990
|
+
let mergeQueueEnabled = false;
|
|
46991
|
+
const result = await runPrLand(number, { repo: o.repo, requireTrain: o.requireTrain !== false, enqueueOnly: o.enqueueOnly }, {
|
|
46992
|
+
hasMergeQueue: async (repo, base) => mergeQueueEnabled = await hasPrMergeQueue(repo, base),
|
|
46993
|
+
readMergeQueue: readPrMergeQueue,
|
|
46994
|
+
findMergeGroupRun: findPrMergeGroupRun,
|
|
46995
|
+
queueProgress: (receipt) => {
|
|
46996
|
+
if (!o.json) printLine(prMergeQueueLine(receipt));
|
|
46997
|
+
},
|
|
46858
46998
|
resolveRepo: async (prNumber, repoOpt) => {
|
|
46859
46999
|
const knownRepo = repoOpt ?? await resolveRepo(o.repo).catch(() => void 0) ?? o.repo;
|
|
46860
47000
|
let repoFromGh = "";
|
|
@@ -46944,7 +47084,8 @@ ${list}`);
|
|
|
46944
47084
|
},
|
|
46945
47085
|
mergeAuto: (prNumber, repo) => ghMergeAutoEnqueue(prNumber, repo, "--squash", {
|
|
46946
47086
|
allowedClosing: landClosingGuardInput?.closing,
|
|
46947
|
-
bodyText: landSquashBody
|
|
47087
|
+
bodyText: landSquashBody,
|
|
47088
|
+
mergeQueue: mergeQueueEnabled
|
|
46948
47089
|
}),
|
|
46949
47090
|
updateBranch: (prNumber, repo) => prLandUpdateBranch(prNumber, repo, Boolean(o.repo)),
|
|
46950
47091
|
pollMerged: async (prNumber, repo, deadlineMs) => {
|
|
@@ -46968,7 +47109,7 @@ ${list}`);
|
|
|
46968
47109
|
return false;
|
|
46969
47110
|
}
|
|
46970
47111
|
});
|
|
46971
|
-
if (result.status !== "failed") {
|
|
47112
|
+
if (result.status !== "failed" && result.status !== "queued") {
|
|
46972
47113
|
const boardAdvance = await advanceClosedIssuesToDone2(number, result.repo);
|
|
46973
47114
|
const crossRepoFilingIssue = result.repo ? await reconcileCrossRepoFilingIssue(defaultGitHubClient(), result.repo, Number(number)) : { status: "failed", error: "could not resolve the PR repo for cross-repo filing-issue reconciliation" };
|
|
46974
47115
|
const recovery = result.repo ? buildPostMergeReconRecovery({
|
|
@@ -47620,7 +47761,13 @@ function trainApplyDeps() {
|
|
|
47620
47761
|
// Slack release announcement (#883/#6521/#6523): the org alerts channel for the Hub, the project's own
|
|
47621
47762
|
// registry releaseChannel META for a product repo — best-effort inside announceRelease itself.
|
|
47622
47763
|
announce: (args) => announceRelease({
|
|
47623
|
-
|
|
47764
|
+
// #8236: the announcement reads an already-PUBLISHED Release, so its `release view` rides the App
|
|
47765
|
+
// read pool like the train's other reads (#8030), never the owner's personal REST quota. Scoped
|
|
47766
|
+
// here, not in isAppRoutableGhReadArgs: other train paths may view a draft the App cannot see.
|
|
47767
|
+
run: async (file, cmdArgs) => {
|
|
47768
|
+
const env = file === "gh" && (cmdArgs[0] === "release" && cmdArgs[1] === "view" || isAppRoutableGhReadArgs(cmdArgs)) ? await ghReadEnv() : void 0;
|
|
47769
|
+
return (await execFileP(file, cmdArgs, { timeout: GH_TRAIN_TIMEOUT_MS, ...env ? { env } : {} })).stdout;
|
|
47770
|
+
},
|
|
47624
47771
|
postAnnouncement: async (payload) => {
|
|
47625
47772
|
const res = await releaseAnnouncement(payload, registryClientDeps(await loadConfig()));
|
|
47626
47773
|
const body = res.body;
|
|
@@ -50919,7 +51066,8 @@ var surfaces_default = {
|
|
|
50919
51066
|
],
|
|
50920
51067
|
outputs: [
|
|
50921
51068
|
"cli/dist/index.cjs",
|
|
50922
|
-
"cli/dist/main.cjs"
|
|
51069
|
+
"cli/dist/main.cjs",
|
|
51070
|
+
"cli/dist/runbook-sweep.cjs"
|
|
50923
51071
|
]
|
|
50924
51072
|
}
|
|
50925
51073
|
],
|
package/cli/package.json
CHANGED
package/package.json
CHANGED
|
@@ -34,6 +34,8 @@ name: gate
|
|
|
34
34
|
# (seed touch: keep BOM digests in lockstep after classifier land.)
|
|
35
35
|
on:
|
|
36
36
|
pull_request:
|
|
37
|
+
merge_group:
|
|
38
|
+
types: [checks_requested]
|
|
37
39
|
push:
|
|
38
40
|
branches: {{GATE_PUSH_BRANCHES_YAML}}
|
|
39
41
|
tags: ['v*']
|
|
@@ -99,10 +101,10 @@ jobs:
|
|
|
99
101
|
lockfile-path: {{GATE_CACHE_DEP_PATH}}
|
|
100
102
|
fetch-depth: 0 # #8129: runbook freshness needs the PR merge-base history.
|
|
101
103
|
- name: Runbook guard
|
|
102
|
-
if: ${{ steps.development-gate.outputs.reuse != 'true' && (github.event_name == 'pull_request') }}
|
|
104
|
+
if: ${{ steps.development-gate.outputs.reuse != 'true' && (github.event_name == 'pull_request' || github.event_name == 'merge_group') }}
|
|
103
105
|
uses: mutmutco/MMI-Hub/.github/actions/runbook-guard@{{GATE_RUNBOOK_SHA}}
|
|
104
106
|
with:
|
|
105
|
-
base-ref:
|
|
107
|
+
base-ref: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_sha || format('origin/{0}', github.base_ref) }}
|
|
106
108
|
# #5427: per-job npm cache under $RUNNER_TEMP — never the shared ~/.npm. Twelve mmi-live lanes
|
|
107
109
|
# share the gha-runner home; npm hardlinks from that cache into node_modules, so one job's
|
|
108
110
|
# `npm ci` can make another job's vitest/dist/workers/forks.js vanish mid-suite (Cannot find
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
name: gate
|
|
2
2
|
on:
|
|
3
3
|
pull_request:
|
|
4
|
+
merge_group:
|
|
5
|
+
types: [checks_requested]
|
|
4
6
|
push:
|
|
5
7
|
branches: {{GATE_PUSH_BRANCHES_YAML}}
|
|
6
8
|
tags: ['v*']
|
|
@@ -49,10 +51,10 @@ jobs:
|
|
|
49
51
|
lockfile-path: package-lock.json
|
|
50
52
|
fetch-depth: 0 # #8129: runbook freshness needs the PR merge-base history.
|
|
51
53
|
- name: Runbook guard
|
|
52
|
-
if: ${{ steps.development-gate.outputs.reuse != 'true' && (github.event_name == 'pull_request') }}
|
|
54
|
+
if: ${{ steps.development-gate.outputs.reuse != 'true' && (github.event_name == 'pull_request' || github.event_name == 'merge_group') }}
|
|
53
55
|
uses: mutmutco/MMI-Hub/.github/actions/runbook-guard@{{GATE_RUNBOOK_SHA}}
|
|
54
56
|
with:
|
|
55
|
-
base-ref:
|
|
57
|
+
base-ref: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_sha || format('origin/{0}', github.base_ref) }}
|
|
56
58
|
- name: Isolate npm cache
|
|
57
59
|
if: ${{ steps.development-gate.outputs.reuse != 'true' }}
|
|
58
60
|
run: echo "NPM_CONFIG_CACHE=$RUNNER_TEMP/npm-cache" >> "$GITHUB_ENV"
|