@mnci/cli 4.41.0 → 4.43.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 +17 -0
- package/dist/cli.js +245 -93
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7896,6 +7896,10 @@ function runKinds(options) {
|
|
|
7896
7896
|
|
|
7897
7897
|
// src/workspace-diagnostics/check-invariants.use-case.ts
|
|
7898
7898
|
var import_node_child_process = require("child_process");
|
|
7899
|
+
var import_node_fs30 = require("fs");
|
|
7900
|
+
var import_node_path35 = require("path");
|
|
7901
|
+
|
|
7902
|
+
// src/workspace-diagnostics/locate-stranded-release-tags.use-case.ts
|
|
7899
7903
|
var import_node_fs29 = require("fs");
|
|
7900
7904
|
var import_node_path34 = require("path");
|
|
7901
7905
|
|
|
@@ -7924,14 +7928,28 @@ function findStrandedReleaseTags(projects, tags) {
|
|
|
7924
7928
|
return stranded;
|
|
7925
7929
|
}
|
|
7926
7930
|
|
|
7931
|
+
// src/workspace-diagnostics/locate-stranded-release-tags.use-case.ts
|
|
7932
|
+
var MNCI_TAG_PATTERN = "{projectName}@{version}";
|
|
7933
|
+
function locateStrandedReleaseTags(workspaceRoot, tagPattern) {
|
|
7934
|
+
if (tagPattern !== void 0 && tagPattern !== MNCI_TAG_PATTERN) {
|
|
7935
|
+
return [];
|
|
7936
|
+
}
|
|
7937
|
+
const listed = runCapture("git", ["tag", "--list"], workspaceRoot);
|
|
7938
|
+
if (listed.status !== 0) {
|
|
7939
|
+
return [];
|
|
7940
|
+
}
|
|
7941
|
+
const projects = (0, import_node_fs29.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot }).map((path) => readJson((0, import_node_path34.join)(workspaceRoot, path))).filter((manifest) => manifest.private !== true && manifest.name !== void 0).map((manifest) => manifest.name);
|
|
7942
|
+
return findStrandedReleaseTags(projects, listed.stdout.split(/\r?\n/).filter(Boolean));
|
|
7943
|
+
}
|
|
7944
|
+
|
|
7927
7945
|
// src/workspace-diagnostics/check-invariants.use-case.ts
|
|
7928
7946
|
var SUPPORTED_ESLINT_MAJOR = ESLINT_VERSION.replace(/^\D*/, "").split(".", 1)[0];
|
|
7929
7947
|
function toPosix2(path) {
|
|
7930
7948
|
return path.replaceAll("\\", "/");
|
|
7931
7949
|
}
|
|
7932
7950
|
function checkEslintConfigs(workspaceRoot) {
|
|
7933
|
-
const rootConfigs = (0,
|
|
7934
|
-
const projectConfigs = (0,
|
|
7951
|
+
const rootConfigs = (0, import_node_fs30.globSync)("eslint.config.{js,mjs,cjs,ts,mts,cts}", { cwd: workspaceRoot });
|
|
7952
|
+
const projectConfigs = (0, import_node_fs30.globSync)("{apps,libs,packages}/*/eslint.config.{js,mjs,cjs,ts,mts,cts}", {
|
|
7935
7953
|
cwd: workspaceRoot
|
|
7936
7954
|
}).map((config) => toPosix2(config));
|
|
7937
7955
|
return [
|
|
@@ -7951,10 +7969,10 @@ function checkEslintConfigs(workspaceRoot) {
|
|
|
7951
7969
|
];
|
|
7952
7970
|
}
|
|
7953
7971
|
function checkEslintEntryPointReachesTheRules(workspaceRoot) {
|
|
7954
|
-
const rules = (0,
|
|
7955
|
-
if (!(0,
|
|
7956
|
-
const entryPoint = (0,
|
|
7957
|
-
const source = (0,
|
|
7972
|
+
const rules = (0, import_node_path35.join)(workspaceRoot, ESLINT_MNCI_FILENAME);
|
|
7973
|
+
if (!(0, import_node_fs30.existsSync)(rules)) return [];
|
|
7974
|
+
const entryPoint = (0, import_node_path35.join)(workspaceRoot, ESLINT_USER_FILENAME);
|
|
7975
|
+
const source = (0, import_node_fs30.existsSync)(entryPoint) ? (0, import_node_fs30.readFileSync)(entryPoint, "utf8") : "";
|
|
7958
7976
|
return [
|
|
7959
7977
|
{
|
|
7960
7978
|
check: `${ESLINT_USER_FILENAME} imports the mnci rules`,
|
|
@@ -7967,7 +7985,7 @@ function checkEslintEntryPointReachesTheRules(workspaceRoot) {
|
|
|
7967
7985
|
function declaredDevDependencies(workspaceRoot) {
|
|
7968
7986
|
try {
|
|
7969
7987
|
const manifest = readJson(
|
|
7970
|
-
(0,
|
|
7988
|
+
(0, import_node_path35.join)(workspaceRoot, "package.json")
|
|
7971
7989
|
);
|
|
7972
7990
|
return manifest.devDependencies ?? {};
|
|
7973
7991
|
} catch {
|
|
@@ -7975,7 +7993,7 @@ function declaredDevDependencies(workspaceRoot) {
|
|
|
7975
7993
|
}
|
|
7976
7994
|
}
|
|
7977
7995
|
function checkNoRetiredFormatter(workspaceRoot) {
|
|
7978
|
-
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0,
|
|
7996
|
+
const files = RETIRED_FORMATTER_FILES.filter((file) => fileExists((0, import_node_path35.join)(workspaceRoot, file)));
|
|
7979
7997
|
const declared = ["prettier", "eslint-config-prettier", "oxlint", "oxfmt", "@mnci/oxlint-config"].filter((name) => declaredDevDependencies(workspaceRoot)[name] !== void 0);
|
|
7980
7998
|
const stale = [...files, ...declared];
|
|
7981
7999
|
if (stale.length === 0) {
|
|
@@ -8001,7 +8019,7 @@ function checkEslintPlugin(nxJson) {
|
|
|
8001
8019
|
};
|
|
8002
8020
|
}
|
|
8003
8021
|
function checkResolvedEslint(workspaceRoot) {
|
|
8004
|
-
const manifestPath = (0,
|
|
8022
|
+
const manifestPath = (0, import_node_path35.join)(workspaceRoot, "node_modules/eslint/package.json");
|
|
8005
8023
|
if (!fileExists(manifestPath)) {
|
|
8006
8024
|
return void 0;
|
|
8007
8025
|
}
|
|
@@ -8019,11 +8037,11 @@ function checkResolvedEslint(workspaceRoot) {
|
|
|
8019
8037
|
}
|
|
8020
8038
|
}
|
|
8021
8039
|
function checkNpmrc(workspaceRoot, registry, scope) {
|
|
8022
|
-
const npmrcPath = (0,
|
|
8040
|
+
const npmrcPath = (0, import_node_path35.join)(workspaceRoot, ".npmrc");
|
|
8023
8041
|
if (!registry || !fileExists(npmrcPath)) {
|
|
8024
8042
|
return void 0;
|
|
8025
8043
|
}
|
|
8026
|
-
const npmrc = (0,
|
|
8044
|
+
const npmrc = (0, import_node_fs30.readFileSync)(npmrcPath, "utf8");
|
|
8027
8045
|
if (registry.kind === "npm") {
|
|
8028
8046
|
return {
|
|
8029
8047
|
check: ".npmrc authenticates the public registry",
|
|
@@ -8040,11 +8058,11 @@ function checkNpmrc(workspaceRoot, registry, scope) {
|
|
|
8040
8058
|
};
|
|
8041
8059
|
}
|
|
8042
8060
|
function checkNpmrcCredentialResolves(workspaceRoot, environment = process.env) {
|
|
8043
|
-
const npmrcPath = (0,
|
|
8061
|
+
const npmrcPath = (0, import_node_path35.join)(workspaceRoot, ".npmrc");
|
|
8044
8062
|
if (!fileExists(npmrcPath)) {
|
|
8045
8063
|
return void 0;
|
|
8046
8064
|
}
|
|
8047
|
-
const npmrc = (0,
|
|
8065
|
+
const npmrc = (0, import_node_fs30.readFileSync)(npmrcPath, "utf8");
|
|
8048
8066
|
const credentials = npmrc.split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).filter((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
|
|
8049
8067
|
const referenced = [
|
|
8050
8068
|
...new Set(
|
|
@@ -8068,13 +8086,13 @@ function checkNpmrcCredentialResolves(workspaceRoot, environment = process.env)
|
|
|
8068
8086
|
};
|
|
8069
8087
|
}
|
|
8070
8088
|
function checkNpmAuthMatchesPipeline(workspaceRoot, registry) {
|
|
8071
|
-
const npmrcPath = (0,
|
|
8072
|
-
const pipelinePath = (0,
|
|
8089
|
+
const npmrcPath = (0, import_node_path35.join)(workspaceRoot, ".npmrc");
|
|
8090
|
+
const pipelinePath = (0, import_node_path35.join)(workspaceRoot, "azure-pipelines.yml");
|
|
8073
8091
|
if (registry?.kind !== "azure-artifacts" || !fileExists(npmrcPath) || !fileExists(pipelinePath)) {
|
|
8074
8092
|
return void 0;
|
|
8075
8093
|
}
|
|
8076
|
-
const holdsCredentials = (0,
|
|
8077
|
-
const runsTask = (0,
|
|
8094
|
+
const holdsCredentials = (0, import_node_fs30.readFileSync)(npmrcPath, "utf8").split("\n").filter((line) => !line.trimStart().startsWith(";") && !line.trimStart().startsWith("#")).some((line) => /(?:_authToken|_password|_auth)\s*=/u.test(line));
|
|
8095
|
+
const runsTask = (0, import_node_fs30.readFileSync)(pipelinePath, "utf8").includes("npmAuthenticate@0");
|
|
8078
8096
|
if (!holdsCredentials && !runsTask) {
|
|
8079
8097
|
return {
|
|
8080
8098
|
check: "npm auth: .npmrc and azure-pipelines.yml agree",
|
|
@@ -8119,13 +8137,13 @@ function npmjsCredentialShape(credentials, environment) {
|
|
|
8119
8137
|
}
|
|
8120
8138
|
function checkVersionActions(workspaceRoot) {
|
|
8121
8139
|
const candidates = [
|
|
8122
|
-
...(0,
|
|
8123
|
-
...(0,
|
|
8124
|
-
...(0,
|
|
8140
|
+
...(0, import_node_fs30.globSync)("packages/*/pubspec.yaml", { cwd: workspaceRoot }),
|
|
8141
|
+
...(0, import_node_fs30.globSync)("packages/*/*.csproj", { cwd: workspaceRoot }),
|
|
8142
|
+
...(0, import_node_fs30.globSync)("python-packages/*/pyproject.toml", { cwd: workspaceRoot })
|
|
8125
8143
|
].map((manifest) => toPosix2(manifest));
|
|
8126
8144
|
return candidates.flatMap((manifest) => {
|
|
8127
8145
|
const projectRoot = manifest.slice(0, manifest.lastIndexOf("/"));
|
|
8128
|
-
const projectJsonPath = (0,
|
|
8146
|
+
const projectJsonPath = (0, import_node_path35.join)(workspaceRoot, projectRoot, "project.json");
|
|
8129
8147
|
let hasOverride = false;
|
|
8130
8148
|
try {
|
|
8131
8149
|
const projectJson = readJson(projectJsonPath);
|
|
@@ -8154,7 +8172,7 @@ function declaredTargets(workspaceRoot, projectRoot) {
|
|
|
8154
8172
|
]) {
|
|
8155
8173
|
try {
|
|
8156
8174
|
const targets = extract(
|
|
8157
|
-
readJson((0,
|
|
8175
|
+
readJson((0, import_node_path35.join)(workspaceRoot, projectRoot, file))
|
|
8158
8176
|
);
|
|
8159
8177
|
if (targets && typeof targets === "object") {
|
|
8160
8178
|
sources.push({
|
|
@@ -8170,8 +8188,8 @@ function declaredTargets(workspaceRoot, projectRoot) {
|
|
|
8170
8188
|
function checkTargetFilesExist(workspaceRoot) {
|
|
8171
8189
|
const projectRoots = new Set(
|
|
8172
8190
|
[
|
|
8173
|
-
...(0,
|
|
8174
|
-
...(0,
|
|
8191
|
+
...(0, import_node_fs30.globSync)("{apps,libs,packages}/*/project.json", { cwd: workspaceRoot }),
|
|
8192
|
+
...(0, import_node_fs30.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot })
|
|
8175
8193
|
].map((manifest) => toPosix2(manifest).split("/").slice(0, 2).join("/"))
|
|
8176
8194
|
);
|
|
8177
8195
|
return [...projectRoots].flatMap(
|
|
@@ -8186,7 +8204,7 @@ function checkOneTargetsFiles(workspaceRoot, source, targetName, target) {
|
|
|
8186
8204
|
return TARGET_FILE_OPTIONS.flatMap((option) => {
|
|
8187
8205
|
const value = target?.options?.[option];
|
|
8188
8206
|
const checkable = typeof value === "string" && !value.includes("{");
|
|
8189
|
-
if (!checkable || fileExists((0,
|
|
8207
|
+
if (!checkable || fileExists((0, import_node_path35.join)(workspaceRoot, value))) {
|
|
8190
8208
|
return [];
|
|
8191
8209
|
}
|
|
8192
8210
|
return [
|
|
@@ -8225,15 +8243,15 @@ function checkGoPluginRegistered(workspaceRoot) {
|
|
|
8225
8243
|
};
|
|
8226
8244
|
}
|
|
8227
8245
|
function checkGoWorkInSync(workspaceRoot) {
|
|
8228
|
-
const goWorkPath = (0,
|
|
8246
|
+
const goWorkPath = (0, import_node_path35.join)(workspaceRoot, "go.work");
|
|
8229
8247
|
if (!fileExists(goWorkPath)) {
|
|
8230
8248
|
return void 0;
|
|
8231
8249
|
}
|
|
8232
|
-
const contents = (0,
|
|
8250
|
+
const contents = (0, import_node_fs30.existsSync)(goWorkPath) ? (0, import_node_fs30.readFileSync)(goWorkPath, "utf8") : "";
|
|
8233
8251
|
const blockEntries = Array.from(contents.matchAll(/(?:^|\n)\s*use\s+\(([^)]*)\)/g), (match) => match[1].split("\n")).flat();
|
|
8234
8252
|
const singleEntries = Array.from(contents.matchAll(/(?:^|\n)\s*use\s+(\.\S+)/g), (match) => match[1]);
|
|
8235
8253
|
const uses = [...blockEntries, ...singleEntries].map((entry) => entry.trim()).filter(Boolean);
|
|
8236
|
-
const stale = uses.filter((entry) => !(0,
|
|
8254
|
+
const stale = uses.filter((entry) => !(0, import_node_fs30.existsSync)((0, import_node_path35.join)(workspaceRoot, entry, "go.mod")));
|
|
8237
8255
|
return {
|
|
8238
8256
|
check: "every go.work `use` entry points to a module that still exists",
|
|
8239
8257
|
ok: stale.length === 0,
|
|
@@ -8249,9 +8267,9 @@ function checkNativeApps(workspaceRoot) {
|
|
|
8249
8267
|
{ file: ".github/workflows/ci.yml", marker: "native (${{ matrix.os }})" },
|
|
8250
8268
|
{ file: "azure-pipelines.yml", marker: "- job: native" }
|
|
8251
8269
|
];
|
|
8252
|
-
const findings = pipelines.filter(({ file }) => fileExists((0,
|
|
8270
|
+
const findings = pipelines.filter(({ file }) => fileExists((0, import_node_path35.join)(workspaceRoot, file))).map(({ file, marker }) => ({
|
|
8253
8271
|
check: `${file} builds the native apps on every OS`,
|
|
8254
|
-
ok: (0,
|
|
8272
|
+
ok: (0, import_node_fs30.readFileSync)((0, import_node_path35.join)(workspaceRoot, file), "utf8").includes(marker),
|
|
8255
8273
|
detail: `${file} has no native job: CI would verify a cgo app on the one agent that cannot build it`,
|
|
8256
8274
|
remedy: "run `mnci upgrade`"
|
|
8257
8275
|
}));
|
|
@@ -8264,7 +8282,7 @@ function checkNativeApps(workspaceRoot) {
|
|
|
8264
8282
|
return findings;
|
|
8265
8283
|
}
|
|
8266
8284
|
function checkNoRootRuntimeDependencies(workspaceRoot) {
|
|
8267
|
-
const manifestPath = (0,
|
|
8285
|
+
const manifestPath = (0, import_node_path35.join)(workspaceRoot, "package.json");
|
|
8268
8286
|
if (!fileExists(manifestPath)) {
|
|
8269
8287
|
return void 0;
|
|
8270
8288
|
}
|
|
@@ -8284,14 +8302,14 @@ function checkNoRootRuntimeDependencies(workspaceRoot) {
|
|
|
8284
8302
|
};
|
|
8285
8303
|
}
|
|
8286
8304
|
function checkRollupSourceMaps(workspaceRoot) {
|
|
8287
|
-
const configs = (0,
|
|
8305
|
+
const configs = (0, import_node_fs30.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
8288
8306
|
cwd: workspaceRoot
|
|
8289
8307
|
}).map((config) => toPosix2(config));
|
|
8290
8308
|
return configs.flatMap((relativePath) => {
|
|
8291
|
-
const configPath = (0,
|
|
8309
|
+
const configPath = (0, import_node_path35.join)(workspaceRoot, relativePath);
|
|
8292
8310
|
let config;
|
|
8293
8311
|
try {
|
|
8294
|
-
config = (0,
|
|
8312
|
+
config = (0, import_node_fs30.readFileSync)(configPath, "utf8");
|
|
8295
8313
|
} catch {
|
|
8296
8314
|
return [];
|
|
8297
8315
|
}
|
|
@@ -8306,11 +8324,11 @@ function checkRollupSourceMaps(workspaceRoot) {
|
|
|
8306
8324
|
});
|
|
8307
8325
|
}
|
|
8308
8326
|
function checkDeclarationSpecifiers(workspaceRoot) {
|
|
8309
|
-
const configs = (0,
|
|
8327
|
+
const configs = (0, import_node_fs30.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
8310
8328
|
cwd: workspaceRoot
|
|
8311
8329
|
}).map((config) => toPosix2(config));
|
|
8312
8330
|
return configs.flatMap((relativePath) => {
|
|
8313
|
-
const configPath = (0,
|
|
8331
|
+
const configPath = (0, import_node_path35.join)(workspaceRoot, relativePath);
|
|
8314
8332
|
if (!fileExists(configPath)) {
|
|
8315
8333
|
return [];
|
|
8316
8334
|
}
|
|
@@ -8325,7 +8343,7 @@ function checkDeclarationSpecifiers(workspaceRoot) {
|
|
|
8325
8343
|
// `plugins` array (what @nx/react:library writes). For any other shape it would no-op, and
|
|
8326
8344
|
// naming a command that silently does nothing is the failure mode the source-map check
|
|
8327
8345
|
// above goes out of its way to avoid, so the remedy depends on the shape.
|
|
8328
|
-
remedy: canAddDeclarationSpecifierPlugin((0,
|
|
8346
|
+
remedy: canAddDeclarationSpecifierPlugin((0, import_node_fs30.readFileSync)(configPath, "utf8")) ? "run `mnci upgrade`, which adds the plugin to the plugins array of withNx's second argument" : "add the plugin to withNx's second argument by hand (copy it from a freshly `mnci add npm-lib`'d project) \u2014 mnci does not recognise the shape of this config, so `mnci upgrade` cannot add it"
|
|
8329
8347
|
}
|
|
8330
8348
|
];
|
|
8331
8349
|
}
|
|
@@ -8341,8 +8359,8 @@ function checkDeclarationSpecifiers(workspaceRoot) {
|
|
|
8341
8359
|
}
|
|
8342
8360
|
function checkPipelinePhases(workspaceRoot) {
|
|
8343
8361
|
const files = ["azure-pipelines.yml", ".github/workflows/ci.yml"];
|
|
8344
|
-
return files.filter((file) => fileExists((0,
|
|
8345
|
-
const { verifyActive, switchedOff } = inspectPipeline((0,
|
|
8362
|
+
return files.filter((file) => fileExists((0, import_node_path35.join)(workspaceRoot, file))).flatMap((file) => {
|
|
8363
|
+
const { verifyActive, switchedOff } = inspectPipeline((0, import_node_fs30.readFileSync)((0, import_node_path35.join)(workspaceRoot, file), "utf8"));
|
|
8346
8364
|
const verify = {
|
|
8347
8365
|
check: `${file} runs the enforced verify phase`,
|
|
8348
8366
|
ok: verifyActive,
|
|
@@ -8383,7 +8401,7 @@ function checkDependencyRangesNotPreserved(nxJson) {
|
|
|
8383
8401
|
};
|
|
8384
8402
|
}
|
|
8385
8403
|
function checkLockfileHasNoLocalRegistry(workspaceRoot) {
|
|
8386
|
-
if (!fileExists((0,
|
|
8404
|
+
if (!fileExists((0, import_node_path35.join)(workspaceRoot, "package-lock.json"))) {
|
|
8387
8405
|
return void 0;
|
|
8388
8406
|
}
|
|
8389
8407
|
return {
|
|
@@ -8394,16 +8412,7 @@ function checkLockfileHasNoLocalRegistry(workspaceRoot) {
|
|
|
8394
8412
|
};
|
|
8395
8413
|
}
|
|
8396
8414
|
function checkReleaseTagsResolve(workspaceRoot, nxJson) {
|
|
8397
|
-
const
|
|
8398
|
-
if (pattern !== void 0 && pattern !== "{projectName}@{version}") {
|
|
8399
|
-
return void 0;
|
|
8400
|
-
}
|
|
8401
|
-
const listed = runCapture("git", ["tag", "--list"], workspaceRoot);
|
|
8402
|
-
if (listed.status !== 0) {
|
|
8403
|
-
return void 0;
|
|
8404
|
-
}
|
|
8405
|
-
const projects = (0, import_node_fs29.globSync)("{apps,libs,packages}/*/package.json", { cwd: workspaceRoot }).map((path) => readJson((0, import_node_path34.join)(workspaceRoot, path))).filter((manifest) => manifest.private !== true && manifest.name !== void 0).map((manifest) => manifest.name);
|
|
8406
|
-
const stranded = findStrandedReleaseTags(projects, listed.stdout.split(/\r?\n/).filter(Boolean));
|
|
8415
|
+
const stranded = locateStrandedReleaseTags(workspaceRoot, nxJson.release?.releaseTag?.pattern);
|
|
8407
8416
|
return {
|
|
8408
8417
|
check: "release tags resolve under each project's current name",
|
|
8409
8418
|
ok: stranded.length === 0,
|
|
@@ -8412,7 +8421,7 @@ function checkReleaseTagsResolve(workspaceRoot, nxJson) {
|
|
|
8412
8421
|
};
|
|
8413
8422
|
}
|
|
8414
8423
|
function collectFindings(workspaceRoot) {
|
|
8415
|
-
const nxJsonPath = (0,
|
|
8424
|
+
const nxJsonPath = (0, import_node_path35.join)(workspaceRoot, "nx.json");
|
|
8416
8425
|
if (!fileExists(nxJsonPath)) {
|
|
8417
8426
|
throw new Error(
|
|
8418
8427
|
`No nx.json found in ${workspaceRoot} \u2014 run 'mnci doctor' from the workspace root.`
|
|
@@ -8476,11 +8485,146 @@ function runDoctor(workspaceRoot, options = {}) {
|
|
|
8476
8485
|
process.exitCode = 1;
|
|
8477
8486
|
}
|
|
8478
8487
|
|
|
8488
|
+
// src/repository-adoption/inspect-repository.use-case.ts
|
|
8489
|
+
var import_node_fs31 = require("fs");
|
|
8490
|
+
var import_node_path36 = require("path");
|
|
8491
|
+
var LOCKFILES = [
|
|
8492
|
+
["package-lock.json", "npm"],
|
|
8493
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
8494
|
+
["yarn.lock", "yarn"],
|
|
8495
|
+
["bun.lock", "bun"],
|
|
8496
|
+
["bun.lockb", "bun"]
|
|
8497
|
+
];
|
|
8498
|
+
var PERSONAL_FILES = ["CLAUDE.md", "AGENTS.md"];
|
|
8499
|
+
var RETIRED_FILE_PATTERN = /^(?:\.prettierrc.*|\.prettierignore|\.oxfmtrc\.json|oxlint\.config\.ts)$/;
|
|
8500
|
+
var RETIRED_NAMES = ["prettier", "oxfmt", "oxlint", "verdaccio"];
|
|
8501
|
+
function retiredNamesIn(manifest) {
|
|
8502
|
+
const declared = Object.keys({ ...manifest.dependencies, ...manifest.devDependencies });
|
|
8503
|
+
const scripts = Object.values(manifest.scripts ?? {}).join(" ");
|
|
8504
|
+
return RETIRED_NAMES.filter((name) => declared.includes(name) || new RegExp(String.raw`\b${name}\b`).test(scripts));
|
|
8505
|
+
}
|
|
8506
|
+
function inspectRepository(repositoryRoot) {
|
|
8507
|
+
const inside = runCapture("git", ["rev-parse", "--is-inside-work-tree"], repositoryRoot);
|
|
8508
|
+
const isGitRepo = inside.status === 0 && inside.stdout.trim() === "true";
|
|
8509
|
+
const dirty = isGitRepo && runCapture("git", ["status", "--porcelain"], repositoryRoot).stdout.trim() !== "";
|
|
8510
|
+
const tags = isGitRepo ? runCapture("git", ["tag", "--list"], repositoryRoot).stdout.split(/\r?\n/).filter(Boolean) : [];
|
|
8511
|
+
const manifestPath = (0, import_node_path36.join)(repositoryRoot, "package.json");
|
|
8512
|
+
const manifest = fileExists(manifestPath) ? readJson(manifestPath) : {};
|
|
8513
|
+
const nxJsonPath = (0, import_node_path36.join)(repositoryRoot, "nx.json");
|
|
8514
|
+
const nxJson = fileExists(nxJsonPath) ? readJson(nxJsonPath) : {};
|
|
8515
|
+
const ci = [];
|
|
8516
|
+
const pipelines = [];
|
|
8517
|
+
if ((0, import_node_fs31.existsSync)((0, import_node_path36.join)(repositoryRoot, "azure-pipelines.yml"))) {
|
|
8518
|
+
ci.push("azure");
|
|
8519
|
+
pipelines.push((0, import_node_path36.join)(repositoryRoot, "azure-pipelines.yml"));
|
|
8520
|
+
}
|
|
8521
|
+
const workflows = (0, import_node_path36.join)(repositoryRoot, ".github", "workflows");
|
|
8522
|
+
if ((0, import_node_fs31.existsSync)(workflows)) {
|
|
8523
|
+
const files = (0, import_node_fs31.readdirSync)(workflows).filter((file) => /\.ya?ml$/.test(file));
|
|
8524
|
+
if (files.length > 0) {
|
|
8525
|
+
ci.push("github");
|
|
8526
|
+
pipelines.push(...files.map((file) => (0, import_node_path36.join)(workflows, file)));
|
|
8527
|
+
}
|
|
8528
|
+
}
|
|
8529
|
+
const rootFiles = (0, import_node_fs31.readdirSync)(repositoryRoot);
|
|
8530
|
+
return {
|
|
8531
|
+
isGitRepo,
|
|
8532
|
+
dirty,
|
|
8533
|
+
packageManager: LOCKFILES.find(([file]) => rootFiles.includes(file))?.[1],
|
|
8534
|
+
nxVersion: manifest.devDependencies?.nx ?? manifest.dependencies?.nx,
|
|
8535
|
+
alreadyMnci: nxJson.mnci !== void 0,
|
|
8536
|
+
projects: locateProjects(repositoryRoot).map(({ name, dir, ecosystem }) => ({ name, dir, ecosystem })),
|
|
8537
|
+
tagCount: tags.length,
|
|
8538
|
+
strandedTags: isGitRepo ? locateStrandedReleaseTags(repositoryRoot, nxJson.release?.releaseTag?.pattern) : [],
|
|
8539
|
+
ci,
|
|
8540
|
+
pipelineUsesMnci: pipelines.some((file) => /\bmnci ci\b/.test((0, import_node_fs31.readFileSync)(file, "utf8"))),
|
|
8541
|
+
retiredTooling: [.../* @__PURE__ */ new Set([...rootFiles.filter((file) => RETIRED_FILE_PATTERN.test(file) || file === ".verdaccio"), ...retiredNamesIn(manifest)])],
|
|
8542
|
+
personalFiles: PERSONAL_FILES.filter((file) => rootFiles.includes(file))
|
|
8543
|
+
};
|
|
8544
|
+
}
|
|
8545
|
+
|
|
8546
|
+
// src/repository-adoption/judge-adoption.policy.ts
|
|
8547
|
+
function judgeAdoption(facts) {
|
|
8548
|
+
const findings = [];
|
|
8549
|
+
const blocker = (detail, step) => {
|
|
8550
|
+
findings.push({ severity: "blocker", detail, step });
|
|
8551
|
+
};
|
|
8552
|
+
const warning = (detail, step) => {
|
|
8553
|
+
findings.push({ severity: "warning", detail, step });
|
|
8554
|
+
};
|
|
8555
|
+
if (!facts.isGitRepo) {
|
|
8556
|
+
blocker("this directory is not a git repository", "run `git init` (or clone the repository) so every step can be its own commit");
|
|
8557
|
+
} else if (facts.dirty) {
|
|
8558
|
+
blocker("the working tree has uncommitted changes", "commit or stash them, so adoption starts from a state you can return to");
|
|
8559
|
+
}
|
|
8560
|
+
if (facts.packageManager !== void 0 && facts.packageManager !== "npm") {
|
|
8561
|
+
blocker(`the repository uses ${facts.packageManager}; mnci workspaces are npm workspaces`, "convert to npm first (out of scope for adopt for now)");
|
|
8562
|
+
}
|
|
8563
|
+
if (facts.projects.length === 0) {
|
|
8564
|
+
blocker("no project manifest was found under the repository", "run mnci adopt from the repository root, or `mnci new` for an empty one");
|
|
8565
|
+
}
|
|
8566
|
+
if (facts.alreadyMnci) {
|
|
8567
|
+
warning("nx.json already carries an mnci block, so this is an mnci workspace", "use `mnci upgrade`; adopt is for repositories mnci has not touched");
|
|
8568
|
+
}
|
|
8569
|
+
if (facts.nxVersion === void 0) {
|
|
8570
|
+
warning("Nx is not installed", "the toolchain step installs the Nx family at the version mnci supports (#380)");
|
|
8571
|
+
}
|
|
8572
|
+
if (facts.strandedTags.length > 0) {
|
|
8573
|
+
warning(
|
|
8574
|
+
`${facts.strandedTags.length} project(s) have release tags only under an old name (${facts.strandedTags.map((entry) => entry.project).join(", ")})`,
|
|
8575
|
+
"the tags step creates the baseline tags before the first release (#379)"
|
|
8576
|
+
);
|
|
8577
|
+
}
|
|
8578
|
+
if (facts.retiredTooling.length > 0) {
|
|
8579
|
+
warning(`retired tooling is present: ${facts.retiredTooling.join(", ")}`, "the toolchain step removes it (#380)");
|
|
8580
|
+
}
|
|
8581
|
+
if (facts.ci.length > 0 && !facts.pipelineUsesMnci) {
|
|
8582
|
+
warning(`an existing ${facts.ci.join(" and ")} pipeline does not call mnci`, "the pipeline step moves its custom steps into slots (#381)");
|
|
8583
|
+
}
|
|
8584
|
+
if (facts.personalFiles.length > 0) {
|
|
8585
|
+
warning(`${facts.personalFiles.join(", ")} exist and are yours`, "adoption leaves them alone; only a block marked by Nx is ever removed");
|
|
8586
|
+
}
|
|
8587
|
+
const ordered = [...findings.filter((finding) => finding.severity === "blocker"), ...findings.filter((finding) => finding.severity === "warning")];
|
|
8588
|
+
return { ready: ordered.every((finding) => finding.severity !== "blocker"), facts, findings: ordered };
|
|
8589
|
+
}
|
|
8590
|
+
|
|
8591
|
+
// src/repository-adoption/run-adopt.use-case.ts
|
|
8592
|
+
function reportAdoption(repositoryRoot) {
|
|
8593
|
+
return judgeAdoption(inspectRepository(repositoryRoot));
|
|
8594
|
+
}
|
|
8595
|
+
function runAdopt(repositoryRoot, options = {}) {
|
|
8596
|
+
const report = reportAdoption(repositoryRoot);
|
|
8597
|
+
if (!report.ready) {
|
|
8598
|
+
process.exitCode = 1;
|
|
8599
|
+
}
|
|
8600
|
+
if (options.json === true) {
|
|
8601
|
+
printJson(report);
|
|
8602
|
+
return;
|
|
8603
|
+
}
|
|
8604
|
+
const { facts } = report;
|
|
8605
|
+
logger.info(`${facts.projects.length} project(s), ${facts.tagCount} tag(s), ${facts.packageManager ?? "no lockfile"}, nx ${facts.nxVersion ?? "not installed"}`);
|
|
8606
|
+
for (const finding of report.findings) {
|
|
8607
|
+
const line = `${finding.severity === "blocker" ? "BLOCKER" : "warning"}: ${finding.detail}
|
|
8608
|
+
next: ${finding.step}`;
|
|
8609
|
+
if (finding.severity === "blocker") {
|
|
8610
|
+
logger.error(line);
|
|
8611
|
+
} else {
|
|
8612
|
+
logger.warn(line);
|
|
8613
|
+
}
|
|
8614
|
+
}
|
|
8615
|
+
if (report.ready) {
|
|
8616
|
+
logger.success("Nothing blocks adoption. This was a read-only report; nothing was changed.");
|
|
8617
|
+
} else {
|
|
8618
|
+
logger.error("Adoption is blocked. Clear the blockers above and run the report again.");
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
|
|
8479
8622
|
// src/command-catalog/command-groups.config.ts
|
|
8480
8623
|
var COMMAND_GROUPS = {
|
|
8481
8624
|
new: "workspace",
|
|
8482
8625
|
upgrade: "workspace",
|
|
8483
8626
|
doctor: "workspace",
|
|
8627
|
+
adopt: "inspect",
|
|
8484
8628
|
add: "projects",
|
|
8485
8629
|
install: "dependencies",
|
|
8486
8630
|
sync: "dependencies",
|
|
@@ -8546,11 +8690,11 @@ function runCommands(program, options) {
|
|
|
8546
8690
|
}
|
|
8547
8691
|
|
|
8548
8692
|
// src/workspace-info/list-projects.use-case.ts
|
|
8549
|
-
var
|
|
8693
|
+
var import_node_path37 = require("path");
|
|
8550
8694
|
var TYPE_TAG_PREFIX = "type:";
|
|
8551
8695
|
function listProjects(workspaceRoot) {
|
|
8552
8696
|
return locateProjects(workspaceRoot).map((location) => {
|
|
8553
|
-
const projectJsonPath = (0,
|
|
8697
|
+
const projectJsonPath = (0, import_node_path37.join)(workspaceRoot, location.dir, "project.json");
|
|
8554
8698
|
const project = fileExists(projectJsonPath) ? readJson(projectJsonPath) : {};
|
|
8555
8699
|
const typeTag = (project.tags ?? []).find((tag) => tag.startsWith(TYPE_TAG_PREFIX));
|
|
8556
8700
|
return {
|
|
@@ -8563,7 +8707,7 @@ function listProjects(workspaceRoot) {
|
|
|
8563
8707
|
}).toSorted((a, b) => a.dir.localeCompare(b.dir));
|
|
8564
8708
|
}
|
|
8565
8709
|
function runProjects(workspaceRoot, options) {
|
|
8566
|
-
if (!fileExists((0,
|
|
8710
|
+
if (!fileExists((0, import_node_path37.join)(workspaceRoot, "nx.json"))) {
|
|
8567
8711
|
throw new Error("No nx.json found here. Run `projects` from the workspace root.");
|
|
8568
8712
|
}
|
|
8569
8713
|
const projects = listProjects(workspaceRoot);
|
|
@@ -8577,11 +8721,11 @@ function runProjects(workspaceRoot, options) {
|
|
|
8577
8721
|
}
|
|
8578
8722
|
|
|
8579
8723
|
// src/workspace-info/read-workspace-info.use-case.ts
|
|
8580
|
-
var
|
|
8724
|
+
var import_node_path39 = require("path");
|
|
8581
8725
|
|
|
8582
8726
|
// src/cli-version/check-for-update.use-case.ts
|
|
8583
|
-
var
|
|
8584
|
-
var
|
|
8727
|
+
var import_node_fs32 = require("fs");
|
|
8728
|
+
var import_node_path38 = require("path");
|
|
8585
8729
|
var import_cross_spawn3 = __toESM(require("cross-spawn"));
|
|
8586
8730
|
var PACKAGE_NAME2 = "@mnci/cli";
|
|
8587
8731
|
var REGISTRY_TIMEOUT_MS = 2e3;
|
|
@@ -8640,8 +8784,8 @@ function releaseTriple(version) {
|
|
|
8640
8784
|
}
|
|
8641
8785
|
function readCliVersion(packageDirectory) {
|
|
8642
8786
|
try {
|
|
8643
|
-
const manifestPath = (0,
|
|
8644
|
-
const manifest = JSON.parse((0,
|
|
8787
|
+
const manifestPath = (0, import_node_path38.join)(packageDirectory, "..", "package.json");
|
|
8788
|
+
const manifest = JSON.parse((0, import_node_fs32.readFileSync)(manifestPath, "utf8"));
|
|
8645
8789
|
return manifest.version ?? "0.0.0";
|
|
8646
8790
|
} catch {
|
|
8647
8791
|
return "0.0.0";
|
|
@@ -8651,7 +8795,7 @@ function readCliVersion(packageDirectory) {
|
|
|
8651
8795
|
// src/workspace-info/read-workspace-info.use-case.ts
|
|
8652
8796
|
function readWorkspaceInfo(workspaceRoot, cliVersion) {
|
|
8653
8797
|
const latest = fetchLatestVersion() ?? null;
|
|
8654
|
-
const isWorkspace = fileExists((0,
|
|
8798
|
+
const isWorkspace = fileExists((0, import_node_path39.join)(workspaceRoot, "nx.json"));
|
|
8655
8799
|
return {
|
|
8656
8800
|
cli: {
|
|
8657
8801
|
version: cliVersion,
|
|
@@ -8672,8 +8816,8 @@ function runInfo(workspaceRoot, cliVersion, options) {
|
|
|
8672
8816
|
}
|
|
8673
8817
|
|
|
8674
8818
|
// src/workspace-creation/adopt-directory.use-case.ts
|
|
8675
|
-
var
|
|
8676
|
-
var
|
|
8819
|
+
var import_node_fs33 = require("fs");
|
|
8820
|
+
var import_node_path40 = require("path");
|
|
8677
8821
|
var NEVER_COPIED = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
8678
8822
|
var AGENT_AND_CI_ENTRIES = [
|
|
8679
8823
|
"AGENTS.md",
|
|
@@ -8704,13 +8848,13 @@ var PREFLIGHT_BLOCKERS = [
|
|
|
8704
8848
|
"packages"
|
|
8705
8849
|
];
|
|
8706
8850
|
function assertAdoptableDirectory(target) {
|
|
8707
|
-
if (!(0,
|
|
8851
|
+
if (!(0, import_node_fs33.existsSync)(target)) {
|
|
8708
8852
|
throw new Error(`--into '${target}' does not exist. Create or clone it first.`);
|
|
8709
8853
|
}
|
|
8710
|
-
if (!(0,
|
|
8854
|
+
if (!(0, import_node_fs33.statSync)(target).isDirectory()) {
|
|
8711
8855
|
throw new Error(`--into '${target}' is not a directory.`);
|
|
8712
8856
|
}
|
|
8713
|
-
const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0,
|
|
8857
|
+
const blockers = PREFLIGHT_BLOCKERS.filter((entry) => (0, import_node_fs33.existsSync)((0, import_node_path40.join)(target, entry)));
|
|
8714
8858
|
if (blockers.length > 0) {
|
|
8715
8859
|
throw new Error(
|
|
8716
8860
|
`--into '${target}' already holds ${blockers.join(", ")}, so it is a project already. Use \`mnci upgrade\` to re-apply the overlay to an existing workspace, or point --into at an empty checkout.`
|
|
@@ -8718,15 +8862,15 @@ function assertAdoptableDirectory(target) {
|
|
|
8718
8862
|
}
|
|
8719
8863
|
}
|
|
8720
8864
|
function mergeGitignore(generatedFile, targetFile) {
|
|
8721
|
-
const existing = (0,
|
|
8865
|
+
const existing = (0, import_node_fs33.readFileSync)(targetFile, "utf8");
|
|
8722
8866
|
const present = new Set(existing.split("\n").map((line) => line.trim()));
|
|
8723
|
-
const additions = (0,
|
|
8867
|
+
const additions = (0, import_node_fs33.readFileSync)(generatedFile, "utf8").split("\n").map((line) => line.trimEnd()).filter((line) => {
|
|
8724
8868
|
const trimmed = line.trim();
|
|
8725
8869
|
return trimmed !== "" && !trimmed.startsWith("#") && !present.has(trimmed);
|
|
8726
8870
|
});
|
|
8727
8871
|
if (additions.length === 0) return false;
|
|
8728
8872
|
const separator = existing.endsWith("\n") ? "" : "\n";
|
|
8729
|
-
(0,
|
|
8873
|
+
(0, import_node_fs33.writeFileSync)(
|
|
8730
8874
|
targetFile,
|
|
8731
8875
|
`${existing}${separator}
|
|
8732
8876
|
# Added by mnci (Nx workspace)
|
|
@@ -8736,9 +8880,9 @@ ${additions.join("\n")}
|
|
|
8736
8880
|
return true;
|
|
8737
8881
|
}
|
|
8738
8882
|
function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
8739
|
-
const entries = (0,
|
|
8883
|
+
const entries = (0, import_node_fs33.readdirSync)(generatedRoot).filter((entry) => !NEVER_COPIED.has(entry));
|
|
8740
8884
|
const collisions = entries.filter(
|
|
8741
|
-
(entry) => (0,
|
|
8885
|
+
(entry) => (0, import_node_fs33.existsSync)((0, import_node_path40.join)(target, entry)) && !EXISTING_WINS.has(entry) && entry !== ".gitignore"
|
|
8742
8886
|
);
|
|
8743
8887
|
if (collisions.length > 0) {
|
|
8744
8888
|
throw new Error(
|
|
@@ -8747,28 +8891,28 @@ function adoptGeneratedWorkspace(generatedRoot, target) {
|
|
|
8747
8891
|
}
|
|
8748
8892
|
const result = { copied: [], kept: [], mergedGitignore: false };
|
|
8749
8893
|
for (const entry of entries) {
|
|
8750
|
-
const from = (0,
|
|
8751
|
-
const to = (0,
|
|
8752
|
-
if (entry === ".gitignore" && (0,
|
|
8894
|
+
const from = (0, import_node_path40.join)(generatedRoot, entry);
|
|
8895
|
+
const to = (0, import_node_path40.join)(target, entry);
|
|
8896
|
+
if (entry === ".gitignore" && (0, import_node_fs33.existsSync)(to)) {
|
|
8753
8897
|
result.mergedGitignore = mergeGitignore(from, to);
|
|
8754
8898
|
result.kept.push(entry);
|
|
8755
8899
|
continue;
|
|
8756
8900
|
}
|
|
8757
|
-
if ((0,
|
|
8901
|
+
if ((0, import_node_fs33.existsSync)(to)) {
|
|
8758
8902
|
result.kept.push(entry);
|
|
8759
8903
|
continue;
|
|
8760
8904
|
}
|
|
8761
|
-
(0,
|
|
8905
|
+
(0, import_node_fs33.cpSync)(from, to, { recursive: true });
|
|
8762
8906
|
result.copied.push(entry);
|
|
8763
8907
|
}
|
|
8764
|
-
(0,
|
|
8908
|
+
(0, import_node_fs33.rmSync)(generatedRoot, { recursive: true, force: true });
|
|
8765
8909
|
return result;
|
|
8766
8910
|
}
|
|
8767
8911
|
|
|
8768
8912
|
// src/workspace-creation/create-workspace.use-case.ts
|
|
8769
|
-
var
|
|
8913
|
+
var import_node_fs34 = require("fs");
|
|
8770
8914
|
var import_node_os2 = require("os");
|
|
8771
|
-
var
|
|
8915
|
+
var import_node_path41 = require("path");
|
|
8772
8916
|
function nxCloudProviderValue(ci) {
|
|
8773
8917
|
return ci === "azure" ? "azure" : "github";
|
|
8774
8918
|
}
|
|
@@ -8811,9 +8955,9 @@ async function resolveRegistry(options) {
|
|
|
8811
8955
|
return await promptRegistry();
|
|
8812
8956
|
}
|
|
8813
8957
|
async function runNew(name, options) {
|
|
8814
|
-
const adoptTarget = options.into === void 0 ? void 0 : (0,
|
|
8958
|
+
const adoptTarget = options.into === void 0 ? void 0 : (0, import_node_path41.resolve)(process.cwd(), options.into);
|
|
8815
8959
|
if (adoptTarget !== void 0) assertAdoptableDirectory(adoptTarget);
|
|
8816
|
-
const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0,
|
|
8960
|
+
const workspaceName = name ?? (adoptTarget === void 0 ? await promptText("Workspace name") : (0, import_node_path41.basename)(adoptTarget));
|
|
8817
8961
|
assertValidProjectName(workspaceName, "Workspace name");
|
|
8818
8962
|
const scope = options.scope ?? (options.yes ? `@${workspaceName}` : await promptText("npm scope for publishable packages", `@${workspaceName}`));
|
|
8819
8963
|
const registry = await resolveRegistry(options);
|
|
@@ -8826,8 +8970,8 @@ async function runNew(name, options) {
|
|
|
8826
8970
|
const npmAuth = resolveNpmAuth(options.npmAuth, registry, ci);
|
|
8827
8971
|
const stack = await resolveStack(options);
|
|
8828
8972
|
const nxCloud = options.nxCloud ?? (options.yes ? false : await promptNxCloud());
|
|
8829
|
-
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0,
|
|
8830
|
-
let workspaceRoot = (0,
|
|
8973
|
+
const stagingParent = adoptTarget === void 0 ? process.cwd() : (0, import_node_fs34.mkdtempSync)((0, import_node_path41.join)((0, import_node_os2.tmpdir)(), "mnci-new-"));
|
|
8974
|
+
let workspaceRoot = (0, import_node_path41.join)(stagingParent, workspaceName);
|
|
8831
8975
|
try {
|
|
8832
8976
|
logger.step(`Creating Nx workspace '${workspaceName}' (preset: ts)`);
|
|
8833
8977
|
runNpx(
|
|
@@ -8850,7 +8994,7 @@ async function runNew(name, options) {
|
|
|
8850
8994
|
workspaceRoot = adoptTarget;
|
|
8851
8995
|
}
|
|
8852
8996
|
} finally {
|
|
8853
|
-
if (adoptTarget !== void 0) (0,
|
|
8997
|
+
if (adoptTarget !== void 0) (0, import_node_fs34.rmSync)(stagingParent, { recursive: true, force: true });
|
|
8854
8998
|
}
|
|
8855
8999
|
logger.step(
|
|
8856
9000
|
"Applying MoNecromanCI overlay (VS Code workspace, release config, .npmrc, commitlint, pipeline, stack)"
|
|
@@ -8860,8 +9004,8 @@ async function runNew(name, options) {
|
|
|
8860
9004
|
{ workspaceName, scope, registry, agent, variableGroup, ci, stack, ...npmAuth && { npmAuth } },
|
|
8861
9005
|
logger.detail
|
|
8862
9006
|
);
|
|
8863
|
-
(0,
|
|
8864
|
-
(0,
|
|
9007
|
+
(0, import_node_fs34.rmSync)((0, import_node_path41.join)(workspaceRoot, "node_modules"), { recursive: true, force: true });
|
|
9008
|
+
(0, import_node_fs34.rmSync)((0, import_node_path41.join)(workspaceRoot, "package-lock.json"), { force: true });
|
|
8865
9009
|
logger.step("Installing the toolchain (commitlint + husky + linting/formatting)");
|
|
8866
9010
|
const installStatus = runShell(
|
|
8867
9011
|
"npm",
|
|
@@ -8899,12 +9043,12 @@ function projectKindHintLines(kinds = PROJECT_KINDS) {
|
|
|
8899
9043
|
}
|
|
8900
9044
|
|
|
8901
9045
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
8902
|
-
var
|
|
9046
|
+
var import_node_path43 = require("path");
|
|
8903
9047
|
var import_prompts4 = require("@inquirer/prompts");
|
|
8904
9048
|
|
|
8905
9049
|
// src/workspace-upgrade/upgrade-workspace.use-case.ts
|
|
8906
|
-
var
|
|
8907
|
-
var
|
|
9050
|
+
var import_node_fs35 = require("fs");
|
|
9051
|
+
var import_node_path42 = require("path");
|
|
8908
9052
|
function resolveRegistry2(options, persisted) {
|
|
8909
9053
|
if (options.registry === "azure-artifacts" || options.organization && options.artifactsFeed) {
|
|
8910
9054
|
const persistedAzure = persisted?.kind === "azure-artifacts" ? persisted : void 0;
|
|
@@ -8933,7 +9077,7 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
8933
9077
|
return persisted.workspaceName;
|
|
8934
9078
|
}
|
|
8935
9079
|
try {
|
|
8936
|
-
const existing = (0,
|
|
9080
|
+
const existing = (0, import_node_fs35.readdirSync)(workspaceRoot).find(
|
|
8937
9081
|
(file) => file.endsWith(".code-workspace") && file !== "undefined.code-workspace"
|
|
8938
9082
|
);
|
|
8939
9083
|
if (existing) {
|
|
@@ -8941,11 +9085,11 @@ function resolveWorkspaceName(workspaceRoot, persisted) {
|
|
|
8941
9085
|
}
|
|
8942
9086
|
} catch {
|
|
8943
9087
|
}
|
|
8944
|
-
return (0,
|
|
9088
|
+
return (0, import_node_path42.basename)(workspaceRoot);
|
|
8945
9089
|
}
|
|
8946
9090
|
function detectNpmAuth(workspaceRoot) {
|
|
8947
9091
|
try {
|
|
8948
|
-
return (0,
|
|
9092
|
+
return (0, import_node_fs35.readFileSync)((0, import_node_path42.join)(workspaceRoot, "azure-pipelines.yml"), "utf8").includes("npmAuthenticate@0") ? "build-identity" : void 0;
|
|
8949
9093
|
} catch {
|
|
8950
9094
|
return void 0;
|
|
8951
9095
|
}
|
|
@@ -8992,7 +9136,7 @@ function resolveOverlayOptions(workspaceRoot, options, persisted) {
|
|
|
8992
9136
|
};
|
|
8993
9137
|
}
|
|
8994
9138
|
function runUpgrade(workspaceRoot, options) {
|
|
8995
|
-
if (!fileExists((0,
|
|
9139
|
+
if (!fileExists((0, import_node_path42.join)(workspaceRoot, "nx.json"))) {
|
|
8996
9140
|
throw new Error(
|
|
8997
9141
|
`No nx.json found in ${workspaceRoot} \u2014 this does not look like an Nx workspace. Run 'mnci upgrade' from the workspace root.`
|
|
8998
9142
|
);
|
|
@@ -9066,13 +9210,18 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
9066
9210
|
"Formatting the workspace (eslint --fix) \u2014 the slowest step, minutes on a large workspace"
|
|
9067
9211
|
);
|
|
9068
9212
|
runFormatter(workspaceRoot);
|
|
9213
|
+
const nxJson = readJson((0, import_node_path42.join)(workspaceRoot, "nx.json"));
|
|
9214
|
+
const stranded = locateStrandedReleaseTags(workspaceRoot, nxJson.release?.releaseTag?.pattern);
|
|
9215
|
+
for (const entry of stranded) {
|
|
9216
|
+
logger.warn(`${entry.project} has release tags only under ${entry.oldTag}: nx release would restart it from its disk version. Run \`git tag ${entry.newTag} ${entry.oldTag}^{commit}\` before the next release (\`mnci doctor\` lists them all).`);
|
|
9217
|
+
}
|
|
9069
9218
|
logger.success("Done. Review the changes with `git diff` before committing.");
|
|
9070
9219
|
logger.info("Run `npm install` and commit package-lock.json too: the overlay may have added or moved a dependency, and CI installs with `npm ci`, which refuses a stale lockfile.");
|
|
9071
9220
|
}
|
|
9072
9221
|
|
|
9073
9222
|
// src/workspace-creation/interactive-wizard.use-case.ts
|
|
9074
9223
|
async function runInteractive() {
|
|
9075
|
-
const inWorkspace = fileExists((0,
|
|
9224
|
+
const inWorkspace = fileExists((0, import_node_path43.join)(process.cwd(), "nx.json"));
|
|
9076
9225
|
const choiceNew = { name: "Create a new monorepo", value: "new" };
|
|
9077
9226
|
const choiceAdd = { name: "Add a project to this workspace", value: "add" };
|
|
9078
9227
|
const choiceUpgrade = {
|
|
@@ -9124,6 +9273,9 @@ function buildProgram(cliVersion) {
|
|
|
9124
9273
|
).option("--json", "print the findings as one JSON document, each with its remedy").action((options) => {
|
|
9125
9274
|
runDoctor(process.cwd(), options);
|
|
9126
9275
|
});
|
|
9276
|
+
program.command("adopt").description("Read an existing repository and report what bringing it under mnci would involve: blockers, warnings and the step that clears each. Read-only; exits non-zero when something blocks").option("--json", "print the report as one JSON document").action((options) => {
|
|
9277
|
+
runAdopt(process.cwd(), options);
|
|
9278
|
+
});
|
|
9127
9279
|
program.command("ci").addArgument(new import_commander.Argument("<phase>", "which phase of the pipeline to run").choices(CI_PHASES)).description(
|
|
9128
9280
|
"Run a phase of the CI pipeline here, the same way CI runs it: `verify` is the sync check and then every project (or, in a pull request, the affected ones) through lint, typecheck, test and build. `setup` installs the Python, Go and Flutter toolchains the workspace needs, `audit` fails on a known advisory that has a fix, `pack` builds the per-app artifacts, `release` versions, tags and publishes, and `native` builds the apps that need a C toolchain on this OS. Exits non-zero when it fails"
|
|
9129
9281
|
).action(async (phase) => {
|