@mutmutco/cli 4.5.55 → 4.5.57
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 +75 -16
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -5516,7 +5516,7 @@ function isSnapshotShape(body) {
|
|
|
5516
5516
|
const staleValid = b?.stale === void 0 || typeof b.stale === "object" && b.stale !== null && Number.isFinite(b.stale.ageMs) && b.stale.ageMs >= 0;
|
|
5517
5517
|
const githubValid = b?.github === void 0 || b.github.credential === "app_installation" && (rate === void 0 || Number.isFinite(rate?.limit) && Number.isFinite(rate?.remaining) && Number.isFinite(rate?.cost) && typeof rate?.resetAt === "string");
|
|
5518
5518
|
return Boolean(
|
|
5519
|
-
b && typeof b === "object" && typeof b.project?.id === "string" && typeof b.project?.title === "string" && typeof b.viewer === "string" && b.viewer.length > 0 && Array.isArray(b.nodes) && Array.isArray(b.writableRepos) && Array.isArray(b.unreadableRepos) && Array.isArray(b.pullRequests) && Array.isArray(b.warnings) && typeof b.partial === "boolean" && (b.eventCursor === void 0 || Number.isInteger(b.eventCursor) && b.eventCursor >= 0) && githubValid && staleValid
|
|
5519
|
+
b && typeof b === "object" && typeof b.project?.id === "string" && typeof b.project?.title === "string" && typeof b.viewer === "string" && b.viewer.length > 0 && Array.isArray(b.nodes) && Array.isArray(b.writableRepos) && Array.isArray(b.unreadableRepos) && Array.isArray(b.pullRequests) && Array.isArray(b.warnings) && typeof b.partial === "boolean" && (b.source === void 0 || b.source === "live" || b.source === "cache") && (b.builtAt === void 0 || typeof b.builtAt === "string" && Number.isFinite(Date.parse(b.builtAt))) && (b.eventCursor === void 0 || Number.isInteger(b.eventCursor) && b.eventCursor >= 0) && githubValid && staleValid
|
|
5520
5520
|
);
|
|
5521
5521
|
}
|
|
5522
5522
|
async function fetchHubBoardSnapshot(request, deps) {
|
|
@@ -7130,12 +7130,37 @@ function extractOnBlock(yaml) {
|
|
|
7130
7130
|
}
|
|
7131
7131
|
return block.length ? block.join("\n") : null;
|
|
7132
7132
|
}
|
|
7133
|
-
function
|
|
7133
|
+
function jobUsesWorkflow(job) {
|
|
7134
|
+
const match = job.body.match(/^\s+uses:\s*['"]?([^'"\s#]*\.github\/workflows\/[^'"\s#@]+\.ya?ml(?:@[^'"\s#]+)?)['"]?\s*(?:#.*)?$/m);
|
|
7135
|
+
return match ? match[1] : null;
|
|
7136
|
+
}
|
|
7137
|
+
function reusableWorkflowRefs(workflows) {
|
|
7138
|
+
const refs = /* @__PURE__ */ new Set();
|
|
7139
|
+
for (const wf of workflows) {
|
|
7140
|
+
if (!workflowTriggersPullRequest(wf.body)) continue;
|
|
7141
|
+
for (const job of parseWorkflowJobs(wf.body)) {
|
|
7142
|
+
const uses = jobUsesWorkflow(job);
|
|
7143
|
+
if (uses && jobReportsPullRequestCheck(job)) refs.add(uses);
|
|
7144
|
+
}
|
|
7145
|
+
}
|
|
7146
|
+
return [...refs];
|
|
7147
|
+
}
|
|
7148
|
+
function parseReusableWorkflowRef(uses) {
|
|
7149
|
+
const local = uses.match(/^\.\/(\.github\/workflows\/[^@]+)$/);
|
|
7150
|
+
if (local) return { path: local[1] };
|
|
7151
|
+
const remote = uses.match(/^([^/]+\/[^/]+)\/(\.github\/workflows\/[^@]+)@(.+)$/);
|
|
7152
|
+
return remote ? { repo: remote[1], path: remote[2], ref: remote[3] } : null;
|
|
7153
|
+
}
|
|
7154
|
+
function collectPullRequestWorkflowContexts(workflows, called = {}) {
|
|
7134
7155
|
const contexts = /* @__PURE__ */ new Set();
|
|
7135
7156
|
for (const wf of workflows) {
|
|
7136
7157
|
if (!workflowTriggersPullRequest(wf.body)) continue;
|
|
7137
7158
|
for (const job of parseWorkflowJobs(wf.body)) {
|
|
7138
|
-
if (jobReportsPullRequestCheck(job))
|
|
7159
|
+
if (!jobReportsPullRequestCheck(job)) continue;
|
|
7160
|
+
const uses = jobUsesWorkflow(job);
|
|
7161
|
+
const body = uses ? called[uses] : void 0;
|
|
7162
|
+
if (body) for (const inner of parseWorkflowJobs(body)) contexts.add(`${job.id} / ${inner.id}`);
|
|
7163
|
+
else contexts.add(job.id);
|
|
7139
7164
|
}
|
|
7140
7165
|
}
|
|
7141
7166
|
return [...contexts].sort((a, b) => a.localeCompare(b));
|
|
@@ -12358,7 +12383,7 @@ function renderBoardItem(item) {
|
|
|
12358
12383
|
return lines2.join("\n");
|
|
12359
12384
|
}
|
|
12360
12385
|
function renderBoardReport(report) {
|
|
12361
|
-
const lines2 = [`Board \xB7 ${report.project.title} \xB7 @${report.viewer}`, renderBoardSource()];
|
|
12386
|
+
const lines2 = [`Board \xB7 ${report.project.title} \xB7 @${report.viewer}`, report.source === "cache" ? "source: cache" : renderBoardSource()];
|
|
12362
12387
|
if (report.github?.rateLimit) {
|
|
12363
12388
|
const { limit, remaining, cost, resetAt } = report.github.rateLimit;
|
|
12364
12389
|
lines2.push(`github: app installation \xB7 GraphQL ${remaining}/${limit} remaining \xB7 cost ${cost} \xB7 resets ${resetAt}`);
|
|
@@ -12631,7 +12656,8 @@ async function readBoard(options, deps = {}) {
|
|
|
12631
12656
|
...groups,
|
|
12632
12657
|
warnings: collected.warnings,
|
|
12633
12658
|
partial: collected.partial,
|
|
12634
|
-
source: "live",
|
|
12659
|
+
source: snapshot?.source ?? "live",
|
|
12660
|
+
...snapshot?.builtAt ? { builtAt: snapshot.builtAt } : {},
|
|
12635
12661
|
...pullRequests ? { pullRequests } : {},
|
|
12636
12662
|
...eventCursor !== void 0 ? { eventCursor } : {},
|
|
12637
12663
|
...github ? { github } : {}
|
|
@@ -17043,10 +17069,10 @@ var rollout_plan_default = {
|
|
|
17043
17069
|
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)."
|
|
17044
17070
|
},
|
|
17045
17071
|
baseline: {
|
|
17046
|
-
version: "4.5.
|
|
17047
|
-
tag: "v4.5.
|
|
17048
|
-
commit: "
|
|
17049
|
-
npm: "@mutmutco/cli@4.5.
|
|
17072
|
+
version: "4.5.57",
|
|
17073
|
+
tag: "v4.5.57",
|
|
17074
|
+
commit: "d8aff7ba4689",
|
|
17075
|
+
npm: "@mutmutco/cli@4.5.57"
|
|
17050
17076
|
},
|
|
17051
17077
|
exitCriterion: "fleet-n-of-n",
|
|
17052
17078
|
hubOnlyShortcut: "forbidden",
|
|
@@ -17063,14 +17089,14 @@ var rollout_plan_default = {
|
|
|
17063
17089
|
repo: "mutmutco/mmi-hub",
|
|
17064
17090
|
role: "canary",
|
|
17065
17091
|
schedule: "train",
|
|
17066
|
-
v3Target: "v4.5.
|
|
17092
|
+
v3Target: "v4.5.57"
|
|
17067
17093
|
}
|
|
17068
17094
|
],
|
|
17069
17095
|
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.",
|
|
17070
17096
|
rollback: {
|
|
17071
17097
|
independent: true,
|
|
17072
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
17073
|
-
v3Target: "v4.5.
|
|
17098
|
+
mechanism: "npm dist-tag latest -> 4.5.57 and redeploy the Hub Lambda from tag v4.5.57 (d8aff7ba4689); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
17099
|
+
v3Target: "v4.5.57 (@mutmutco/cli@4.5.57, tag commit d8aff7ba4689 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
17074
17100
|
}
|
|
17075
17101
|
},
|
|
17076
17102
|
{
|
|
@@ -27278,7 +27304,17 @@ function gateWorkflowFiles(prWorkflowPaths) {
|
|
|
27278
27304
|
}
|
|
27279
27305
|
async function resolveEmittedPrContexts(deps, repo, branch) {
|
|
27280
27306
|
const workflows = await resolveBranchWorkflows(deps, repo, branch);
|
|
27281
|
-
return workflows === void 0 ? void 0 : collectPullRequestWorkflowContexts(workflows);
|
|
27307
|
+
return workflows === void 0 ? void 0 : collectPullRequestWorkflowContexts(workflows, await resolveCalledWorkflows(deps, repo, branch, workflows));
|
|
27308
|
+
}
|
|
27309
|
+
async function resolveCalledWorkflows(deps, repo, branch, workflows) {
|
|
27310
|
+
const called = {};
|
|
27311
|
+
for (const uses of reusableWorkflowRefs(workflows)) {
|
|
27312
|
+
const ref = parseReusableWorkflowRef(uses);
|
|
27313
|
+
if (!ref) continue;
|
|
27314
|
+
const body = await fetchFileContent(deps, ref.repo ?? repo, ref.ref ?? branch, ref.path);
|
|
27315
|
+
if (body) called[uses] = body;
|
|
27316
|
+
}
|
|
27317
|
+
return called;
|
|
27282
27318
|
}
|
|
27283
27319
|
async function resolveBranchWorkflows(deps, repo, branch) {
|
|
27284
27320
|
const paths = await listWorkflowPaths(deps, repo, branch);
|
|
@@ -27526,7 +27562,7 @@ async function auditRepoCi(repo, deps) {
|
|
|
27526
27562
|
};
|
|
27527
27563
|
const getEmittedPrContexts = async () => {
|
|
27528
27564
|
const workflows = await getBranchWorkflows();
|
|
27529
|
-
return workflows === void 0 ? void 0 : collectPullRequestWorkflowContexts(workflows);
|
|
27565
|
+
return workflows === void 0 ? void 0 : collectPullRequestWorkflowContexts(workflows, await resolveCalledWorkflows(deps, repo, baseBranch, workflows));
|
|
27530
27566
|
};
|
|
27531
27567
|
const committedReferenceRaw = deployableGated ? await fetchFileContent(deps, repo, baseBranch, PRODUCT_RULESET_REF) : null;
|
|
27532
27568
|
let authoritativeRuleset = null;
|
|
@@ -35281,7 +35317,13 @@ async function suiteRelease(deps, ownerGo) {
|
|
|
35281
35317
|
else rcAligned = await deps.sameContent(member.repo, member.sha, rcHead);
|
|
35282
35318
|
}
|
|
35283
35319
|
if (!sha || sha.toLowerCase() !== member.sha?.toLowerCase() || !member.released && !member.releasedAs && !rcAligned && rcHead?.toLowerCase() !== member.sha?.toLowerCase()) throw new Error(`${member.repo}: rc tag/branch ${member.tag} changed after the cut; release refused`);
|
|
35284
|
-
const
|
|
35320
|
+
const planned = member.releasedAs ?? suiteReleaseTag(member.tag);
|
|
35321
|
+
if (!member.released && !member.hotfixedTo && live.version !== member.backend && await deps.tagSha(member.repo, planned)) {
|
|
35322
|
+
const hotfix = await deps.hotfixOver(member.repo, planned, live.version);
|
|
35323
|
+
if (hotfix) member.hotfixedTo = hotfix;
|
|
35324
|
+
}
|
|
35325
|
+
if (member.hotfixedTo && !member.released) continue;
|
|
35326
|
+
const katipReleaseSha = member.id === "katip" ? await deps.tagSha(member.repo, planned) : void 0;
|
|
35285
35327
|
const expectedBackend = member.id === "katip" && member.released ? member.backendAfterRelease ?? katipReleaseSha : member.backend;
|
|
35286
35328
|
if (live.version !== expectedBackend && !(member.id === "katip" && !member.released && katipReleaseSha && live.version === katipReleaseSha))
|
|
35287
35329
|
throw new Error(`${member.repo}: live backend changed after the cut (${expectedBackend} \u2192 ${live.version}); release refused`);
|
|
@@ -35289,7 +35331,14 @@ async function suiteRelease(deps, ownerGo) {
|
|
|
35289
35331
|
if ((await deps.tagSha(SUITE_REPO, record.leadRcTag))?.toLowerCase() !== record.leadRcSha?.toLowerCase()) throw new Error("MM-Work rc tag changed after the cut; release refused");
|
|
35290
35332
|
for (const member of record.members) {
|
|
35291
35333
|
if (member.released || member.carried) continue;
|
|
35292
|
-
if (member.
|
|
35334
|
+
if (member.hotfixedTo) {
|
|
35335
|
+
console.warn(`${member.repo}: released as ${member.releasedAs ?? suiteReleaseTag(member.tag)} and hotfixed to ${member.hotfixedTo}, which is live; recorded as released (#7482)`);
|
|
35336
|
+
member.backendAfterRelease = (await deps.backend({ repo: member.repo, id: member.id, bundles: {} })).version;
|
|
35337
|
+
member.released = true;
|
|
35338
|
+
writeSuiteCut(deps.recordPath, record);
|
|
35339
|
+
continue;
|
|
35340
|
+
}
|
|
35341
|
+
if (member.releasedAs && member.releasedAs !== suiteReleaseTag(member.tag)) console.warn(`${member.repo}: its rc already shipped as ${member.releasedAs}, not ${suiteReleaseTag(member.tag)}; finishing that release (#7464)`);
|
|
35293
35342
|
await deps.release(member.repo, member.releasedAs ?? suiteReleaseTag(member.tag), member.sha);
|
|
35294
35343
|
if (member.id === "katip") {
|
|
35295
35344
|
const expected = await deps.tagSha(member.repo, member.releasedAs ?? suiteReleaseTag(member.tag));
|
|
@@ -45366,6 +45415,15 @@ function suiteTrainIo(root, summaryFile) {
|
|
|
45366
45415
|
const [a, b] = (await exec("git", ["rev-parse", `${candidate}^{tree}`, `${head}^{tree}`], target)).trim().split(/\s+/);
|
|
45367
45416
|
return !!a && a === b;
|
|
45368
45417
|
};
|
|
45418
|
+
const hotfixOver = async (repo, planned, liveSha) => {
|
|
45419
|
+
const target = await checkout(repo);
|
|
45420
|
+
await exec("git", ["fetch", "origin", "--tags"], target);
|
|
45421
|
+
const later = releaseTagsFrom(await exec("git", ["tag", "--contains", planned, "--list", "v*"], target)).filter((t) => t !== planned);
|
|
45422
|
+
for (const tag of later) {
|
|
45423
|
+
if ((await exec("git", ["rev-parse", `${tag}^{commit}`], target)).trim().toLowerCase() === liveSha.toLowerCase()) return tag;
|
|
45424
|
+
}
|
|
45425
|
+
return void 0;
|
|
45426
|
+
};
|
|
45369
45427
|
const rcRuns = async () => JSON.parse(await gh(["run", "list", "--repo", "mutmutco/MMI-Hub", "--workflow", "module-rc-publish.yml", "--event", "workflow_dispatch", "--limit", "100", "--json", "databaseId,displayTitle,conclusion,status,createdAt"]));
|
|
45370
45428
|
const watchRcRun = async (title, fields, reuse) => {
|
|
45371
45429
|
const since = Date.now() - 1e4;
|
|
@@ -45454,6 +45512,7 @@ function suiteTrainIo(root, summaryFile) {
|
|
|
45454
45512
|
release,
|
|
45455
45513
|
shippedTag,
|
|
45456
45514
|
sameContent: sameContent2,
|
|
45515
|
+
hotfixOver,
|
|
45457
45516
|
announce: async (record) => {
|
|
45458
45517
|
if (!summaryFile) throw new Error("suite announcement requires --announce-summary-file; outcome was not posted");
|
|
45459
45518
|
const result = await trainApplyDeps().announce?.({ repo: SUITE_REPO, tag: record.leadRcTag.replace(/-rc\.\d+$/, ""), summaryFile });
|
package/package.json
CHANGED