diff --git a/common/autoinstallers/plugins/package.json b/common/autoinstallers/plugins/package.json new file mode 100644 index 00000000000..106dd139955 --- /dev/null +++ b/common/autoinstallers/plugins/package.json @@ -0,0 +1,8 @@ +{ + "name": "plugins", + "version": "1.0.0", + "private": true, + "dependencies": { + "@rushstack/rush-published-versions-json-plugin": "0.1.0" + } +} diff --git a/common/autoinstallers/plugins/pnpm-lock.yaml b/common/autoinstallers/plugins/pnpm-lock.yaml new file mode 100644 index 00000000000..3f722f3ce13 --- /dev/null +++ b/common/autoinstallers/plugins/pnpm-lock.yaml @@ -0,0 +1,316 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@rushstack/rush-published-versions-json-plugin': + specifier: 0.1.0 + version: 0.1.0 + +packages: + + '@pnpm/lockfile.types@900.0.0': + resolution: {integrity: sha512-/4+3CAu4uIjx0ln1DYXNdj0qKJ3wyRDY+RS+eFzV6OHjreaTKWsF2WcjigYp1M5mxL4kj2RsRGgBGEyKtCfEWg==} + engines: {node: '>=18.12'} + + '@pnpm/patching.types@900.0.0': + resolution: {integrity: sha512-A/3kgRD4Xy2tBMPjOBdx5ZdgmpUobphzWkqDB72S5SIB6gdyCg32AUV0/aO12DwMxpT7kyqMhkkynUOPBfdlUQ==} + engines: {node: '>=18.12'} + + '@pnpm/types@900.0.0': + resolution: {integrity: sha512-GucC9h/EVbU03Kl7M/FqVes1s5RCQaGCW2f41lFA7VqqHWQElR6k1q33iF6f6fXDUSCdzB1IUxSq9ghP2J+8Pw==} + engines: {node: '>=18.12'} + + '@rushstack/credential-cache@0.2.7': + resolution: {integrity: sha512-5vYUGreyf0ZvQ5lLFsQHLbJe1//hBZeI8G7BMoyDaLt4/uegfHNTmiXgYNXDQaqpnM9ImHyXSuOS/DrcbM3aMA==} + + '@rushstack/lookup-by-path@0.9.7': + resolution: {integrity: sha512-wlyXv5n0scQF7DEcv4KcFxsoVbSLXfZhVvS91S6gc6fOWpLoqIzSGANY9yIQtQpyJqrr0vwLUppa+zv/CB4sYw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/node-core-library@5.20.3': + resolution: {integrity: sha512-95JgEPq2k7tHxhF9/OJnnyHDXfC9cLhhta0An/6MlkDsX2A6dTzDrTUG18vx4vjc280V0fi0xDH9iQczpSuWsw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/package-deps-hash@4.7.7': + resolution: {integrity: sha512-nj7wspFmch+SmPr6RT46zO9aKGD6IjVBP8z3JMmiiJq5p7WgNyqEENOBWGZ42Hwpav9qjj9hWxMggHJiwLg3mA==} + + '@rushstack/problem-matcher@0.2.1': + resolution: {integrity: sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rush-published-versions-json-plugin@0.1.0': + resolution: {integrity: sha512-LS3U3ChGkS+6zRknmz4DT8LjegPBRFLs8pM2D3+s5fOn8bPxAiAVRtIfpkde02HSXyNf7h9RV8xn8Z13gBF54w==} + + '@rushstack/rush-sdk@5.172.0': + resolution: {integrity: sha512-SC5txCn1pFKfY2ozXSvppM9YViETmqUwRb0cpwhzKs5BqMDT5YcQHPwHySRjmzGaTEkHLT2VuTJ5iuJ2dpJzNQ==} + + '@rushstack/terminal@0.22.3': + resolution: {integrity: sha512-gHC9pIMrUPzAbBiI4VZMU7Q+rsCzb8hJl36lFIulIzoceKotyKL3Rd76AZ2CryCTKEg+0bnTj406HE5YY5OQvw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + +snapshots: + + '@pnpm/lockfile.types@900.0.0': + dependencies: + '@pnpm/patching.types': 900.0.0 + '@pnpm/types': 900.0.0 + + '@pnpm/patching.types@900.0.0': {} + + '@pnpm/types@900.0.0': {} + + '@rushstack/credential-cache@0.2.7': + dependencies: + '@rushstack/node-core-library': 5.20.3 + transitivePeerDependencies: + - '@types/node' + + '@rushstack/lookup-by-path@0.9.7': {} + + '@rushstack/node-core-library@5.20.3': + dependencies: + ajv: 8.18.0 + ajv-draft-04: 1.0.0(ajv@8.18.0) + ajv-formats: 3.0.1(ajv@8.18.0) + fs-extra: 11.3.4 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.11 + semver: 7.5.4 + + '@rushstack/package-deps-hash@4.7.7': + dependencies: + '@rushstack/node-core-library': 5.20.3 + transitivePeerDependencies: + - '@types/node' + + '@rushstack/problem-matcher@0.2.1': {} + + '@rushstack/rush-published-versions-json-plugin@0.1.0': + dependencies: + '@rushstack/node-core-library': 5.20.3 + '@rushstack/rush-sdk': 5.172.0 + '@rushstack/terminal': 0.22.3 + transitivePeerDependencies: + - '@types/node' + + '@rushstack/rush-sdk@5.172.0': + dependencies: + '@pnpm/lockfile.types-900': '@pnpm/lockfile.types@900.0.0' + '@rushstack/credential-cache': 0.2.7 + '@rushstack/lookup-by-path': 0.9.7 + '@rushstack/node-core-library': 5.20.3 + '@rushstack/package-deps-hash': 4.7.7 + '@rushstack/terminal': 0.22.3 + tapable: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@rushstack/terminal@0.22.3': + dependencies: + '@rushstack/node-core-library': 5.20.3 + '@rushstack/problem-matcher': 0.2.1 + supports-color: 8.1.1 + + ajv-draft-04@1.0.0(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.0: {} + + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + function-bind@1.1.2: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + import-lazy@4.0.0: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + jju@1.4.0: {} + + json-schema-traverse@1.0.0: {} + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + path-parse@1.0.7: {} + + require-from-string@2.0.2: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tapable@2.2.1: {} + + universalify@2.0.1: {} + + yallist@4.0.0: {} diff --git a/common/autoinstallers/plugins/rush-plugins/@rushstack/rush-published-versions-json-plugin/rush-plugin-manifest.json b/common/autoinstallers/plugins/rush-plugins/@rushstack/rush-published-versions-json-plugin/rush-plugin-manifest.json new file mode 100644 index 00000000000..03631898b98 --- /dev/null +++ b/common/autoinstallers/plugins/rush-plugins/@rushstack/rush-published-versions-json-plugin/rush-plugin-manifest.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json", + "plugins": [ + { + "pluginName": "rush-published-versions-json-plugin", + "description": "A Rush plugin for generating a JSON file containing the versions of all published packages in the monorepo.", + "entryPoint": "./lib-commonjs/index.js", + "associatedCommands": ["record-published-versions"], + "commandLineJsonFilePath": "./command-line.json" + } + ] +} diff --git a/common/autoinstallers/plugins/rush-plugins/@rushstack/rush-published-versions-json-plugin/rush-published-versions-json-plugin/command-line.json b/common/autoinstallers/plugins/rush-plugins/@rushstack/rush-published-versions-json-plugin/rush-published-versions-json-plugin/command-line.json new file mode 100644 index 00000000000..248cc35030b --- /dev/null +++ b/common/autoinstallers/plugins/rush-plugins/@rushstack/rush-published-versions-json-plugin/rush-published-versions-json-plugin/command-line.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", + "commands": [ + { + "commandKind": "globalPlugin", + "name": "record-published-versions", + "summary": "Generates a JSON file recording the version numbers of all published packages.", + "safeForSimultaneousRushProcesses": true + } + ], + "parameters": [ + { + "parameterKind": "string", + "longName": "--output-path", + "shortName": "-o", + "argumentName": "FILE_PATH", + "description": "The path to the output JSON file. Relative paths are resolved from the repo root.", + "associatedCommands": ["record-published-versions"], + "required": true + } + ] +} diff --git a/common/config/azure-pipelines/npm-post-publish.yaml b/common/config/azure-pipelines/npm-post-publish.yaml index 08eadb59b57..483168fa095 100644 --- a/common/config/azure-pipelines/npm-post-publish.yaml +++ b/common/config/azure-pipelines/npm-post-publish.yaml @@ -111,14 +111,21 @@ extends: --verbose DisplayName: 'Rush Build (repo-toolbox)' - - script: 'node repo-scripts/repo-toolbox/lib-commonjs/start.js bump-decoupled-local-dependencies' - displayName: 'Bump decoupled local dependencies' + - template: /common/config/azure-pipelines/templates/run-repo-toolbox.yaml@self + parameters: + Arguments: 'bump-decoupled-local-dependencies' + DisplayName: 'Bump decoupled local dependencies' - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self parameters: Arguments: 'update' DisplayName: 'Rush Update' + - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self + parameters: + Arguments: 'update-autoinstaller --name plugins' + DisplayName: 'Rush Update Autoinstaller (plugins)' + - bash: cp common/temp/install-run/@microsoft+rush@*/package-lock.json common/config/validation/rush-package-lock.json displayName: 'Update rush-package-lock.json' @@ -206,7 +213,11 @@ extends: # Run api-documenter with the Docusaurus plugin from the # api.rushstack.io project directory so it picks up # config/api-documenter.json. - - script: 'npx @microsoft/api-documenter@latest generate --input-folder $(Pipeline.Workspace)/api --output-folder ./docs/pages' + - script: > + npx @microsoft/api-documenter@latest + generate + --input-folder $(Pipeline.Workspace)/api + --output-folder ./docs/pages displayName: 'Generate API documentation' workingDirectory: websites/api.rushstack.io diff --git a/common/config/azure-pipelines/templates/post-publish.yaml b/common/config/azure-pipelines/templates/post-publish.yaml index 0a6f7528ef9..a08e554a06e 100644 --- a/common/config/azure-pipelines/templates/post-publish.yaml +++ b/common/config/azure-pipelines/templates/post-publish.yaml @@ -1,17 +1,23 @@ steps: - - script: > - node repo-scripts/repo-toolbox/lib-commonjs/start.js record-versions - --out-file $(Build.ArtifactStagingDirectory)/published-versions/published-versions.json - displayName: 'Record Published Versions' + - template: /common/config/azure-pipelines/templates/install-run-rush.yaml@self + parameters: + Arguments: > + record-published-versions + --output-path $(Build.ArtifactStagingDirectory)/published-versions/published-versions.json + DisplayName: 'Record Published Versions' - - script: > - node repo-scripts/repo-toolbox/lib-commonjs/start.js collect-project-files - --subfolder temp/json-schemas - --output-path $(Build.ArtifactStagingDirectory)/json-schemas - displayName: 'Collect JSON Schemas' + - template: /common/config/azure-pipelines/templates/run-repo-toolbox.yaml@self + parameters: + Arguments: > + collect-project-files + --subfolder temp/json-schemas + --output-path $(Build.ArtifactStagingDirectory)/json-schemas + DisplayName: 'Collect JSON Schemas' - - script: > - node repo-scripts/repo-toolbox/lib-commonjs/start.js collect-project-files - --subfolder temp/api - --output-path $(Build.ArtifactStagingDirectory)/api - displayName: 'Collect API review files' + - template: /common/config/azure-pipelines/templates/run-repo-toolbox.yaml@self + parameters: + Arguments: > + collect-project-files + --subfolder temp/api + --output-path $(Build.ArtifactStagingDirectory)/api + DisplayName: 'Collect API review files' diff --git a/common/config/azure-pipelines/templates/run-repo-toolbox.yaml b/common/config/azure-pipelines/templates/run-repo-toolbox.yaml new file mode 100644 index 00000000000..7e8786d8866 --- /dev/null +++ b/common/config/azure-pipelines/templates/run-repo-toolbox.yaml @@ -0,0 +1,10 @@ +# Runs repo-toolbox with the specified CLI arguments. +parameters: + - name: Arguments + type: string + - name: DisplayName + type: string + +steps: + - script: 'node repo-scripts/repo-toolbox/lib-commonjs/start.js ${{ parameters.Arguments }}' + displayName: '${{ parameters.DisplayName }}' diff --git a/common/config/rush/rush-plugins.json b/common/config/rush/rush-plugins.json index bee0e46c491..ad93f5d3910 100644 --- a/common/config/rush/rush-plugins.json +++ b/common/config/rush/rush-plugins.json @@ -25,5 +25,10 @@ // */ // "autoinstallerName": "rush-plugins" // } + { + "packageName": "@rushstack/rush-published-versions-json-plugin", + "pluginName": "rush-published-versions-json-plugin", + "autoinstallerName": "plugins" + } ] } diff --git a/repo-scripts/repo-toolbox/src/cli/ToolboxCommandLine.ts b/repo-scripts/repo-toolbox/src/cli/ToolboxCommandLine.ts index bf98ea120da..6a79c0ce0c8 100644 --- a/repo-scripts/repo-toolbox/src/cli/ToolboxCommandLine.ts +++ b/repo-scripts/repo-toolbox/src/cli/ToolboxCommandLine.ts @@ -5,7 +5,6 @@ import { CommandLineParser } from '@rushstack/ts-command-line'; import { ConsoleTerminalProvider, type ITerminal, Terminal } from '@rushstack/terminal'; import { ReadmeAction } from './actions/ReadmeAction'; -import { RecordVersionsAction } from './actions/RecordVersionsAction'; import { BumpDecoupledLocalDependencies } from './actions/BumpDecoupledLocalDependencies'; import { CollectProjectFilesAction } from './actions/CollectProjectFilesAction'; @@ -19,7 +18,6 @@ export class ToolboxCommandLine extends CommandLineParser { const terminal: ITerminal = new Terminal(new ConsoleTerminalProvider()); this.addAction(new ReadmeAction(terminal)); - this.addAction(new RecordVersionsAction(terminal)); this.addAction(new BumpDecoupledLocalDependencies(terminal)); this.addAction(new CollectProjectFilesAction(terminal)); } diff --git a/repo-scripts/repo-toolbox/src/cli/actions/BumpDecoupledLocalDependencies.ts b/repo-scripts/repo-toolbox/src/cli/actions/BumpDecoupledLocalDependencies.ts index eb9172aa678..14657e0be70 100644 --- a/repo-scripts/repo-toolbox/src/cli/actions/BumpDecoupledLocalDependencies.ts +++ b/repo-scripts/repo-toolbox/src/cli/actions/BumpDecoupledLocalDependencies.ts @@ -3,9 +3,9 @@ import type { ChildProcess } from 'node:child_process'; -import { Async, Executable, JsonFile } from '@rushstack/node-core-library'; +import { Async, Executable, FileSystem, type FolderItem, JsonFile } from '@rushstack/node-core-library'; import type { ITerminal } from '@rushstack/terminal'; -import { DependencyType, RushConfiguration } from '@microsoft/rush-lib'; +import { DependencyType, PackageJsonEditor, RushConfiguration, type Subspace } from '@microsoft/rush-lib'; import type { IRushConfigurationJson } from '@microsoft/rush-lib/lib/api/RushConfiguration'; import { CommandLineAction } from '@rushstack/ts-command-line'; @@ -30,6 +30,13 @@ async function _getLatestPublishedVersionAsync(terminal: ITerminal, packageName: }); } +interface IProjectLike { + packageName: string; + decoupledLocalDependencies: Iterable; + subspace: Subspace | undefined; + packageJsonEditor: PackageJsonEditor; +} + export class BumpDecoupledLocalDependencies extends CommandLineAction { private readonly _terminal: ITerminal; @@ -45,21 +52,78 @@ export class BumpDecoupledLocalDependencies extends CommandLineAction { protected override async onExecuteAsync(): Promise { const terminal: ITerminal = this._terminal; - const { projects, rushJsonFile } = RushConfiguration.loadFromDefaultLocation({ + const rushConfiguration: RushConfiguration = RushConfiguration.loadFromDefaultLocation({ startingFolder: process.cwd() }); + const { projects, rushJsonFile, commonAutoinstallersFolder } = rushConfiguration; - const cyclicDependencyNames: Set = new Set(); + const projectsToUpdate: IProjectLike[] = []; - for (const { decoupledLocalDependencies } of projects) { + const allDecoupledLocalDependencyNames: Set = new Set(); + for (const project of projects) { + const { decoupledLocalDependencies } = project; for (const decoupledLocalDependency of decoupledLocalDependencies) { - cyclicDependencyNames.add(decoupledLocalDependency); + allDecoupledLocalDependencyNames.add(decoupledLocalDependency); + } + + projectsToUpdate.push(project); + } + + // Collect all package names published from this repo + const publishedPackageNames: Set = new Set(); + for (const { shouldPublish, packageName } of projects) { + // Note that shouldPublish is also true here if the project is driven by a version policy + if (shouldPublish) { + publishedPackageNames.add(packageName); + } + } + + let autoinstallerEntries: FolderItem[] = []; + try { + autoinstallerEntries = await FileSystem.readFolderItemsAsync(commonAutoinstallersFolder); + } catch (error) { + if (!FileSystem.isNotExistError(error)) { + throw error; } } - const decoupledLocalDependencyVersionsByName: Map = new Map(); await Async.forEachAsync( - Array.from(cyclicDependencyNames), + autoinstallerEntries, + async (folderItem) => { + if (folderItem.isDirectory()) { + const autoinstallerName: string = folderItem.name; + const packageJsonPath: string = `${commonAutoinstallersFolder}/${autoinstallerName}/package.json`; + try { + const packageJsonEditor: PackageJsonEditor = PackageJsonEditor.load(packageJsonPath); + + const { dependencyList, devDependencyList } = packageJsonEditor; + const decoupledLocalDependencies: Set = new Set(); + for (const { name } of [...dependencyList, ...devDependencyList]) { + if (publishedPackageNames.has(name)) { + allDecoupledLocalDependencyNames.add(name); + decoupledLocalDependencies.add(name); + } + } + + projectsToUpdate.push({ + packageName: `${autoinstallerName} (autoinstaller)`, + decoupledLocalDependencies, + subspace: undefined, + packageJsonEditor + }); + } catch (error) { + if (!FileSystem.isNotExistError(error)) { + throw error; + } + } + } + }, + { concurrency: 10 } + ); + + const decoupledLocalDependencyVersionsByName: Map = new Map(); + await Async.forEachAsync( + allDecoupledLocalDependencyNames, async (decoupledLocalDependencyName) => { const version: string = await _getLatestPublishedVersionAsync(terminal, decoupledLocalDependencyName); decoupledLocalDependencyVersionsByName.set(decoupledLocalDependencyName, version); @@ -71,21 +135,17 @@ export class BumpDecoupledLocalDependencies extends CommandLineAction { terminal.writeLine(); - for (const { - packageName, - decoupledLocalDependencies, - subspace, - packageJson: { dependencies, devDependencies }, - packageJsonEditor - } of projects) { - const { allowedAlternativeVersions } = subspace.getCommonVersions(); + for (const { packageName, decoupledLocalDependencies, subspace, packageJsonEditor } of projectsToUpdate) { + const { allowedAlternativeVersions } = subspace?.getCommonVersions() ?? {}; for (const cyclicDependencyProject of decoupledLocalDependencies) { - const existingVersion: string | undefined = - dependencies?.[cyclicDependencyProject] ?? devDependencies?.[cyclicDependencyProject]; + const { version: existingVersion } = + packageJsonEditor.tryGetDependency(cyclicDependencyProject) ?? + packageJsonEditor.tryGetDevDependency(cyclicDependencyProject) ?? + {}; if ( existingVersion && - allowedAlternativeVersions.get(cyclicDependencyProject)?.includes(existingVersion) + allowedAlternativeVersions?.get(cyclicDependencyProject)?.includes(existingVersion) ) { // Skip if the existing version is allowed by common-versions.json continue; diff --git a/repo-scripts/repo-toolbox/src/cli/actions/RecordVersionsAction.ts b/repo-scripts/repo-toolbox/src/cli/actions/RecordVersionsAction.ts deleted file mode 100644 index 57dc988bdd5..00000000000 --- a/repo-scripts/repo-toolbox/src/cli/actions/RecordVersionsAction.ts +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See LICENSE in the project root for license information. - -import * as path from 'node:path'; - -import { JsonFile } from '@rushstack/node-core-library'; -import type { ITerminal } from '@rushstack/terminal'; -import { RushConfiguration } from '@microsoft/rush-lib'; -import { CommandLineAction, type CommandLineStringParameter } from '@rushstack/ts-command-line'; - -export class RecordVersionsAction extends CommandLineAction { - private readonly _outFilePath: CommandLineStringParameter; - - private readonly _terminal: ITerminal; - - public constructor(terminal: ITerminal) { - super({ - actionName: 'record-versions', - summary: 'Generates a JSON file recording the version numbers of all published packages.', - documentation: '' - }); - - this._terminal = terminal; - - this._outFilePath = this.defineStringParameter({ - parameterLongName: '--out-file', - parameterShortName: '-o', - argumentName: 'FILE_PATH', - description: 'The path to the output file.', - required: true - }); - } - - protected override async onExecuteAsync(): Promise { - const terminal: ITerminal = this._terminal; - const rushConfig: RushConfiguration = RushConfiguration.loadFromDefaultLocation({ - startingFolder: process.cwd() - }); - - terminal.writeLine(`Found Rush configuration at ${rushConfig.rushJsonFile}`); - - const publishedPackageVersions: Record = {}; - for (const project of rushConfig.projects) { - if (project.shouldPublish || project.versionPolicy) { - publishedPackageVersions[project.packageName] = project.packageJson.version; - } - } - - const resolvedOutputPath: string = path.resolve(process.cwd(), this._outFilePath.value!); - await JsonFile.saveAsync(publishedPackageVersions, resolvedOutputPath, { - ensureFolderExists: true - }); - - terminal.writeLine(`Wrote file to ${resolvedOutputPath}`); - } -}