@mnci/cli 4.3.0 → 4.3.2
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/cli.js +91 -6
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -859,8 +859,9 @@ var NPM_AUDIT_STEP = `node -e "const cp=require('node:child_process');const r=cp
|
|
|
859
859
|
var VERIFY_TARGETS = "lint,typecheck,test,build";
|
|
860
860
|
var AFFECTED_OR_ALL_GUARD = `node -e "const cp=require('node:child_process');const T='${VERIFY_TARGETS}';const all=()=>process.exit(cp.spawnSync('npx nx run-many -t '+T,{stdio:'inherit',shell:true}).status ?? 1);const ref=process.env.GITHUB_BASE_REF||process.env.SYSTEM_PULLREQUEST_TARGETBRANCH||'';if(!ref){console.log('Not a pull request - verifying EVERY project.');all()}const target=ref.replace('refs/heads/','');const mergeBase=r=>{const o=cp.spawnSync('git',['merge-base',r,'HEAD'],{encoding:'utf8'});return o.status===0?o.stdout.trim():''};let base=mergeBase('origin/'+target);if(!base){console.log('No origin/'+target+' ref - fetching it to resolve a merge-base.');cp.spawnSync('git',['fetch','--no-tags','origin',target],{stdio:'inherit'});base=mergeBase('FETCH_HEAD')}if(!base){console.log('Could not resolve a merge-base with '+target+' - verifying EVERY project.');all()}console.log('Pull request against '+target+' - verifying projects affected since '+base);process.exit(cp.spawnSync('npx nx affected -t '+T+' --base='+base,{stdio:'inherit',shell:true}).status ?? 1)"`;
|
|
861
861
|
var PACK_APPS_GUARD = `node -e "const fs=require('node:fs');fs.mkdirSync('dist/drop',{recursive:true});const hasProjectJson=fs.globSync('apps/*/project.json').length>0;const hasInlineNx=fs.globSync('apps/*/package.json').some((f)=>{try{return Boolean(JSON.parse(fs.readFileSync(f,'utf8')).nx)}catch{return false}});const hasCsproj=fs.globSync('apps/*/*.csproj').length>0;if(!hasProjectJson&&!hasInlineNx&&!hasCsproj){console.log('No apps to pack - skipping.');process.exit(0)}process.exit(require('node:child_process').spawnSync('npx nx run-many -t package',{stdio:'inherit',shell:true}).status ?? 1)"`;
|
|
862
|
+
var SHALLOW_CLONE_GUARD = `node -e "const r=require('node:child_process').spawnSync('git',['rev-parse','--is-shallow-repository'],{encoding:'utf8'});if(r.status!==0){console.error('Could not determine whether this checkout has full history (git rev-parse --is-shallow-repository failed) - refusing to release. '+(r.stderr||'').trim());process.exit(1)}if(r.stdout.trim()==='true'){console.error('This checkout is a shallow clone. nx release resolves the current version of each package from its git tag, and silently falls back to the permanently-stale on-disk version when a tag cannot be found - which can propose, and publish, a version DOWNGRADE. Fetch full history before releasing - set fetchDepth (Azure) or fetch-depth (GitHub) to 0.');process.exit(1)}"`;
|
|
862
863
|
function releaseGuard(pythonPublishEnv, nugetPublishEnv) {
|
|
863
|
-
return String.raw`node -e "const fs=require('node:fs'),cp=require('node:child_process');const npmCount=fs.globSync('packages/*/package.json').length;const csharpCount=fs.globSync('packages/*/*.csproj').length;const pythonCount=fs.globSync('python-packages/*/pyproject.toml').length;const hasNpm=npmCount>0;const hasPython=pythonCount>0;const hasCsharp=csharpCount>0;if(!hasNpm&&!hasPython&&!hasCsharp){console.log('Nothing to release - skipping.');process.exit(0)}const specifier=process.env.RELEASE_SPECIFIER||'';let releaseCmd='npx nx release --yes';if(specifier){if(!/^(major|minor|patch|\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?)$/.test(specifier)){console.error('RELEASE_SPECIFIER value \''+specifier+'\' is invalid - use major, minor, patch, or an exact version like 1.2.3.');process.exit(1)}const releaseProjectCount=npmCount+csharpCount+pythonCount;if(/^(major|minor|patch)$/.test(specifier)&&releaseProjectCount>1){console.error('RELEASE_SPECIFIER is a keyword (\''+specifier+'\') but this workspace has '+releaseProjectCount+' releasable packages - a keyword under-bumps interdependent packages, because nx computes the dependency-bump pass from a stale cached version. Set RELEASE_SPECIFIER to an exact version instead, or clear it.');process.exit(1)}releaseCmd='npx nx release '+specifier+' --yes'}const env={...process.env};${pythonPublishEnv}${nugetPublishEnv}process.exit(cp.spawnSync(releaseCmd,{stdio:'inherit',shell:true,env}).status ?? 1)"`;
|
|
864
|
+
return String.raw`node -e "const fs=require('node:fs'),cp=require('node:child_process');const npmCount=fs.globSync('packages/*/package.json').length;const csharpCount=fs.globSync('packages/*/*.csproj').length;const pythonCount=fs.globSync('python-packages/*/pyproject.toml').length;const dartCount=fs.globSync('packages/*/pubspec.yaml').length;const hasNpm=npmCount>0;const hasPython=pythonCount>0;const hasCsharp=csharpCount>0;const hasDart=dartCount>0;if(!hasNpm&&!hasPython&&!hasCsharp&&!hasDart){console.log('Nothing to release - skipping.');process.exit(0)}const specifier=process.env.RELEASE_SPECIFIER||'';let releaseCmd='npx nx release --yes';if(specifier){if(!/^(major|minor|patch|\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?)$/.test(specifier)){console.error('RELEASE_SPECIFIER value \''+specifier+'\' is invalid - use major, minor, patch, or an exact version like 1.2.3.');process.exit(1)}const releaseProjectCount=npmCount+csharpCount+pythonCount+dartCount;if(/^(major|minor|patch)$/.test(specifier)&&releaseProjectCount>1){console.error('RELEASE_SPECIFIER is a keyword (\''+specifier+'\') but this workspace has '+releaseProjectCount+' releasable packages - a keyword under-bumps interdependent packages, because nx computes the dependency-bump pass from a stale cached version. Set RELEASE_SPECIFIER to an exact version instead, or clear it.');process.exit(1)}releaseCmd='npx nx release '+specifier+' --yes'}const env={...process.env};${pythonPublishEnv}${nugetPublishEnv}process.exit(cp.spawnSync(releaseCmd,{stdio:'inherit',shell:true,env}).status ?? 1)"`;
|
|
864
865
|
}
|
|
865
866
|
function pythonPublishEnvFragment(pythonPublishUrl2) {
|
|
866
867
|
return pythonPublishUrl2 ? `if(hasPython){env.TWINE_REPOSITORY_URL='${pythonPublishUrl2}';env.TWINE_USERNAME='AzureArtifacts';env.TWINE_PASSWORD=Buffer.from(process.env.PAT,'base64').toString()}` : "";
|
|
@@ -1112,6 +1113,17 @@ steps:
|
|
|
1112
1113
|
displayName: Tag the run per app (type-name)
|
|
1113
1114
|
condition: ${onMain}
|
|
1114
1115
|
|
|
1116
|
+
# nx release resolves each package's current version from its git tag, and
|
|
1117
|
+
# falls back to the (permanently stale, since git.commit is false) on-disk
|
|
1118
|
+
# version when a tag cannot be resolved \u2014 which happens whenever this
|
|
1119
|
+
# checkout lacks full history. This is currently guaranteed by fetchDepth 0
|
|
1120
|
+
# above plus the explicit fetch below, but neither is expressed as a
|
|
1121
|
+
# dependency anywhere else, so this makes it a hard, loud precondition
|
|
1122
|
+
# instead of a silently wrong version discovered after release.
|
|
1123
|
+
- script: ${SHALLOW_CLONE_GUARD}
|
|
1124
|
+
displayName: Verify this is a full checkout (nx release needs the real tag history)
|
|
1125
|
+
condition: ${onMain}
|
|
1126
|
+
|
|
1115
1127
|
# Version + tag + publish, in one release, for npm (packages/*), Python
|
|
1116
1128
|
# (python-packages/*) AND C# (packages/*/*.csproj) \u2014 conventional commits,
|
|
1117
1129
|
# tag-only push. Portable guard: nx release errors on an empty scope, so
|
|
@@ -1326,6 +1338,18 @@ jobs:
|
|
|
1326
1338
|
path: dist/drop
|
|
1327
1339
|
if-no-files-found: ignore
|
|
1328
1340
|
|
|
1341
|
+
# nx release resolves each package's current version from its git tag,
|
|
1342
|
+
# and falls back to the (permanently stale, since git.commit is false)
|
|
1343
|
+
# on-disk version when a tag cannot be resolved \u2014 which happens
|
|
1344
|
+
# whenever this checkout lacks full history. This is currently
|
|
1345
|
+
# guaranteed by fetch-depth 0 above plus the explicit fetch below, but
|
|
1346
|
+
# neither is expressed as a dependency anywhere else, so this makes it
|
|
1347
|
+
# a hard, loud precondition instead of a silently wrong version
|
|
1348
|
+
# discovered after release.
|
|
1349
|
+
- run: ${SHALLOW_CLONE_GUARD}
|
|
1350
|
+
name: Verify this is a full checkout (nx release needs the real tag history)
|
|
1351
|
+
if: \${{ ${onMain} }}
|
|
1352
|
+
|
|
1329
1353
|
# Version + tag + publish, in one release, for npm (packages/*), Python
|
|
1330
1354
|
# (python-packages/*) AND C# (packages/*/*.csproj) \u2014 conventional
|
|
1331
1355
|
# commits, tag-only push. Portable guard: nx release errors on an empty
|
|
@@ -1717,11 +1741,18 @@ var SOURCEMAP_PATH_TRANSFORM = [
|
|
|
1717
1741
|
].join("\n");
|
|
1718
1742
|
var DECLARATION_SPECIFIER_PLUGIN_MARKER = "name: 'mnci-normalise-declaration-specifiers'";
|
|
1719
1743
|
var DECLARATION_SPECIFIER_EXTENSION_MARKER = "bareRelativeSpecifier";
|
|
1744
|
+
var DECLARATION_SPECIFIER_DIRECTORY_MARKER = "resolveSpecifierSuffix";
|
|
1745
|
+
function hasDeclarationSpecifierPlugin(config) {
|
|
1746
|
+
return config.includes(DECLARATION_SPECIFIER_PLUGIN_MARKER);
|
|
1747
|
+
}
|
|
1748
|
+
function hasDirectoryAwareDeclarationSpecifiers(config) {
|
|
1749
|
+
return config.includes(DECLARATION_SPECIFIER_DIRECTORY_MARKER);
|
|
1750
|
+
}
|
|
1720
1751
|
var DECLARATION_SPECIFIER_PLUGIN = [
|
|
1721
1752
|
" {",
|
|
1722
1753
|
" name: 'mnci-normalise-declaration-specifiers',",
|
|
1723
1754
|
" writeBundle (outputOptions) {",
|
|
1724
|
-
" const { readdirSync, readFileSync, writeFileSync } = require('node:fs')",
|
|
1755
|
+
" const { existsSync, readdirSync, readFileSync, writeFileSync } = require('node:fs')",
|
|
1725
1756
|
" const { join } = require('node:path')",
|
|
1726
1757
|
" const dir = outputOptions.dir ?? './dist'",
|
|
1727
1758
|
" const stub = join(dir, 'index.d.ts')",
|
|
@@ -1749,17 +1780,31 @@ var DECLARATION_SPECIFIER_PLUGIN = [
|
|
|
1749
1780
|
" }",
|
|
1750
1781
|
" for (const entry of entries) {",
|
|
1751
1782
|
" if (!entry.name.endsWith('.d.ts')) continue",
|
|
1752
|
-
" const
|
|
1783
|
+
" const from = entry.parentPath ?? entry.path",
|
|
1784
|
+
" const filePath = join(from, entry.name)",
|
|
1753
1785
|
" let declaration",
|
|
1754
1786
|
" try {",
|
|
1755
1787
|
" declaration = readFileSync(filePath, 'utf8')",
|
|
1756
1788
|
" } catch {",
|
|
1757
1789
|
" continue",
|
|
1758
1790
|
" }",
|
|
1791
|
+
" // A bare specifier may name a FILE or a DIRECTORY BARREL - resolved",
|
|
1792
|
+
" // against what rollup actually emitted next to this file, never",
|
|
1793
|
+
" // guessed. A directory needs /index.js, not .js (a file that was",
|
|
1794
|
+
" // never written); anything neither form matches is left alone rather",
|
|
1795
|
+
" // than rewritten to a specifier that cannot resolve.",
|
|
1796
|
+
` const ${DECLARATION_SPECIFIER_DIRECTORY_MARKER} = (specifier) => {`,
|
|
1797
|
+
" if (hasExtension.test(specifier)) return null",
|
|
1798
|
+
" if (existsSync(join(from, specifier + '.d.ts'))) return specifier + '.js'",
|
|
1799
|
+
" if (existsSync(join(from, specifier, 'index.d.ts'))) return specifier + '/index.js'",
|
|
1800
|
+
" return null",
|
|
1801
|
+
" }",
|
|
1759
1802
|
" const withExtensions = declaration.replace(",
|
|
1760
1803
|
` ${DECLARATION_SPECIFIER_EXTENSION_MARKER},`,
|
|
1761
|
-
" (match, space, quote, specifier) =>",
|
|
1762
|
-
|
|
1804
|
+
" (match, space, quote, specifier) => {",
|
|
1805
|
+
` const resolved = ${DECLARATION_SPECIFIER_DIRECTORY_MARKER}(specifier)`,
|
|
1806
|
+
" return resolved === null ? match : `from${space}${quote}${resolved}${quote}`",
|
|
1807
|
+
" },",
|
|
1763
1808
|
" )",
|
|
1764
1809
|
" if (withExtensions !== declaration) writeFileSync(filePath, withExtensions)",
|
|
1765
1810
|
" }",
|
|
@@ -1818,7 +1863,7 @@ function findEnclosingBraceSpan(text, needle) {
|
|
|
1818
1863
|
return void 0;
|
|
1819
1864
|
}
|
|
1820
1865
|
function withUpgradedDeclarationSpecifierPlugin(config) {
|
|
1821
|
-
if (!config.includes(DECLARATION_SPECIFIER_PLUGIN_MARKER) || config.includes(
|
|
1866
|
+
if (!config.includes(DECLARATION_SPECIFIER_PLUGIN_MARKER) || config.includes(DECLARATION_SPECIFIER_DIRECTORY_MARKER)) {
|
|
1822
1867
|
return config;
|
|
1823
1868
|
}
|
|
1824
1869
|
const span = findEnclosingBraceSpan(config, DECLARATION_SPECIFIER_PLUGIN_MARKER);
|
|
@@ -4059,6 +4104,7 @@ function checkNpmrc(workspaceRoot, registry, scope) {
|
|
|
4059
4104
|
function checkVersionActions(workspaceRoot) {
|
|
4060
4105
|
const candidates = [
|
|
4061
4106
|
...(0, import_node_fs9.globSync)("packages/*/pubspec.yaml", { cwd: workspaceRoot }),
|
|
4107
|
+
...(0, import_node_fs9.globSync)("packages/*/*.csproj", { cwd: workspaceRoot }),
|
|
4062
4108
|
...(0, import_node_fs9.globSync)("python-packages/*/pyproject.toml", { cwd: workspaceRoot })
|
|
4063
4109
|
].map((manifest) => toPosix2(manifest));
|
|
4064
4110
|
return candidates.flatMap((manifest) => {
|
|
@@ -4187,6 +4233,44 @@ function checkRollupSourceMaps(workspaceRoot) {
|
|
|
4187
4233
|
];
|
|
4188
4234
|
});
|
|
4189
4235
|
}
|
|
4236
|
+
function checkDeclarationSpecifiers(workspaceRoot) {
|
|
4237
|
+
const configs = (0, import_node_fs9.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
4238
|
+
cwd: workspaceRoot
|
|
4239
|
+
}).map((config) => toPosix2(config));
|
|
4240
|
+
return configs.flatMap((relativePath) => {
|
|
4241
|
+
const configPath = (0, import_node_path15.join)(workspaceRoot, relativePath);
|
|
4242
|
+
if (!fileExists(configPath)) {
|
|
4243
|
+
return [];
|
|
4244
|
+
}
|
|
4245
|
+
const resolved = resolveRollupConfigText(configPath);
|
|
4246
|
+
if (!hasDeclarationSpecifierPlugin(resolved)) {
|
|
4247
|
+
return [
|
|
4248
|
+
{
|
|
4249
|
+
check: `${relativePath} normalises declaration specifiers`,
|
|
4250
|
+
ok: false,
|
|
4251
|
+
detail: "no mnci-normalise-declaration-specifiers plugin \u2014 the emitted .d.ts files keep the extensionless imports tsconfig.lib.json allows, which a nodenext consumer cannot resolve",
|
|
4252
|
+
// Deliberately NOT `mnci upgrade`, which would send the user in a
|
|
4253
|
+
// circle: `upgradeDeclarationSpecifierPlugins` only rewrites a
|
|
4254
|
+
// plugin that is already there, and `repairDeclarationSpecifiers`
|
|
4255
|
+
// is anchored on the generator's own placeholder comment, which a
|
|
4256
|
+
// config in this state no longer has. Verified by running the
|
|
4257
|
+
// command against exactly this shape — it no-ops. Naming a command
|
|
4258
|
+
// that silently does nothing is the failure mode this file's own
|
|
4259
|
+
// source-map check already goes out of its way to avoid.
|
|
4260
|
+
remedy: "add the plugin to withNx's second argument by hand (copy it from a freshly `mnci add npm-lib`'d project) \u2014 `mnci upgrade` only updates a plugin that is already present, it cannot restore a missing one"
|
|
4261
|
+
}
|
|
4262
|
+
];
|
|
4263
|
+
}
|
|
4264
|
+
return [
|
|
4265
|
+
{
|
|
4266
|
+
check: `${relativePath} resolves directory barrels in declarations`,
|
|
4267
|
+
ok: hasDirectoryAwareDeclarationSpecifiers(resolved),
|
|
4268
|
+
detail: "the plugin appends .js to every bare specifier, including ones naming a directory barrel, which needs /index.js \u2014 the named file is never emitted, so every export behind it publishes as `any` with nothing reporting it",
|
|
4269
|
+
remedy: "run `mnci upgrade`, which replaces the plugin body with the current one"
|
|
4270
|
+
}
|
|
4271
|
+
];
|
|
4272
|
+
});
|
|
4273
|
+
}
|
|
4190
4274
|
function collectFindings(workspaceRoot) {
|
|
4191
4275
|
const nxJsonPath = (0, import_node_path15.join)(workspaceRoot, "nx.json");
|
|
4192
4276
|
if (!fileExists(nxJsonPath)) {
|
|
@@ -4203,6 +4287,7 @@ function collectFindings(workspaceRoot) {
|
|
|
4203
4287
|
checkNpmrc(workspaceRoot, nxJson.mnci?.registry, nxJson.mnci?.scope),
|
|
4204
4288
|
checkNoRootRuntimeDependencies(workspaceRoot),
|
|
4205
4289
|
...checkRollupSourceMaps(workspaceRoot),
|
|
4290
|
+
...checkDeclarationSpecifiers(workspaceRoot),
|
|
4206
4291
|
...checkVersionActions(workspaceRoot),
|
|
4207
4292
|
...checkTargetFilesExist(workspaceRoot),
|
|
4208
4293
|
checkSync(workspaceRoot)
|