Skip to content

[rush-lib][rush-published-versions-json-plugin] Add plugin-native global commands; add published versions JSON plugin.#5701

Open
iclanton wants to merge 6 commits intomicrosoft:mainfrom
iclanton:rush-published-versions-plugin
Open

[rush-lib][rush-published-versions-json-plugin] Add plugin-native global commands; add published versions JSON plugin.#5701
iclanton wants to merge 6 commits intomicrosoft:mainfrom
iclanton:rush-published-versions-plugin

Conversation

@iclanton
Copy link
Member

Summary

This PR makes two related changes:

  1. Extends the Rush plugin API to allow plugins to implement native global commands without requiring a shell script. Previously, global commands always required a shellCommand — plugins had no way to run their own code directly.

  2. Adds @rushstack/rush-published-versions-json-plugin, a new Rush plugin that generates a JSON file recording the version numbers of all published packages in a monorepo. Usage: rush record-published-versions --output-path <path>. This plugin is also the first consumer of the new API, serving as a reference implementation.

Details

Rush plugin API changes (@microsoft/rush-lib):

  • Added customParametersByLongName to IGlobalCommand, giving plugin hooks access to parsed command-line parameter values (e.g. --output-path). Parameters are keyed by long name and return CommandLineParameter objects from @rushstack/ts-command-line.
  • Added setHandled() to IGlobalCommand. When a plugin hook calls this, the default shell command execution is skipped. If a command has shellCommand: "" but no plugin calls setHandled(), a clear error is thrown.
  • Narrowed the beforeInstall hook's command type from IGlobalCommand to IRushCommand, since install/update actions were never global custom commands.

Plugin (@rushstack/rush-published-versions-json-plugin):

  • Provides a command-line.json defining the record-published-versions global command with a required --output-path string parameter and shellCommand: "".
  • The plugin's apply() method taps runGlobalCustomCommand.for('record-published-versions'), calls command.setHandled(), then generates a JSON map of { packageName: version } for all projects with shouldPublish or a versionPolicy.

Design alternatives considered:

  • Making shellCommand optional in the JSON schema — rejected because it would let repo users accidentally omit shellCommand and get a command that silently does nothing.
  • Using isFromPlugin flag on CommandLineConfiguration — replaced with the setHandled() approach, which is more explicit and lets the plugin itself declare that it handled the command.

No backwards compatibility concerns — IGlobalCommand is @beta and the new members are additive. Existing global commands with a shellCommand are unaffected.

How it was tested

  • Built @microsoft/rush-lib, @rushstack/rush-sdk, and @rushstack/rush-published-versions-json-plugin with rush build — all pass cleanly with no errors or warnings.
  • Verified the API review file (rush-lib.api.md) reflects the expected surface changes.

Impacted documentation

"summary": "Generates a JSON file recording the version numbers of all published packages.",
"safeForSimultaneousRushProcesses": true,
// The command is handled by the plugin, so we don't want Rush to attempt to execute anything.
"shellCommand": ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not make shellCommand optional?
is this to maintain backwards compat?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be optional in common/config/rush/command-line.json. I didn't make it optional for the sake of not forking the schema just for plugins.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This design might be a bit confusing. When a person sees "shellCommand": "" they would reasonably think nothing happens. How are they supposed to know that actually the implementation is provided in code?

"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json",
"commands": [
{
"commandKind": "global",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or perhaps this can be globalPlugin? to signify that it is handled by a rush plugin and does not need to provide a shell command. maybe it has an options param?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs triage

Development

Successfully merging this pull request may close these issues.

3 participants