@mutmutco/cli 3.30.0 → 3.31.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 +45 -20
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -9277,31 +9277,45 @@ async function activateProductRuleset(repo, rulesetBody, client) {
|
|
|
9277
9277
|
}
|
|
9278
9278
|
|
|
9279
9279
|
// src/workflow-context.ts
|
|
9280
|
-
function
|
|
9280
|
+
function parseWorkflowJobs(yaml) {
|
|
9281
9281
|
const lines = yaml.split(/\r?\n/);
|
|
9282
9282
|
let inJobs = false;
|
|
9283
9283
|
let jobIndent = -1;
|
|
9284
|
-
const
|
|
9284
|
+
const jobs = [];
|
|
9285
|
+
let current = null;
|
|
9285
9286
|
for (const line of lines) {
|
|
9286
9287
|
if (!inJobs) {
|
|
9287
9288
|
if (/^jobs:\s*$/.test(line)) inJobs = true;
|
|
9288
9289
|
continue;
|
|
9289
9290
|
}
|
|
9290
9291
|
if (/^\S/.test(line) && !line.startsWith("#")) break;
|
|
9291
|
-
const trimmed = line.trim();
|
|
9292
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
9293
9292
|
const match = line.match(/^(\s+)([A-Za-z0-9_-]+):\s*$/);
|
|
9294
|
-
if (
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
jobIndent
|
|
9298
|
-
|
|
9299
|
-
|
|
9293
|
+
if (match) {
|
|
9294
|
+
const indent = match[1].length;
|
|
9295
|
+
if (jobIndent < 0) jobIndent = indent;
|
|
9296
|
+
if (indent === jobIndent) {
|
|
9297
|
+
current = { id: match[2], body: line, indent };
|
|
9298
|
+
jobs.push(current);
|
|
9299
|
+
continue;
|
|
9300
|
+
}
|
|
9301
|
+
if (indent < jobIndent) break;
|
|
9300
9302
|
}
|
|
9301
|
-
if (
|
|
9302
|
-
|
|
9303
|
+
if (current) current.body += `
|
|
9304
|
+
${line}`;
|
|
9303
9305
|
}
|
|
9304
|
-
return
|
|
9306
|
+
return jobs;
|
|
9307
|
+
}
|
|
9308
|
+
function jobReportsPullRequestCheck(job) {
|
|
9309
|
+
const lines = job.body.split(/\r?\n/).slice(1);
|
|
9310
|
+
const propertyIndent = lines.filter((line) => line.trim() && !line.trimStart().startsWith("#")).map((line) => line.match(/^(\s+)/)?.[1].length ?? 0).filter((indent) => indent > job.indent).reduce((minimum, indent) => Math.min(minimum, indent), Number.POSITIVE_INFINITY);
|
|
9311
|
+
if (!Number.isFinite(propertyIndent)) return true;
|
|
9312
|
+
const directIf = lines.find((line) => {
|
|
9313
|
+
const match = line.match(/^(\s*)if:\s*(.+)$/);
|
|
9314
|
+
return match?.[1].length === propertyIndent;
|
|
9315
|
+
});
|
|
9316
|
+
if (!directIf) return true;
|
|
9317
|
+
const expression = directIf.replace(/^\s*if:\s*/, "").trim().replace(/^\$\{\{\s*/, "").replace(/\s*\}\}$/, "").trim();
|
|
9318
|
+
return !/^(?:github\.event_name\s*==\s*['"]push['"]|['"]push['"]\s*==\s*github\.event_name)$/.test(expression);
|
|
9305
9319
|
}
|
|
9306
9320
|
function workflowTriggersPullRequest(yaml) {
|
|
9307
9321
|
const onBlock = extractOnBlock(yaml);
|
|
@@ -9340,7 +9354,9 @@ function collectPullRequestWorkflowContexts(workflows) {
|
|
|
9340
9354
|
const contexts = /* @__PURE__ */ new Set();
|
|
9341
9355
|
for (const wf of workflows) {
|
|
9342
9356
|
if (!workflowTriggersPullRequest(wf.body)) continue;
|
|
9343
|
-
for (const
|
|
9357
|
+
for (const job of parseWorkflowJobs(wf.body)) {
|
|
9358
|
+
if (jobReportsPullRequestCheck(job)) contexts.add(job.id);
|
|
9359
|
+
}
|
|
9344
9360
|
}
|
|
9345
9361
|
return [...contexts].sort((a, b) => a.localeCompare(b));
|
|
9346
9362
|
}
|
|
@@ -9926,7 +9942,13 @@ async function auditRepoCi(repo, deps) {
|
|
|
9926
9942
|
label: "delete_branch_on_merge enabled",
|
|
9927
9943
|
detail: info.delete_branch_on_merge === true ? void 0 : "false or unavailable"
|
|
9928
9944
|
});
|
|
9929
|
-
const
|
|
9945
|
+
const hasCanonicalGateWorkflow = repoClass === "hub" ? true : repoClass === "content" ? true : await contentExists(deps, repo, baseBranch, PRODUCT_GATE_PATH);
|
|
9946
|
+
let prWorkflowPaths = repoClass === "deployable" && hasCanonicalGateWorkflow ? [PRODUCT_GATE_PATH] : [];
|
|
9947
|
+
if (repoClass === "deployable" && !hasCanonicalGateWorkflow) {
|
|
9948
|
+
const listedWorkflowPaths = await listWorkflowPaths(deps, repo, baseBranch);
|
|
9949
|
+
prWorkflowPaths = listedWorkflowPaths === void 0 ? [] : await filterPullRequestTriggered(deps, repo, baseBranch, listedWorkflowPaths);
|
|
9950
|
+
}
|
|
9951
|
+
const hasGateWorkflow = hasCanonicalGateWorkflow || prWorkflowPaths.length > 0;
|
|
9930
9952
|
let emittedPrContexts;
|
|
9931
9953
|
const getEmittedPrContexts = async () => {
|
|
9932
9954
|
emittedPrContexts ??= await resolveEmittedPrContexts(deps, repo, baseBranch);
|
|
@@ -9947,7 +9969,7 @@ async function auditRepoCi(repo, deps) {
|
|
|
9947
9969
|
checks.push({
|
|
9948
9970
|
ok: hasGateWorkflow,
|
|
9949
9971
|
label: `gate workflow committed on ${baseBranch}`,
|
|
9950
|
-
detail:
|
|
9972
|
+
detail: hasCanonicalGateWorkflow ? `read ${PRODUCT_GATE_PATH} at refs/heads/${baseBranch}` : prWorkflowPaths.length > 0 ? `read PR workflows at refs/heads/${baseBranch}: ${prWorkflowPaths.join(", ")}` : `missing ${PRODUCT_GATE_PATH} and no PR-triggered workflows at refs/heads/${baseBranch}`,
|
|
9951
9973
|
remediation: `mmi-cli bootstrap apply ${repo} --class deployable --execute (seeds gate.yml)`
|
|
9952
9974
|
});
|
|
9953
9975
|
checks.push({
|
|
@@ -9989,7 +10011,7 @@ async function auditRepoCi(repo, deps) {
|
|
|
9989
10011
|
}
|
|
9990
10012
|
}
|
|
9991
10013
|
}
|
|
9992
|
-
const workflowPaths =
|
|
10014
|
+
const workflowPaths = repoClass === "deployable" ? prWorkflowPaths : [];
|
|
9993
10015
|
const { policy, reason } = resolveMergeCiPolicy({
|
|
9994
10016
|
workflowPaths,
|
|
9995
10017
|
registryCi,
|
|
@@ -17810,9 +17832,12 @@ var DOC_PLACEHOLDER_PROMPTS = [
|
|
|
17810
17832
|
"install, dev server",
|
|
17811
17833
|
"lint, typecheck, repo gate script",
|
|
17812
17834
|
"ports, env from vault not files",
|
|
17813
|
-
"
|
|
17814
|
-
"
|
|
17815
|
-
"
|
|
17835
|
+
"top-level dir/module: what it is, in one line",
|
|
17836
|
+
"Owner/operator \u2014 who runs this day to day",
|
|
17837
|
+
"one human-readable command/steps to get this running locally",
|
|
17838
|
+
"the product/service/library, in one or two bullets",
|
|
17839
|
+
"(top-level dir)",
|
|
17840
|
+
"Languages, frameworks, datastores, major services",
|
|
17816
17841
|
"Build/test commands, CI gate, deploy target"
|
|
17817
17842
|
];
|
|
17818
17843
|
function unfilledDocPlaceholders(text) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutmutco/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.31.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",
|