@mnci/cli 4.2.3 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +156 -32
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -860,7 +860,7 @@ 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
862
|
function releaseGuard(pythonPublishEnv, nugetPublishEnv) {
|
|
863
|
-
return `node -e "const fs=require('node:fs'),cp=require('node:child_process');const
|
|
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
864
|
}
|
|
865
865
|
function pythonPublishEnvFragment(pythonPublishUrl2) {
|
|
866
866
|
return pythonPublishUrl2 ? `if(hasPython){env.TWINE_REPOSITORY_URL='${pythonPublishUrl2}';env.TWINE_USERNAME='AzureArtifacts';env.TWINE_PASSWORD=Buffer.from(process.env.PAT,'base64').toString()}` : "";
|
|
@@ -943,6 +943,18 @@ variables:
|
|
|
943
943
|
# agent OS.
|
|
944
944
|
- name: npm_config_cache
|
|
945
945
|
value: $(Pipeline.Workspace)/.npm
|
|
946
|
+
# Overrides the bump nx would compute from conventional commits for one
|
|
947
|
+
# release run \u2014 'major', 'minor', 'patch', or an exact version ('1.2.3').
|
|
948
|
+
# Defined here (rather than left unset) so $(RELEASE_SPECIFIER) always
|
|
949
|
+
# expands: an Azure Pipelines macro that names an undefined variable is
|
|
950
|
+
# left as the literal, unexpanded text '$(RELEASE_SPECIFIER)' rather than
|
|
951
|
+
# empty, which would otherwise reach the release guard below as a bogus
|
|
952
|
+
# value. Override it per run in Pipelines -> Run pipeline -> Variables, or
|
|
953
|
+
# set a repo-level default in Pipeline -> Edit -> Variables. See the
|
|
954
|
+
# release step below for why a bare keyword is unreliable once more than
|
|
955
|
+
# one package is releasable.
|
|
956
|
+
- name: RELEASE_SPECIFIER
|
|
957
|
+
value: ''
|
|
946
958
|
|
|
947
959
|
steps:
|
|
948
960
|
- checkout: self
|
|
@@ -1106,11 +1118,24 @@ steps:
|
|
|
1106
1118
|
# skip cleanly when there is nothing to release. When there are Python or
|
|
1107
1119
|
# C# packages and an Azure feed, twine/NuGet publish credentials are
|
|
1108
1120
|
# exported (raw PAT, decoded from the base64 variable).
|
|
1121
|
+
#
|
|
1122
|
+
# RELEASE_SPECIFIER (the pipeline variable above) overrides the bump nx
|
|
1123
|
+
# would compute from conventional commits for THIS run. In a workspace with
|
|
1124
|
+
# more than one releasable package, a bare keyword ('major'/'minor'/'patch')
|
|
1125
|
+
# is unreliable \u2014 nx versions interdependent packages in two passes (a
|
|
1126
|
+
# dependency-bump pass, then the specifier pass), and the second pass
|
|
1127
|
+
# computes from a version cached before the first pass ran, silently
|
|
1128
|
+
# landing back on the same patch bump either way. An exact version ('1.2.3')
|
|
1129
|
+
# does not have this problem, since both passes apply it verbatim \u2014 prefer
|
|
1130
|
+
# it whenever more than one package is releasable. The guard below fails
|
|
1131
|
+
# the run rather than under-bumping silently: clear the variable back to
|
|
1132
|
+
# '' once the override is no longer needed.
|
|
1109
1133
|
- script: ${releaseGuard(pythonPublishEnvFragment(pythonPublishUrl2), nugetPublishEnvFragment(nugetFeedUrl2))}
|
|
1110
1134
|
displayName: Release \u2014 version, tag and publish (npm + Python + C#)
|
|
1111
1135
|
condition: ${onMain}
|
|
1112
1136
|
env:
|
|
1113
1137
|
${npmAuthName}: ${npmAuthValue}
|
|
1138
|
+
RELEASE_SPECIFIER: $(RELEASE_SPECIFIER)
|
|
1114
1139
|
|
|
1115
1140
|
# nx release's own git push (release.git.push) is deliberately left off: it
|
|
1116
1141
|
# only runs when a remote GitHub/GitLab Release is configured, which this
|
|
@@ -1262,7 +1287,7 @@ jobs:
|
|
|
1262
1287
|
# directly rather than a hand-rolled 'node -e' guard \u2014 see
|
|
1263
1288
|
# DOTNET_DETECT_AZURE's remarks for the full reasoning. hashFiles()
|
|
1264
1289
|
# gates it inline, so a JS-only workspace pays nothing.
|
|
1265
|
-
- uses: actions/setup-dotnet@
|
|
1290
|
+
- uses: actions/setup-dotnet@v6
|
|
1266
1291
|
if: \${{ hashFiles('apps/*/*.csproj', 'packages/*/*.csproj', 'libs/*/*.csproj') != '' }}
|
|
1267
1292
|
with:
|
|
1268
1293
|
dotnet-version: ${DOTNET_SDK_VERSION}
|
|
@@ -1306,7 +1331,21 @@ jobs:
|
|
|
1306
1331
|
# commits, tag-only push. Portable guard: nx release errors on an empty
|
|
1307
1332
|
# scope, so skip cleanly when there is nothing to release. When there
|
|
1308
1333
|
# are Python or C# packages and an Azure feed, twine/NuGet publish
|
|
1309
|
-
# credentials are exported (raw PAT, decoded from the base64 secret)
|
|
1334
|
+
# credentials are exported (raw PAT, decoded from the base64 secret).
|
|
1335
|
+
#
|
|
1336
|
+
# RELEASE_SPECIFIER (repository variable, Settings -> Secrets and
|
|
1337
|
+
# variables -> Actions -> Variables) overrides the bump nx would compute
|
|
1338
|
+
# from conventional commits for THIS run: 'major', 'minor', 'patch', or
|
|
1339
|
+
# an exact version ('1.2.3'). In a workspace with more than one
|
|
1340
|
+
# releasable package, a bare keyword is unreliable \u2014 nx versions
|
|
1341
|
+
# interdependent packages in two passes (a dependency-bump pass, then
|
|
1342
|
+
# the specifier pass), and the second pass computes from a version
|
|
1343
|
+
# cached before the first pass ran, silently landing back on the same
|
|
1344
|
+
# patch bump either way. An exact version does not have this problem,
|
|
1345
|
+
# since both passes apply it verbatim \u2014 prefer it whenever more than one
|
|
1346
|
+
# package is releasable. The guard below fails the run rather than
|
|
1347
|
+
# under-bumping silently: unset or clear the variable once the override
|
|
1348
|
+
# is no longer needed.${githubReleases ? `
|
|
1310
1349
|
# This provider also creates a per-project GitHub Release (changelog
|
|
1311
1350
|
# generated from conventional commits since that project's last tag),
|
|
1312
1351
|
# which is why 'nx release' pushes the tag itself here \u2014 see
|
|
@@ -1316,7 +1355,8 @@ jobs:
|
|
|
1316
1355
|
name: Release \u2014 version, tag${githubReleases ? ", publish and GitHub Release" : " and publish"} (npm + Python + C#)
|
|
1317
1356
|
if: \${{ ${onMain} }}
|
|
1318
1357
|
env:
|
|
1319
|
-
${npmAuthName}: ${npmAuthValue}
|
|
1358
|
+
${npmAuthName}: ${npmAuthValue}
|
|
1359
|
+
RELEASE_SPECIFIER: \${{ vars.RELEASE_SPECIFIER }}${githubReleases ? `
|
|
1320
1360
|
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}` : ""}
|
|
1321
1361
|
${githubReleases ? "" : `
|
|
1322
1362
|
# nx release's own git push (release.git.push) is deliberately left off: it
|
|
@@ -1675,31 +1715,9 @@ var SOURCEMAP_PATH_TRANSFORM = [
|
|
|
1675
1715
|
" },",
|
|
1676
1716
|
""
|
|
1677
1717
|
].join("\n");
|
|
1678
|
-
var
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
" // as a stub re-exporting the real declarations, and builds that specifier with",
|
|
1682
|
-
" // path.relative() - an OS-NATIVE path. On Windows it emits",
|
|
1683
|
-
String.raw` // export * from "./src\\index";`,
|
|
1684
|
-
" // which is not a valid module specifier on ANY platform: a specifier is",
|
|
1685
|
-
" // URL-style, so / is correct everywhere and a backslash nowhere. It resolves on",
|
|
1686
|
-
" // Windows only because the resolver normalises separators there, leaving the",
|
|
1687
|
-
" // package untyped on Linux and macOS.",
|
|
1688
|
-
" //",
|
|
1689
|
-
" // mnci also points `types` past this stub, so nothing depends on it being",
|
|
1690
|
-
" // correct; this makes the emitted file correct too. Remove once Nx fixes the",
|
|
1691
|
-
" // plugin - its own devkit already exports normalizePath for exactly this.",
|
|
1692
|
-
" //",
|
|
1693
|
-
" // The second half fixes a separate defect in the REAL declarations `types`",
|
|
1694
|
-
' // points at: tsconfig.lib.json declares under moduleResolution "bundler",',
|
|
1695
|
-
' // where a bare relative specifier ("./lib/align") is valid, so every emitted',
|
|
1696
|
-
" // .d.ts keeps the source's own extensionless imports verbatim. A consumer on",
|
|
1697
|
-
' // "moduleResolution": "nodenext" - the workspace root default - requires an',
|
|
1698
|
-
" // explicit extension on every relative specifier and gets TS2834 (or,",
|
|
1699
|
-
" // combined with skipLibCheck, a silent zero-export module) instead. Declared",
|
|
1700
|
-
" // extensions are left untouched; only a bare relative specifier gets .js",
|
|
1701
|
-
" // appended, matching what tsc itself emits under node16/nodenext.",
|
|
1702
|
-
" plugins: [",
|
|
1718
|
+
var DECLARATION_SPECIFIER_PLUGIN_MARKER = "name: 'mnci-normalise-declaration-specifiers'";
|
|
1719
|
+
var DECLARATION_SPECIFIER_EXTENSION_MARKER = "bareRelativeSpecifier";
|
|
1720
|
+
var DECLARATION_SPECIFIER_PLUGIN = [
|
|
1703
1721
|
" {",
|
|
1704
1722
|
" name: 'mnci-normalise-declaration-specifiers',",
|
|
1705
1723
|
" writeBundle (outputOptions) {",
|
|
@@ -1721,7 +1739,7 @@ var ROLLUP_CONFIG_WITH_DTS_FIX = [
|
|
|
1721
1739
|
" const normalised = source.replaceAll(separator, '/')",
|
|
1722
1740
|
" if (normalised !== source) writeFileSync(stub, normalised)",
|
|
1723
1741
|
"",
|
|
1724
|
-
String.raw` const
|
|
1742
|
+
String.raw` const ${DECLARATION_SPECIFIER_EXTENSION_MARKER} = /from(\s+)(['"])(\.[^'"]+?)\2/g`,
|
|
1725
1743
|
String.raw` const hasExtension = /\.(?:mjs|cjs|jsx?|json)$/`,
|
|
1726
1744
|
" let entries",
|
|
1727
1745
|
" try {",
|
|
@@ -1739,17 +1757,93 @@ var ROLLUP_CONFIG_WITH_DTS_FIX = [
|
|
|
1739
1757
|
" continue",
|
|
1740
1758
|
" }",
|
|
1741
1759
|
" const withExtensions = declaration.replace(",
|
|
1742
|
-
|
|
1760
|
+
` ${DECLARATION_SPECIFIER_EXTENSION_MARKER},`,
|
|
1743
1761
|
" (match, space, quote, specifier) =>",
|
|
1744
1762
|
" hasExtension.test(specifier) ? match : `from${space}${quote}${specifier}.js${quote}`,",
|
|
1745
1763
|
" )",
|
|
1746
1764
|
" if (withExtensions !== declaration) writeFileSync(filePath, withExtensions)",
|
|
1747
1765
|
" }",
|
|
1748
1766
|
" }",
|
|
1749
|
-
" }"
|
|
1767
|
+
" }"
|
|
1768
|
+
].join("\n");
|
|
1769
|
+
var ROLLUP_CONFIG_WITH_DTS_FIX = [
|
|
1770
|
+
" {",
|
|
1771
|
+
" // Added by MoNecromanCI. @nx/rollup's dts-bundle plugin writes dist/index.d.ts",
|
|
1772
|
+
" // as a stub re-exporting the real declarations, and builds that specifier with",
|
|
1773
|
+
" // path.relative() - an OS-NATIVE path. On Windows it emits",
|
|
1774
|
+
String.raw` // export * from "./src\\index";`,
|
|
1775
|
+
" // which is not a valid module specifier on ANY platform: a specifier is",
|
|
1776
|
+
" // URL-style, so / is correct everywhere and a backslash nowhere. It resolves on",
|
|
1777
|
+
" // Windows only because the resolver normalises separators there, leaving the",
|
|
1778
|
+
" // package untyped on Linux and macOS.",
|
|
1779
|
+
" //",
|
|
1780
|
+
" // mnci also points `types` past this stub, so nothing depends on it being",
|
|
1781
|
+
" // correct; this makes the emitted file correct too. Remove once Nx fixes the",
|
|
1782
|
+
" // plugin - its own devkit already exports normalizePath for exactly this.",
|
|
1783
|
+
" //",
|
|
1784
|
+
" // The second half fixes a separate defect in the REAL declarations `types`",
|
|
1785
|
+
' // points at: tsconfig.lib.json declares under moduleResolution "bundler",',
|
|
1786
|
+
' // where a bare relative specifier ("./lib/align") is valid, so every emitted',
|
|
1787
|
+
" // .d.ts keeps the source's own extensionless imports verbatim. A consumer on",
|
|
1788
|
+
' // "moduleResolution": "nodenext" - the workspace root default - requires an',
|
|
1789
|
+
" // explicit extension on every relative specifier and gets TS2834 (or,",
|
|
1790
|
+
" // combined with skipLibCheck, a silent zero-export module) instead. Declared",
|
|
1791
|
+
" // extensions are left untouched; only a bare relative specifier gets .js",
|
|
1792
|
+
" // appended, matching what tsc itself emits under node16/nodenext.",
|
|
1793
|
+
" plugins: [",
|
|
1794
|
+
DECLARATION_SPECIFIER_PLUGIN,
|
|
1750
1795
|
" ]",
|
|
1751
1796
|
" }"
|
|
1752
1797
|
].join("\n");
|
|
1798
|
+
function findEnclosingBraceSpan(text, needle) {
|
|
1799
|
+
const needleIndex = text.indexOf(needle);
|
|
1800
|
+
if (needleIndex === -1) {
|
|
1801
|
+
return void 0;
|
|
1802
|
+
}
|
|
1803
|
+
const start = text.lastIndexOf("{", needleIndex);
|
|
1804
|
+
if (start === -1) {
|
|
1805
|
+
return void 0;
|
|
1806
|
+
}
|
|
1807
|
+
let depth = 0;
|
|
1808
|
+
for (let index = start; index < text.length; index += 1) {
|
|
1809
|
+
if (text[index] === "{") {
|
|
1810
|
+
depth += 1;
|
|
1811
|
+
} else if (text[index] === "}") {
|
|
1812
|
+
depth -= 1;
|
|
1813
|
+
if (depth === 0) {
|
|
1814
|
+
return [start, index + 1];
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
return void 0;
|
|
1819
|
+
}
|
|
1820
|
+
function withUpgradedDeclarationSpecifierPlugin(config) {
|
|
1821
|
+
if (!config.includes(DECLARATION_SPECIFIER_PLUGIN_MARKER) || config.includes(DECLARATION_SPECIFIER_EXTENSION_MARKER)) {
|
|
1822
|
+
return config;
|
|
1823
|
+
}
|
|
1824
|
+
const span = findEnclosingBraceSpan(config, DECLARATION_SPECIFIER_PLUGIN_MARKER);
|
|
1825
|
+
if (!span) {
|
|
1826
|
+
return config;
|
|
1827
|
+
}
|
|
1828
|
+
const [start, end] = span;
|
|
1829
|
+
return `${config.slice(0, start)}${DECLARATION_SPECIFIER_PLUGIN}${config.slice(end)}`;
|
|
1830
|
+
}
|
|
1831
|
+
function upgradeDeclarationSpecifierPlugins(workspaceRoot) {
|
|
1832
|
+
const changed = [];
|
|
1833
|
+
const configs = (0, import_node_fs3.globSync)(["packages/*/rollup.config.cjs", "libs/*/rollup.config.cjs"], {
|
|
1834
|
+
cwd: workspaceRoot
|
|
1835
|
+
});
|
|
1836
|
+
for (const relativePath of configs) {
|
|
1837
|
+
const configPath = (0, import_node_path3.join)(workspaceRoot, relativePath);
|
|
1838
|
+
const before = (0, import_node_fs3.readFileSync)(configPath, "utf8");
|
|
1839
|
+
const after = withUpgradedDeclarationSpecifierPlugin(before);
|
|
1840
|
+
if (after !== before) {
|
|
1841
|
+
writeFileEnsured(configPath, after);
|
|
1842
|
+
changed.push(relativePath.replaceAll("\\", "/"));
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return changed;
|
|
1846
|
+
}
|
|
1753
1847
|
function repairDeclarationSpecifiers(projectRoot) {
|
|
1754
1848
|
const configPath = (0, import_node_path3.join)(projectRoot, "rollup.config.cjs");
|
|
1755
1849
|
if (!fileExists(configPath)) {
|
|
@@ -1812,6 +1906,22 @@ function repairPublishableManifest(manifestPath) {
|
|
|
1812
1906
|
}
|
|
1813
1907
|
writeFileEnsured(manifestPath, toJson(manifest));
|
|
1814
1908
|
}
|
|
1909
|
+
function repairPublishableManifests(workspaceRoot) {
|
|
1910
|
+
const changed = [];
|
|
1911
|
+
const manifests = (0, import_node_fs3.globSync)(["packages/*/package.json", "libs/*/package.json"], {
|
|
1912
|
+
cwd: workspaceRoot
|
|
1913
|
+
});
|
|
1914
|
+
for (const relativePath of manifests) {
|
|
1915
|
+
const manifestPath = (0, import_node_path3.join)(workspaceRoot, relativePath);
|
|
1916
|
+
const before = (0, import_node_fs3.readFileSync)(manifestPath, "utf8");
|
|
1917
|
+
repairPublishableManifest(manifestPath);
|
|
1918
|
+
const after = (0, import_node_fs3.readFileSync)(manifestPath, "utf8");
|
|
1919
|
+
if (after !== before) {
|
|
1920
|
+
changed.push(relativePath.replaceAll("\\", "/"));
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
return changed;
|
|
1924
|
+
}
|
|
1815
1925
|
function ensureAdmZip(workspaceRoot) {
|
|
1816
1926
|
if (hasPlugin(workspaceRoot, "adm-zip")) {
|
|
1817
1927
|
return;
|
|
@@ -4318,6 +4428,20 @@ function runUpgrade(workspaceRoot, options) {
|
|
|
4318
4428
|
logger.detail(`updated ${path}`);
|
|
4319
4429
|
}
|
|
4320
4430
|
}
|
|
4431
|
+
const repairedManifests = repairPublishableManifests(workspaceRoot);
|
|
4432
|
+
if (repairedManifests.length > 0) {
|
|
4433
|
+
logger.step("Repointing `types` at the real declaration file");
|
|
4434
|
+
for (const path of repairedManifests) {
|
|
4435
|
+
logger.detail(`updated ${path}`);
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
const upgradedDtsPlugins = upgradeDeclarationSpecifierPlugins(workspaceRoot);
|
|
4439
|
+
if (upgradedDtsPlugins.length > 0) {
|
|
4440
|
+
logger.step("Upgrading declaration specifiers to resolve under nodenext");
|
|
4441
|
+
for (const path of upgradedDtsPlugins) {
|
|
4442
|
+
logger.detail(`updated ${path}`);
|
|
4443
|
+
}
|
|
4444
|
+
}
|
|
4321
4445
|
logger.step(
|
|
4322
4446
|
"Formatting the workspace (eslint --fix) \u2014 the slowest step, minutes on a large workspace"
|
|
4323
4447
|
);
|