@mnci/cli 1.19.7 → 2.0.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/README.md +25 -86
- package/dist/cli.js +116 -329
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -80,12 +80,11 @@ function runNpx(arguments_, cwd) {
|
|
|
80
80
|
throw new Error(`npx ${arguments_.join(" ")} failed with exit code ${status}`);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
function runFormatter(cwd,
|
|
84
|
-
const
|
|
85
|
-
const status = runShell("npx", [command, ...arguments_], cwd);
|
|
83
|
+
function runFormatter(cwd, target = ".") {
|
|
84
|
+
const status = runShell("npx", ["eslint", target, "--fix"], cwd);
|
|
86
85
|
if (status !== 0) {
|
|
87
86
|
logger.warn(
|
|
88
|
-
|
|
87
|
+
`eslint could not format '${target}' (exit code ${status}). The project was generated; run 'npm run format' to normalise it.`
|
|
89
88
|
);
|
|
90
89
|
}
|
|
91
90
|
}
|
|
@@ -142,20 +141,7 @@ async function promptStack() {
|
|
|
142
141
|
{ name: "Vitest", value: "vitest" }
|
|
143
142
|
]
|
|
144
143
|
});
|
|
145
|
-
|
|
146
|
-
message: "Linter and formatter",
|
|
147
|
-
choices: [
|
|
148
|
-
{
|
|
149
|
-
name: "ESLint + Prettier \u2014 every file type, the widest rule coverage",
|
|
150
|
-
value: "eslint"
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
name: "oxlint + oxfmt for JS/TS, ESLint for the rest \u2014 much faster, same style",
|
|
154
|
-
value: "oxlint"
|
|
155
|
-
}
|
|
156
|
-
]
|
|
157
|
-
});
|
|
158
|
-
return { testRunner, linter };
|
|
144
|
+
return { testRunner };
|
|
159
145
|
}
|
|
160
146
|
|
|
161
147
|
// src/util/fsx.ts
|
|
@@ -1220,7 +1206,7 @@ async function runAdd(kind, name, options) {
|
|
|
1220
1206
|
case "python-vendor": {
|
|
1221
1207
|
await addPythonVendor(workspaceRoot, resolvedName, options, kindProvided);
|
|
1222
1208
|
syncProjectReferences(workspaceRoot);
|
|
1223
|
-
runFormatter(workspaceRoot
|
|
1209
|
+
runFormatter(workspaceRoot);
|
|
1224
1210
|
return;
|
|
1225
1211
|
}
|
|
1226
1212
|
default: {
|
|
@@ -1231,7 +1217,7 @@ async function runAdd(kind, name, options) {
|
|
|
1231
1217
|
}
|
|
1232
1218
|
}
|
|
1233
1219
|
syncProjectReferences(workspaceRoot);
|
|
1234
|
-
runFormatter(workspaceRoot
|
|
1220
|
+
runFormatter(workspaceRoot);
|
|
1235
1221
|
logger.success(`Added ${resolvedKind} '${resolvedName}'.`);
|
|
1236
1222
|
}
|
|
1237
1223
|
function syncProjectReferences(workspaceRoot) {
|
|
@@ -1248,14 +1234,7 @@ function readWorkspaceStack(workspaceRoot) {
|
|
|
1248
1234
|
);
|
|
1249
1235
|
const stack = nxJson.mnci?.stack;
|
|
1250
1236
|
return {
|
|
1251
|
-
testRunner: stack?.testRunner === "vitest" ? "vitest" : "jest"
|
|
1252
|
-
// Defaults to `eslint` when absent, the same call `mnci upgrade` makes and
|
|
1253
|
-
// for the same reason: every workspace generated before the choice existed
|
|
1254
|
-
// has no persisted value and is an ESLint workspace. Reading it at all is
|
|
1255
|
-
// the fix — this function returned `testRunner` alone, so `add` finished by
|
|
1256
|
-
// formatting an oxlint workspace with Prettier, against Prettier's defaults,
|
|
1257
|
-
// since the overlay had deleted the config that would have corrected it.
|
|
1258
|
-
linter: stack?.linter === "oxlint" ? "oxlint" : "eslint"
|
|
1237
|
+
testRunner: stack?.testRunner === "vitest" ? "vitest" : "jest"
|
|
1259
1238
|
};
|
|
1260
1239
|
}
|
|
1261
1240
|
|
|
@@ -1266,8 +1245,7 @@ var import_node_path12 = require("path");
|
|
|
1266
1245
|
// src/overlay.ts
|
|
1267
1246
|
var import_node_fs6 = require("fs");
|
|
1268
1247
|
var import_node_path11 = require("path");
|
|
1269
|
-
var DEFAULT_STACK = { testRunner: "jest"
|
|
1270
|
-
var PRETTIER_VERSION = "^3.8.1";
|
|
1248
|
+
var DEFAULT_STACK = { testRunner: "jest" };
|
|
1271
1249
|
var TS_COMPILER_DEPENDENCIES = {
|
|
1272
1250
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
1273
1251
|
typescript: "npm:@typescript/typescript6@^6.0.2"
|
|
@@ -1375,32 +1353,12 @@ var COMMITLINT_CONFIG = `export default { extends: ['@commitlint/config-conventi
|
|
|
1375
1353
|
`;
|
|
1376
1354
|
var COMMIT_MSG_HOOK = `npx --no -- commitlint --edit "$1"
|
|
1377
1355
|
`;
|
|
1378
|
-
var PRETTIER_CONFIG = `// The formatting half of @mnci/eslint-config.
|
|
1379
|
-
//
|
|
1380
|
-
// Prettier's options live in the same package as the ESLint rules on purpose:
|
|
1381
|
-
// linting and formatting are one decision. \`eslint-config-prettier\` is composed
|
|
1382
|
-
// last inside that package so every formatting rule defers to these settings, and
|
|
1383
|
-
// splitting the two across packages means a version pair that can drift until
|
|
1384
|
-
// \`npm run lint\` and \`npm run format:check\` disagree with each other.
|
|
1385
|
-
//
|
|
1386
|
-
// Consuming it as a shareable config also means a formatting fix reaches this
|
|
1387
|
-
// workspace through \`npm update\`, the same way a rule change does, instead of
|
|
1388
|
-
// waiting for \`mnci upgrade\` to rewrite a file.
|
|
1389
|
-
//
|
|
1390
|
-
// TO OVERRIDE an option, spread it rather than re-exporting:
|
|
1391
|
-
//
|
|
1392
|
-
// import mnci from '@mnci/eslint-config/prettier'
|
|
1393
|
-
// export default { ...mnci, printWidth: 120 }
|
|
1394
|
-
//
|
|
1395
|
-
// TO SEE the resolved options for a file: npx prettier --find-config-path <file>
|
|
1396
|
-
export { default } from '@mnci/eslint-config/prettier'
|
|
1397
|
-
`;
|
|
1398
1356
|
var ESLINT_CONFIG_VERSION = "^0.1.0";
|
|
1399
1357
|
function eslintConfigSpec() {
|
|
1400
1358
|
return process.env.MNCI_ESLINT_CONFIG_SPEC ?? ESLINT_CONFIG_VERSION;
|
|
1401
1359
|
}
|
|
1402
1360
|
var ESLINT_VERSION = "^10.8.0";
|
|
1403
|
-
function devcontainerJson(workspaceName
|
|
1361
|
+
function devcontainerJson(workspaceName) {
|
|
1404
1362
|
return `${toJson({
|
|
1405
1363
|
name: workspaceName,
|
|
1406
1364
|
image: `mcr.microsoft.com/devcontainers/typescript-node:${NODE_VERSION}-bookworm`,
|
|
@@ -1411,6 +1369,10 @@ function devcontainerJson(workspaceName, linter) {
|
|
|
1411
1369
|
// `npm ci` first: every guard after it runs through the workspace's own
|
|
1412
1370
|
// scripts and Nx, which do not exist until the install completes.
|
|
1413
1371
|
postCreateCommand: [
|
|
1372
|
+
// Same pin the workflow applies, for the same reason — a container whose
|
|
1373
|
+
// npm major differs from CI's resolves dependencies differently, which is
|
|
1374
|
+
// precisely the drift this file exists to remove.
|
|
1375
|
+
`npm install -g npm@${NPM_VERSION}`,
|
|
1414
1376
|
"npm ci",
|
|
1415
1377
|
"npm run python:install",
|
|
1416
1378
|
GOLANGCI_LINT_INSTALL_GUARD,
|
|
@@ -1419,7 +1381,7 @@ function devcontainerJson(workspaceName, linter) {
|
|
|
1419
1381
|
// The same recommendations the `.code-workspace` file carries, so opening
|
|
1420
1382
|
// the folder in a container suggests the identical toolset.
|
|
1421
1383
|
customizations: {
|
|
1422
|
-
vscode: { extensions:
|
|
1384
|
+
vscode: { extensions: VSCODE_RECOMMENDED_EXTENSIONS }
|
|
1423
1385
|
}
|
|
1424
1386
|
})}
|
|
1425
1387
|
`;
|
|
@@ -1429,7 +1391,13 @@ var ROOT_LINT_TARGET = {
|
|
|
1429
1391
|
cache: true,
|
|
1430
1392
|
options: {
|
|
1431
1393
|
command: [
|
|
1432
|
-
|
|
1394
|
+
// `--cache` is the one ESLint speed option that actually pays here:
|
|
1395
|
+
// measured best-of-3 on this repo, an unchanged re-run drops from 9,546ms
|
|
1396
|
+
// to 2,835ms (3.4x). `--concurrency=auto` was measured too and REJECTED —
|
|
1397
|
+
// it came out 8% SLOWER, because per-worker TypeScript type-service
|
|
1398
|
+
// startup costs more than the parallelism saves. The cache file is
|
|
1399
|
+
// per-machine and gitignored.
|
|
1400
|
+
"eslint . --cache",
|
|
1433
1401
|
'--ignore-pattern "apps/**"',
|
|
1434
1402
|
'--ignore-pattern "libs/**"',
|
|
1435
1403
|
'--ignore-pattern "packages/**"',
|
|
@@ -1473,38 +1441,23 @@ function eslintToolchainDependencies(nxVersion) {
|
|
|
1473
1441
|
"@mnci/eslint-config": eslintConfigSpec()
|
|
1474
1442
|
};
|
|
1475
1443
|
}
|
|
1476
|
-
var
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
function
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
}
|
|
1494
|
-
};
|
|
1495
|
-
}
|
|
1496
|
-
var OXLINT_VERSION = "^1.76.0";
|
|
1497
|
-
var OXFMT_VERSION = "^0.61.0";
|
|
1498
|
-
function oxlintToolchainDependencies() {
|
|
1499
|
-
return {
|
|
1500
|
-
"@mnci/oxlint-config": oxlintConfigSpec(),
|
|
1501
|
-
oxlint: OXLINT_VERSION,
|
|
1502
|
-
oxfmt: OXFMT_VERSION
|
|
1503
|
-
};
|
|
1504
|
-
}
|
|
1505
|
-
var OXLINT_CONFIG_VERSION = "^0.1.0";
|
|
1506
|
-
function oxlintConfigSpec() {
|
|
1507
|
-
return process.env.MNCI_OXLINT_CONFIG_SPEC ?? OXLINT_CONFIG_VERSION;
|
|
1444
|
+
var RETIRED_FORMATTER_FILES = [
|
|
1445
|
+
".prettierrc",
|
|
1446
|
+
".prettierrc.json",
|
|
1447
|
+
".prettierrc.mjs",
|
|
1448
|
+
".prettierignore",
|
|
1449
|
+
"oxlint.config.ts",
|
|
1450
|
+
".oxfmtrc.json"
|
|
1451
|
+
];
|
|
1452
|
+
function withoutRetiredFormatterDependencies(devDeps) {
|
|
1453
|
+
const retired = /* @__PURE__ */ new Set([
|
|
1454
|
+
"prettier",
|
|
1455
|
+
"eslint-config-prettier",
|
|
1456
|
+
"oxlint",
|
|
1457
|
+
"oxfmt",
|
|
1458
|
+
"@mnci/oxlint-config"
|
|
1459
|
+
]);
|
|
1460
|
+
return Object.fromEntries(Object.entries(devDeps).filter(([name]) => !retired.has(name)));
|
|
1508
1461
|
}
|
|
1509
1462
|
var ESLINT_BLOCK_INVENTORY = `// WHAT IS IN HERE. Each line is one config block, by the \`name\` it carries.
|
|
1510
1463
|
//
|
|
@@ -1531,9 +1484,9 @@ var ESLINT_BLOCK_INVENTORY = `// WHAT IS IN HERE. Each line is one config block,
|
|
|
1531
1484
|
// mnci/tests *.spec/*.test relaxations \u2014 eslint-plugin-jest
|
|
1532
1485
|
// (Vitest's globals too; the two stacks share them)
|
|
1533
1486
|
// mnci/nx-dependency-checks @nx/eslint-plugin, on publishable packages' manifests
|
|
1534
|
-
// mnci/
|
|
1535
|
-
//
|
|
1536
|
-
//
|
|
1487
|
+
// mnci/standard JavaScript Standard Style as ESLint rules \u2014 the
|
|
1488
|
+
// whole formatting opinion. Composed LAST, on
|
|
1489
|
+
// purpose: nothing may follow that disables it.
|
|
1537
1490
|
//
|
|
1538
1491
|
// To list them as ESLint actually resolves them: npx eslint --inspect-config
|
|
1539
1492
|
`;
|
|
@@ -1563,77 +1516,9 @@ ${ESLINT_BLOCK_INVENTORY}//
|
|
|
1563
1516
|
// impossible to satisfy at the same time. Formatting lives in .prettierrc.mjs.
|
|
1564
1517
|
export default mnci({ workspaceRoot: import.meta.dirname })
|
|
1565
1518
|
`;
|
|
1566
|
-
var
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
// the file types oxlint cannot parse at all \u2014 YAML, TOML, Markdown, CSS, HTML,
|
|
1570
|
-
// JSON \u2014 plus @nx/dependency-checks on publishable manifests.
|
|
1571
|
-
//
|
|
1572
|
-
// The JS/TS rule blocks are deliberately NOT composed here. Running both linters
|
|
1573
|
-
// over the same file would report one defect twice under two different names.
|
|
1574
|
-
//
|
|
1575
|
-
// TO OVERRIDE, append a named block after the spread, exactly as the full config
|
|
1576
|
-
// documents. To change a JS/TS rule, edit oxlint.config.ts instead \u2014 this file
|
|
1577
|
-
// does not lint JS/TS.
|
|
1578
|
-
export default [...nonJs({ workspaceRoot: import.meta.dirname })]
|
|
1579
|
-
`;
|
|
1580
|
-
var OXLINT_CONFIG = `import { defineConfig } from 'oxlint'
|
|
1581
|
-
import mnci from '@mnci/oxlint-config'
|
|
1582
|
-
|
|
1583
|
-
// oxlint owns JS/TS/JSX here; eslint.config.mjs keeps everything oxlint cannot
|
|
1584
|
-
// parse. The contract @mnci/oxlint-config holds itself to: anything
|
|
1585
|
-
// @mnci/eslint-config accepts must pass oxlint, so switching linters never turns
|
|
1586
|
-
// a green codebase red.
|
|
1587
|
-
//
|
|
1588
|
-
// oxlint.config.ts, not .oxlintrc.json, and that is not a preference: .oxlintrc's
|
|
1589
|
-
// \`extends\` takes PATHS relative to the config file, so
|
|
1590
|
-
// \`extends: ["@mnci/oxlint-config"]\` fails with "No such file or directory".
|
|
1591
|
-
// defineConfig is the only shareable-config route oxlint offers.
|
|
1592
|
-
//
|
|
1593
|
-
// Type-aware rules (no-floating-promises and friends) are opt-in \u2014 pass
|
|
1594
|
-
// { typeAware: true } AND run oxlint with --type-aware. They report findings the
|
|
1595
|
-
// ESLint stack accepts, so they are off by default to keep the contract above.
|
|
1596
|
-
export default defineConfig({ extends: [mnci()] })
|
|
1597
|
-
`;
|
|
1598
|
-
var OXFMT_CONFIG = `${JSON.stringify(
|
|
1599
|
-
{
|
|
1600
|
-
$schema: "./node_modules/oxfmt/configuration_schema.json",
|
|
1601
|
-
semi: false,
|
|
1602
|
-
singleQuote: true,
|
|
1603
|
-
trailingComma: "none",
|
|
1604
|
-
arrowParens: "avoid",
|
|
1605
|
-
printWidth: 100,
|
|
1606
|
-
tabWidth: 2,
|
|
1607
|
-
useTabs: false
|
|
1608
|
-
},
|
|
1609
|
-
null,
|
|
1610
|
-
2
|
|
1611
|
-
)}
|
|
1612
|
-
`;
|
|
1613
|
-
var PRETTIER_IGNORE = `node_modules
|
|
1614
|
-
dist
|
|
1615
|
-
dist-dev
|
|
1616
|
-
dist-uat
|
|
1617
|
-
dist-prod
|
|
1618
|
-
coverage
|
|
1619
|
-
.next
|
|
1620
|
-
out
|
|
1621
|
-
.nx
|
|
1622
|
-
tmp
|
|
1623
|
-
package-lock.json
|
|
1624
|
-
*.lock
|
|
1625
|
-
.venv
|
|
1626
|
-
venv
|
|
1627
|
-
__pycache__
|
|
1628
|
-
.pytest_cache
|
|
1629
|
-
.ruff_cache
|
|
1630
|
-
.dart_tool
|
|
1631
|
-
`;
|
|
1632
|
-
var LINTER_EXTENSIONS = {
|
|
1633
|
-
eslint: ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
|
|
1634
|
-
oxlint: ["oxc.oxc-vscode", "dbaeumer.vscode-eslint"]
|
|
1635
|
-
};
|
|
1636
|
-
var SHARED_VSCODE_EXTENSIONS = [
|
|
1519
|
+
var VSCODE_RECOMMENDED_EXTENSIONS = [
|
|
1520
|
+
"dbaeumer.vscode-eslint",
|
|
1521
|
+
"esbenp.prettier-vscode",
|
|
1637
1522
|
"nrwl.angular-console",
|
|
1638
1523
|
"firsttris.vscode-jest-runner"
|
|
1639
1524
|
];
|
|
@@ -1649,25 +1534,9 @@ var FORMATTED_LANGUAGES = [
|
|
|
1649
1534
|
"css",
|
|
1650
1535
|
"html"
|
|
1651
1536
|
];
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
}
|
|
1656
|
-
function vscodeExtensions(linter) {
|
|
1657
|
-
return [...LINTER_EXTENSIONS[linter], ...SHARED_VSCODE_EXTENSIONS];
|
|
1658
|
-
}
|
|
1659
|
-
function vscodeSettings(linter) {
|
|
1660
|
-
const formatter = linter === "oxlint" ? "oxc.oxc-vscode" : "esbenp.prettier-vscode";
|
|
1661
|
-
const eslintLanguages = linter === "oxlint" ? ["json", "jsonc", "markdown", "yaml", "html", "css"] : [
|
|
1662
|
-
"javascript",
|
|
1663
|
-
"javascriptreact",
|
|
1664
|
-
"typescript",
|
|
1665
|
-
"typescriptreact",
|
|
1666
|
-
"json",
|
|
1667
|
-
"jsonc",
|
|
1668
|
-
"markdown",
|
|
1669
|
-
"yaml"
|
|
1670
|
-
];
|
|
1537
|
+
function vscodeSettings() {
|
|
1538
|
+
const formatter = "dbaeumer.vscode-eslint";
|
|
1539
|
+
const eslintLanguages = [...FORMATTED_LANGUAGES];
|
|
1671
1540
|
return {
|
|
1672
1541
|
"eslint.validate": eslintLanguages,
|
|
1673
1542
|
"editor.codeActionsOnSave": {
|
|
@@ -1690,19 +1559,19 @@ function vscodeSettings(linter) {
|
|
|
1690
1559
|
// while `.json`/`.jsonc`/`.yaml` were — exactly the three that had explicit
|
|
1691
1560
|
// entries here and nothing else did.
|
|
1692
1561
|
...Object.fromEntries(
|
|
1693
|
-
|
|
1562
|
+
FORMATTED_LANGUAGES.map((language) => [
|
|
1694
1563
|
`[${language}]`,
|
|
1695
1564
|
{ "editor.defaultFormatter": formatter }
|
|
1696
1565
|
])
|
|
1697
1566
|
)
|
|
1698
1567
|
};
|
|
1699
1568
|
}
|
|
1700
|
-
function vscodeWorkspace(workspaceName,
|
|
1569
|
+
function vscodeWorkspace(workspaceName, existingTasks) {
|
|
1701
1570
|
return JSON.stringify(
|
|
1702
1571
|
{
|
|
1703
1572
|
folders: [{ path: ".", name: workspaceName }],
|
|
1704
|
-
settings: vscodeSettings(
|
|
1705
|
-
extensions: { recommendations:
|
|
1573
|
+
settings: vscodeSettings(),
|
|
1574
|
+
extensions: { recommendations: VSCODE_RECOMMENDED_EXTENSIONS },
|
|
1706
1575
|
tasks: {
|
|
1707
1576
|
version: existingTasks?.version ?? "2.0.0",
|
|
1708
1577
|
tasks: existingTasks?.tasks ?? []
|
|
@@ -1722,12 +1591,14 @@ var ROOT_SCRIPTS = {
|
|
|
1722
1591
|
"release:preview": "nx release --dry-run",
|
|
1723
1592
|
prepare: "husky"
|
|
1724
1593
|
};
|
|
1725
|
-
function rootScripts(
|
|
1726
|
-
const formatter = linter === "oxlint" ? "oxfmt" : "prettier";
|
|
1594
|
+
function rootScripts() {
|
|
1727
1595
|
return {
|
|
1728
1596
|
...ROOT_SCRIPTS,
|
|
1729
|
-
|
|
1730
|
-
|
|
1597
|
+
// ESLint is the formatter, so `format` is `--fix` and there is no separate
|
|
1598
|
+
// `format:check`: `lint` already reports formatting as ordinary errors.
|
|
1599
|
+
// Carrying a second script that ran the same tool twice would just make a
|
|
1600
|
+
// CI run slower for no extra coverage.
|
|
1601
|
+
format: "eslint . --fix --cache",
|
|
1731
1602
|
"python:install": `${PYTHON_INSTALL_GUARD} && ${PYTHON_WORKSPACE_INSTALL_GUARD}`
|
|
1732
1603
|
};
|
|
1733
1604
|
}
|
|
@@ -1761,7 +1632,7 @@ function mnciConfig(options) {
|
|
|
1761
1632
|
agent: options.agent,
|
|
1762
1633
|
variableGroup: options.variableGroup,
|
|
1763
1634
|
ci: options.ci,
|
|
1764
|
-
stack: { testRunner: options.stack.testRunner
|
|
1635
|
+
stack: { testRunner: options.stack.testRunner }
|
|
1765
1636
|
};
|
|
1766
1637
|
}
|
|
1767
1638
|
function readMnciConfig(workspaceRoot) {
|
|
@@ -1779,11 +1650,12 @@ var PYTHON_WORKSPACE_INSTALL_GUARD = `node -e "const fs=require('node:fs'),path=
|
|
|
1779
1650
|
var PIP_AUDIT_GUARD = `node -e "if(!require('node:fs').existsSync('requirements-dev.txt')){console.log('No Python projects - skipping.');process.exit(0)}const py=process.platform==='win32'?'python':'python3';require('node:child_process').spawnSync(py,['-m','pip_audit'],{stdio:'inherit'});process.exit(0)"`;
|
|
1780
1651
|
var GO_MODULE_DOWNLOAD_GUARD = `node -e "if(!require('node:fs').existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}process.exit(require('node:child_process').spawnSync('go',['mod','download'],{stdio:'inherit'}).status ?? 1)"`;
|
|
1781
1652
|
var GOLANGCI_LINT_INSTALL_GUARD = `node -e "const fs=require('node:fs'),cp=require('node:child_process');if(!fs.existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}if(cp.spawnSync('golangci-lint',['--version'],{stdio:'ignore'}).status===0){console.log('golangci-lint already installed - skipping.');process.exit(0)}process.exit(cp.spawnSync('go',['install','github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest'],{stdio:'inherit'}).status ?? 1)"`;
|
|
1782
|
-
var GO_TOOL_PATH_PRELUDE =
|
|
1653
|
+
var GO_TOOL_PATH_PRELUDE = "const fs=require('node:fs'),cp=require('node:child_process');if(!fs.existsSync('go.mod')){console.log('No Go projects - skipping.');process.exit(0)}const r=cp.spawnSync('go',['env','GOPATH'],{encoding:'utf8'});if(r.status!==0){console.log('Could not resolve GOPATH - skipping.');process.exit(0)}const bin=require('node:path').join(r.stdout.trim(),'bin');";
|
|
1783
1654
|
var GO_TOOL_PATH_AZURE = `node -e "${GO_TOOL_PATH_PRELUDE}console.log('##vso[task.prependpath]'+bin)"`;
|
|
1784
1655
|
var GO_TOOL_PATH_GITHUB = `node -e "${GO_TOOL_PATH_PRELUDE}if(!process.env.GITHUB_PATH){console.log('Not running in GitHub Actions - skipping.');process.exit(0)}fs.appendFileSync(process.env.GITHUB_PATH,bin+${String.raw`'\n'`})"`;
|
|
1785
1656
|
var FLUTTER_SDK_VERSION = "3.44.8";
|
|
1786
1657
|
var NODE_VERSION = "24";
|
|
1658
|
+
var NPM_VERSION = "11";
|
|
1787
1659
|
var FLUTTER_SDK_DIRECTORY_EXPRESSION = `require('node:path').join(require('node:os').homedir(),'.mnci-flutter-${FLUTTER_SDK_VERSION}')`;
|
|
1788
1660
|
var FLUTTER_SDK_INSTALL_GUARD = `node -e "const fs=require('node:fs'),cp=require('node:child_process');if(!fs.existsSync('pubspec.yaml')){console.log('No Flutter projects - skipping.');process.exit(0)}if(cp.spawnSync('flutter',['--version'],{stdio:'ignore',shell:process.platform==='win32'}).status===0){console.log('Flutter SDK already on PATH - skipping.');process.exit(0)}const sdk=${FLUTTER_SDK_DIRECTORY_EXPRESSION};if(fs.existsSync(sdk)){console.log('Flutter SDK already installed at '+sdk+' - skipping.');process.exit(0)}process.exit(cp.spawnSync('git',['clone','--depth','1','--branch','${FLUTTER_SDK_VERSION}','https://github.com/flutter/flutter.git',sdk],{stdio:'inherit'}).status ?? 1)"`;
|
|
1789
1661
|
var FLUTTER_TOOL_PATH_PRELUDE = `const fs=require('node:fs'),path=require('node:path');if(!fs.existsSync('pubspec.yaml')){console.log('No Flutter projects - skipping.');process.exit(0)}const sdk=${FLUTTER_SDK_DIRECTORY_EXPRESSION};if(!fs.existsSync(sdk)){console.log('Flutter SDK was not installed by mnci (already on PATH) - skipping.');process.exit(0)}const bin=path.join(sdk,'bin');`;
|
|
@@ -1807,7 +1679,7 @@ function poolBlock(agent) {
|
|
|
1807
1679
|
return /^(?:ubuntu|windows|macos)-/i.test(agent) ? ` vmImage: ${agent}` : ` name: ${agent}`;
|
|
1808
1680
|
}
|
|
1809
1681
|
function azurePipelinesYaml(agent, variableGroup, pythonPublishUrl2, registryKind = "azure-artifacts") {
|
|
1810
|
-
const onMain =
|
|
1682
|
+
const onMain = "and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'), eq(variables['Build.SourceBranchName'], 'main'))";
|
|
1811
1683
|
const [npmAuthName, npmAuthValue] = npmAuthEnvVariable(registryKind, (name) => `$(${name})`);
|
|
1812
1684
|
return `name: monorepo-ci-$(Date:yyyyMMdd)$(Rev:.r)
|
|
1813
1685
|
|
|
@@ -1961,17 +1833,6 @@ steps:
|
|
|
1961
1833
|
- script: npx nx sync:check
|
|
1962
1834
|
displayName: Verify the workspace is synced (run 'npx nx sync' locally and commit if this fails)
|
|
1963
1835
|
|
|
1964
|
-
# Prettier owns ALL formatting in this workspace, so it needs a gate of its
|
|
1965
|
-
# own: ESLint is configured for correctness only and deliberately reports
|
|
1966
|
-
# nothing about formatting. Without this step the entire formatting opinion is
|
|
1967
|
-
# advisory, and a workspace drifts out of compliance with no signal anywhere.
|
|
1968
|
-
#
|
|
1969
|
-
# Stays workspace-wide even on a PR, unlike the verify step below: it is one
|
|
1970
|
-
# Prettier invocation over the whole tree, not a per-project Nx target, so
|
|
1971
|
-
# there is nothing to scope down and formatting is never partially checked.
|
|
1972
|
-
- script: npm run format:check
|
|
1973
|
-
displayName: Check formatting (run 'npm run format' locally to fix)
|
|
1974
|
-
|
|
1975
1836
|
# The one verify step, and deliberately the only one: affected projects on a
|
|
1976
1837
|
# pull request, EVERY project on anything else (a push to main included, so a
|
|
1977
1838
|
# release is always verified in full). Every fallback \u2014 no target branch, an
|
|
@@ -2026,7 +1887,7 @@ steps:
|
|
|
2026
1887
|
`;
|
|
2027
1888
|
}
|
|
2028
1889
|
function githubActionsYaml(agent, pythonPublishUrl2, registryKind = "azure-artifacts", ci = "github") {
|
|
2029
|
-
const onMain =
|
|
1890
|
+
const onMain = "github.event_name == 'push' && github.ref_name == 'main'";
|
|
2030
1891
|
const [npmAuthName, npmAuthValue] = npmAuthEnvVariable(
|
|
2031
1892
|
registryKind,
|
|
2032
1893
|
(name) => `\${{ secrets.${name} }}`
|
|
@@ -2088,6 +1949,13 @@ jobs:
|
|
|
2088
1949
|
# dependency change misses the cache and a no-op change hits it.
|
|
2089
1950
|
cache: npm
|
|
2090
1951
|
|
|
1952
|
+
# setup-node installs whatever npm the Node image bundles, and npm's major
|
|
1953
|
+
# is part of the contract: npm 11 reuses an already-installed tree instead
|
|
1954
|
+
# of re-resolving, so it applies \`overrides\` differently from npm 10. See
|
|
1955
|
+
# NPM_VERSION's remarks for the measurement.
|
|
1956
|
+
- run: npm install -g npm@${NPM_VERSION}
|
|
1957
|
+
name: Pin npm to the major mnci verifies against
|
|
1958
|
+
|
|
2091
1959
|
- run: npm ci
|
|
2092
1960
|
name: Install dependencies
|
|
2093
1961
|
env:
|
|
@@ -2161,19 +2029,6 @@ jobs:
|
|
|
2161
2029
|
- run: npx nx sync:check
|
|
2162
2030
|
name: Verify the workspace is synced (run 'npx nx sync' locally and commit if this fails)
|
|
2163
2031
|
|
|
2164
|
-
# Prettier owns ALL formatting in this workspace, so it needs a gate of
|
|
2165
|
-
# its own: ESLint is configured for correctness only and deliberately
|
|
2166
|
-
# reports nothing about formatting. Without this step the entire
|
|
2167
|
-
# formatting opinion is advisory, and a workspace drifts out of
|
|
2168
|
-
# compliance with no signal anywhere.
|
|
2169
|
-
#
|
|
2170
|
-
# Stays workspace-wide even on a PR, unlike the verify step below: it is
|
|
2171
|
-
# one Prettier invocation over the whole tree, not a per-project Nx
|
|
2172
|
-
# target, so there is nothing to scope down and formatting is never
|
|
2173
|
-
# partially checked.
|
|
2174
|
-
- run: npm run format:check
|
|
2175
|
-
name: Check formatting (run 'npm run format' locally to fix)
|
|
2176
|
-
|
|
2177
2032
|
# The one verify step, and deliberately the only one: affected projects on
|
|
2178
2033
|
# a pull request, EVERY project on anything else (a push to main included,
|
|
2179
2034
|
# so a release is always verified in full). Every fallback \u2014 no target
|
|
@@ -2298,23 +2153,15 @@ function applyOverlay(workspaceRoot, options) {
|
|
|
2298
2153
|
const manifest = readJson(manifestPath);
|
|
2299
2154
|
const scripts = {
|
|
2300
2155
|
...manifest.scripts,
|
|
2301
|
-
...rootScripts(
|
|
2156
|
+
...rootScripts()
|
|
2302
2157
|
};
|
|
2303
2158
|
const existingDevDeps = manifest.devDependencies;
|
|
2304
|
-
const devDeps =
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
// Additive for the linter, exclusive for the formatter: the hybrid keeps
|
|
2311
|
-
// the whole ESLint toolchain for the file types oxlint cannot parse, but
|
|
2312
|
-
// exactly one of prettier/oxfmt formats the workspace. Declaring both is
|
|
2313
|
-
// how an editor ends up applying the one CI does not check.
|
|
2314
|
-
...options.stack.linter === "oxlint" ? oxlintToolchainDependencies() : { prettier: PRETTIER_VERSION }
|
|
2315
|
-
},
|
|
2316
|
-
options.stack.linter
|
|
2317
|
-
);
|
|
2159
|
+
const devDeps = withoutRetiredFormatterDependencies({
|
|
2160
|
+
...existingDevDeps,
|
|
2161
|
+
...TS_COMPILER_DEPENDENCIES,
|
|
2162
|
+
// The preset pins `nx` itself; the ESLint plugins must match it exactly.
|
|
2163
|
+
...eslintToolchainDependencies(existingDevDeps?.nx ?? "latest")
|
|
2164
|
+
});
|
|
2318
2165
|
const overrides = {
|
|
2319
2166
|
...manifest.overrides,
|
|
2320
2167
|
...ESLINT_PEER_OVERRIDES
|
|
@@ -2325,7 +2172,7 @@ function applyOverlay(workspaceRoot, options) {
|
|
|
2325
2172
|
includedScripts: existingNx?.includedScripts ?? [],
|
|
2326
2173
|
targets: {
|
|
2327
2174
|
...existingNx?.targets,
|
|
2328
|
-
lint:
|
|
2175
|
+
lint: ROOT_LINT_TARGET
|
|
2329
2176
|
}
|
|
2330
2177
|
};
|
|
2331
2178
|
writeFileEnsured(
|
|
@@ -2344,28 +2191,20 @@ function applyOverlay(workspaceRoot, options) {
|
|
|
2344
2191
|
const hookPath = (0, import_node_path11.join)(workspaceRoot, ".husky/commit-msg");
|
|
2345
2192
|
writeFileEnsured(hookPath, COMMIT_MSG_HOOK);
|
|
2346
2193
|
markExecutable(hookPath);
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
writeFileEnsured((0, import_node_path11.join)(workspaceRoot, "eslint.config.mjs"), ESLINT_CONFIG_NON_JS);
|
|
2351
|
-
removeIfPresent((0, import_node_path11.join)(workspaceRoot, ".prettierrc.mjs"));
|
|
2352
|
-
} else {
|
|
2353
|
-
writeFileEnsured((0, import_node_path11.join)(workspaceRoot, "eslint.config.mjs"), ESLINT_CONFIG);
|
|
2354
|
-
writeFileEnsured((0, import_node_path11.join)(workspaceRoot, ".prettierrc.mjs"), PRETTIER_CONFIG);
|
|
2355
|
-
removeIfPresent((0, import_node_path11.join)(workspaceRoot, "oxlint.config.ts"));
|
|
2356
|
-
removeIfPresent((0, import_node_path11.join)(workspaceRoot, ".oxfmtrc.json"));
|
|
2194
|
+
writeFileEnsured((0, import_node_path11.join)(workspaceRoot, "eslint.config.mjs"), ESLINT_CONFIG);
|
|
2195
|
+
for (const retired of RETIRED_FORMATTER_FILES) {
|
|
2196
|
+
removeIfPresent((0, import_node_path11.join)(workspaceRoot, retired));
|
|
2357
2197
|
}
|
|
2358
2198
|
writeFileEnsured(
|
|
2359
2199
|
(0, import_node_path11.join)(workspaceRoot, ".devcontainer/devcontainer.json"),
|
|
2360
|
-
devcontainerJson(options.workspaceName
|
|
2200
|
+
devcontainerJson(options.workspaceName)
|
|
2361
2201
|
);
|
|
2362
|
-
writeFileEnsured((0, import_node_path11.join)(workspaceRoot, ".prettierignore"), PRETTIER_IGNORE);
|
|
2363
2202
|
removeNxScaffolding(workspaceRoot);
|
|
2364
2203
|
const codeWorkspacePath = (0, import_node_path11.join)(workspaceRoot, `${options.workspaceName}.code-workspace`);
|
|
2365
2204
|
const existing = readCodeWorkspace(codeWorkspacePath);
|
|
2366
2205
|
writeFileEnsured(
|
|
2367
2206
|
codeWorkspacePath,
|
|
2368
|
-
vscodeWorkspace(options.workspaceName,
|
|
2207
|
+
vscodeWorkspace(options.workspaceName, existing?.tasks)
|
|
2369
2208
|
);
|
|
2370
2209
|
if (options.workspaceName !== "undefined") {
|
|
2371
2210
|
(0, import_node_fs6.rmSync)((0, import_node_path11.join)(workspaceRoot, "undefined.code-workspace"), { force: true });
|
|
@@ -2408,65 +2247,28 @@ function checkEslintConfigs(workspaceRoot) {
|
|
|
2408
2247
|
}
|
|
2409
2248
|
];
|
|
2410
2249
|
}
|
|
2411
|
-
function checkPrettierConfig(workspaceRoot) {
|
|
2412
|
-
const strayExists = fileExists((0, import_node_path12.join)(workspaceRoot, ".prettierrc"));
|
|
2413
|
-
return {
|
|
2414
|
-
check: "Prettier config is mnci\u2019s",
|
|
2415
|
-
ok: !strayExists,
|
|
2416
|
-
detail: ".prettierrc exists and outranks .prettierrc.json, so mnci\u2019s config is ignored",
|
|
2417
|
-
remedy: "delete .prettierrc (or run `mnci upgrade`, which deletes it)"
|
|
2418
|
-
};
|
|
2419
|
-
}
|
|
2420
|
-
function checkLinterModeIsConsistent(workspaceRoot) {
|
|
2421
|
-
const linter = readMnciConfig(workspaceRoot).stack?.linter ?? "eslint";
|
|
2422
|
-
const oxlintFiles = ["oxlint.config.ts", ".oxfmtrc.json"].filter(
|
|
2423
|
-
(file) => fileExists((0, import_node_path12.join)(workspaceRoot, file))
|
|
2424
|
-
);
|
|
2425
|
-
const hasPrettier = fileExists((0, import_node_path12.join)(workspaceRoot, ".prettierrc.mjs"));
|
|
2426
|
-
const stray = linter === "oxlint" ? hasPrettier ? [".prettierrc.mjs"] : [] : oxlintFiles;
|
|
2427
|
-
return {
|
|
2428
|
-
check: `linter is ${linter} and only ${linter}'s config files are present`,
|
|
2429
|
-
ok: stray.length === 0,
|
|
2430
|
-
detail: `${stray.join(", ")} belongs to the other linter mode, so two configs are in play at once`,
|
|
2431
|
-
remedy: "run `mnci upgrade`, which removes the mode the workspace did not choose"
|
|
2432
|
-
};
|
|
2433
|
-
}
|
|
2434
2250
|
function declaredDevDependencies(workspaceRoot) {
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
}
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
const declared = declaredDevDependencies(workspaceRoot)[stale] !== void 0;
|
|
2444
|
-
return {
|
|
2445
|
-
check: `only ${linter === "oxlint" ? "oxfmt" : "prettier"} is declared as the formatter`,
|
|
2446
|
-
ok: !declared,
|
|
2447
|
-
detail: `${stale} is declared but nothing runs it \u2014 the editor may still resolve and apply it, disagreeing with \`npm run format:check\``,
|
|
2448
|
-
remedy: "run `mnci upgrade`, which drops the formatter of the mode you left"
|
|
2449
|
-
};
|
|
2251
|
+
try {
|
|
2252
|
+
const manifest = readJson(
|
|
2253
|
+
(0, import_node_path12.join)(workspaceRoot, "package.json")
|
|
2254
|
+
);
|
|
2255
|
+
return manifest.devDependencies ?? {};
|
|
2256
|
+
} catch {
|
|
2257
|
+
return {};
|
|
2258
|
+
}
|
|
2450
2259
|
}
|
|
2451
|
-
function
|
|
2452
|
-
const
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
detail: "not an oxlint workspace",
|
|
2458
|
-
remedy: ""
|
|
2459
|
-
};
|
|
2260
|
+
function checkNoRetiredFormatter(workspaceRoot) {
|
|
2261
|
+
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0, import_node_path12.join)(workspaceRoot, file)));
|
|
2262
|
+
const declared = ["prettier", "eslint-config-prettier", "oxlint", "oxfmt", "@mnci/oxlint-config"].filter((name) => declaredDevDependencies(workspaceRoot)[name] !== void 0);
|
|
2263
|
+
const stale = [...files, ...declared];
|
|
2264
|
+
if (stale.length === 0) {
|
|
2265
|
+
return { check: "ESLint is the only linter and formatter", ok: true };
|
|
2460
2266
|
}
|
|
2461
|
-
const devDeps = declaredDevDependencies(workspaceRoot);
|
|
2462
|
-
const missing = ["oxlint", "oxfmt", "@mnci/oxlint-config"].filter(
|
|
2463
|
-
(dependency) => devDeps[dependency] === void 0
|
|
2464
|
-
);
|
|
2465
2267
|
return {
|
|
2466
|
-
check: "
|
|
2467
|
-
ok:
|
|
2468
|
-
detail: `
|
|
2469
|
-
remedy: "
|
|
2268
|
+
check: "no retired formatter is still configured",
|
|
2269
|
+
ok: false,
|
|
2270
|
+
detail: `Found: ${stale.join(", ")}. These no longer run, but an editor extension still resolves them and will reformat on save against an opinion no gate checks.`,
|
|
2271
|
+
remedy: "Run 'mnci upgrade' to remove them."
|
|
2470
2272
|
};
|
|
2471
2273
|
}
|
|
2472
2274
|
function checkEslintPlugin(nxJson) {
|
|
@@ -2562,10 +2364,7 @@ function collectFindings(workspaceRoot) {
|
|
|
2562
2364
|
const nxJson = readJson(nxJsonPath);
|
|
2563
2365
|
return [
|
|
2564
2366
|
...checkEslintConfigs(workspaceRoot),
|
|
2565
|
-
|
|
2566
|
-
checkLinterModeIsConsistent(workspaceRoot),
|
|
2567
|
-
checkOneFormatterDeclared(workspaceRoot),
|
|
2568
|
-
checkOxlintToolchainDeclared(workspaceRoot),
|
|
2367
|
+
checkNoRetiredFormatter(workspaceRoot),
|
|
2569
2368
|
checkEslintPlugin(nxJson),
|
|
2570
2369
|
checkResolvedEslint(workspaceRoot),
|
|
2571
2370
|
checkNpmrc(workspaceRoot, nxJson.mnci?.registry, nxJson.mnci?.scope),
|
|
@@ -2599,22 +2398,17 @@ var import_node_path15 = require("path");
|
|
|
2599
2398
|
var import_prompts8 = require("@inquirer/prompts");
|
|
2600
2399
|
|
|
2601
2400
|
// src/commands/new.ts
|
|
2401
|
+
var import_node_fs8 = require("fs");
|
|
2602
2402
|
var import_node_path13 = require("path");
|
|
2603
2403
|
function nxCloudProviderValue(ci) {
|
|
2604
2404
|
return ci === "azure" ? "azure" : "github";
|
|
2605
2405
|
}
|
|
2606
2406
|
async function resolveStack(options) {
|
|
2607
|
-
if (options.testRunner || options.
|
|
2608
|
-
return {
|
|
2609
|
-
testRunner: options.testRunner ?? DEFAULT_STACK.testRunner,
|
|
2610
|
-
linter: options.linter ?? DEFAULT_STACK.linter
|
|
2611
|
-
};
|
|
2407
|
+
if (options.testRunner || options.yes) {
|
|
2408
|
+
return { testRunner: options.testRunner ?? DEFAULT_STACK.testRunner };
|
|
2612
2409
|
}
|
|
2613
2410
|
const prompted = await promptStack();
|
|
2614
|
-
return {
|
|
2615
|
-
testRunner: prompted.testRunner,
|
|
2616
|
-
linter: prompted.linter
|
|
2617
|
-
};
|
|
2411
|
+
return { testRunner: prompted.testRunner };
|
|
2618
2412
|
}
|
|
2619
2413
|
var CI_PROVIDERS = /* @__PURE__ */ new Set(["azure", "github", "both"]);
|
|
2620
2414
|
async function resolveCi(options) {
|
|
@@ -2671,6 +2465,8 @@ async function runNew(name, options) {
|
|
|
2671
2465
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
2672
2466
|
);
|
|
2673
2467
|
applyOverlay(workspaceRoot, { workspaceName, scope, registry, agent, variableGroup, ci, stack });
|
|
2468
|
+
(0, import_node_fs8.rmSync)((0, import_node_path13.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
|
|
2469
|
+
(0, import_node_fs8.rmSync)((0, import_node_path13.join)(workspaceRoot, "package-lock.json"), { force: true });
|
|
2674
2470
|
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
2675
2471
|
const installStatus = runShell(
|
|
2676
2472
|
"npm",
|
|
@@ -2681,10 +2477,8 @@ async function runNew(name, options) {
|
|
|
2681
2477
|
throw new Error(`npm install of the toolchain failed with exit code ${installStatus}`);
|
|
2682
2478
|
}
|
|
2683
2479
|
runShell("npx", ["husky"], workspaceRoot);
|
|
2684
|
-
logger.step(
|
|
2685
|
-
|
|
2686
|
-
);
|
|
2687
|
-
runFormatter(workspaceRoot, stack.linter);
|
|
2480
|
+
logger.step("Formatting the workspace (eslint --fix, JavaScript Standard Style)");
|
|
2481
|
+
runFormatter(workspaceRoot);
|
|
2688
2482
|
logger.success("Done. Next steps:");
|
|
2689
2483
|
logger.info(` cd ${workspaceName}`);
|
|
2690
2484
|
logger.info(" mnci add react-app web # or: react-lib, react-internal-lib, node-app,");
|
|
@@ -2702,7 +2496,7 @@ async function runNew(name, options) {
|
|
|
2702
2496
|
}
|
|
2703
2497
|
|
|
2704
2498
|
// src/commands/upgrade.ts
|
|
2705
|
-
var
|
|
2499
|
+
var import_node_fs9 = require("fs");
|
|
2706
2500
|
var import_node_path14 = require("path");
|
|
2707
2501
|
function resolveRegistry2(options, persisted) {
|
|
2708
2502
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
@@ -2732,7 +2526,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
2732
2526
|
return persisted.workspaceName;
|
|
2733
2527
|
}
|
|
2734
2528
|
try {
|
|
2735
|
-
const existing = (0,
|
|
2529
|
+
const existing = (0, import_node_fs9.readdirSync)(workspaceRoot).find(
|
|
2736
2530
|
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
2737
2531
|
);
|
|
2738
2532
|
if (existing) {
|
|
@@ -2761,7 +2555,6 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
2761
2555
|
);
|
|
2762
2556
|
}
|
|
2763
2557
|
const variableGroup = options.variableGroup ?? persisted.variableGroup ?? "Build";
|
|
2764
|
-
const linter = options.linter ?? persisted.stack?.linter ?? "eslint";
|
|
2765
2558
|
const testRunner = options.testRunner ?? persisted.stack?.testRunner;
|
|
2766
2559
|
if (!testRunner) {
|
|
2767
2560
|
throw new Error(
|
|
@@ -2775,7 +2568,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
2775
2568
|
agent,
|
|
2776
2569
|
variableGroup,
|
|
2777
2570
|
ci,
|
|
2778
|
-
stack: { testRunner
|
|
2571
|
+
stack: { testRunner }
|
|
2779
2572
|
};
|
|
2780
2573
|
}
|
|
2781
2574
|
function runUpgrade(workspaceRoot, options) {
|
|
@@ -2790,7 +2583,7 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
2790
2583
|
"Re-applying the MoNecromanCI overlay (release config, .npmrc, commitlint, pipeline, stack)"
|
|
2791
2584
|
);
|
|
2792
2585
|
applyOverlay(workspaceRoot, resolved);
|
|
2793
|
-
runFormatter(workspaceRoot
|
|
2586
|
+
runFormatter(workspaceRoot);
|
|
2794
2587
|
logger.success("Done. Review the changes with `git diff` before committing.");
|
|
2795
2588
|
}
|
|
2796
2589
|
|
|
@@ -2817,7 +2610,7 @@ async function runInteractive() {
|
|
|
2817
2610
|
}
|
|
2818
2611
|
|
|
2819
2612
|
// src/util/versionChecker.ts
|
|
2820
|
-
var
|
|
2613
|
+
var import_node_fs10 = require("fs");
|
|
2821
2614
|
var import_node_path16 = require("path");
|
|
2822
2615
|
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
2823
2616
|
var PACKAGE_NAME = "@mnci/cli";
|
|
@@ -2875,7 +2668,7 @@ function releaseTriple(version) {
|
|
|
2875
2668
|
function readCliVersion(packageDirectory) {
|
|
2876
2669
|
try {
|
|
2877
2670
|
const manifestPath = (0, import_node_path16.join)(packageDirectory, "..", "package.json");
|
|
2878
|
-
const manifest = JSON.parse((0,
|
|
2671
|
+
const manifest = JSON.parse((0, import_node_fs10.readFileSync)(manifestPath, "utf8"));
|
|
2879
2672
|
return manifest.version ?? "0.0.0";
|
|
2880
2673
|
} catch {
|
|
2881
2674
|
return "0.0.0";
|
|
@@ -2889,10 +2682,7 @@ function buildProgram(cliVersion) {
|
|
|
2889
2682
|
program.command("new").argument("[name]", "workspace name").description("Create a new monorepo (Nx TS preset + release/pipeline overlay)").option("-y, --yes", "accept defaults for anything not passed as a flag").option("--scope <scope>", "npm scope for publishable packages (e.g. @demo)").option("--registry <kind>", "azure-artifacts | npm").option("--organization <name>", "Azure DevOps organization").option("--project <name>", "Azure DevOps project").option("--artifacts-feed <name>", "Azure Artifacts feed").option(
|
|
2890
2683
|
"--agent <pool>",
|
|
2891
2684
|
"CI build agent: a vmImage (e.g. ubuntu-latest) or self-hosted pool name"
|
|
2892
|
-
).option("--variable-group <name>", "Azure DevOps variable group holding the npm PAT").option("--ci <provider>", "CI provider: azure | github | both").option("--test-runner <runner>", "unit-test runner: jest | vitest").option(
|
|
2893
|
-
"--linter <linter>",
|
|
2894
|
-
"linter + formatter: eslint (ESLint + Prettier) | oxlint (oxlint + oxfmt for JS/TS, ESLint for the rest)"
|
|
2895
|
-
).option("--nx-cloud", "connect the workspace to Nx Cloud (remote caching + CI insights)").action(async (name, options) => {
|
|
2685
|
+
).option("--variable-group <name>", "Azure DevOps variable group holding the npm PAT").option("--ci <provider>", "CI provider: azure | github | both").option("--test-runner <runner>", "unit-test runner: jest | vitest").option("--nx-cloud", "connect the workspace to Nx Cloud (remote caching + CI insights)").action(async (name, options) => {
|
|
2896
2686
|
await runNew(name, options);
|
|
2897
2687
|
});
|
|
2898
2688
|
program.command("upgrade").description(
|
|
@@ -2900,9 +2690,6 @@ function buildProgram(cliVersion) {
|
|
|
2900
2690
|
).option("--scope <scope>", "npm scope for publishable packages (overrides the persisted value)").option("--registry <kind>", "azure-artifacts | npm (overrides the persisted value)").option("--organization <name>", "Azure DevOps organization").option("--project <name>", "Azure DevOps project").option("--artifacts-feed <name>", "Azure Artifacts feed").option("--agent <pool>", "CI build agent (overrides the persisted value)").option("--variable-group <name>", "Azure DevOps variable group holding the npm PAT").option("--ci <provider>", "CI provider: azure | github | both (overrides the persisted value)").option(
|
|
2901
2691
|
"--test-runner <runner>",
|
|
2902
2692
|
"unit-test runner: jest | vitest (overrides the persisted value)"
|
|
2903
|
-
).option(
|
|
2904
|
-
"--linter <linter>",
|
|
2905
|
-
"linter + formatter: eslint | oxlint (overrides the persisted value)"
|
|
2906
2693
|
).action((options) => {
|
|
2907
2694
|
runUpgrade(process.cwd(), options);
|
|
2908
2695
|
});
|