Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rush] Pass subspace parameter directly to SelectionParameterSet #4700

Merged
merged 10 commits into from
May 15, 2024

Conversation

william2958
Copy link
Contributor

@william2958 william2958 commented May 13, 2024

Summary

This MR addresses an issue where currently when the "--subspace" parameter is passed to the install or update action, i.e. rush install --subspace my_subspace, all projects in the entire monorepo will be selected to be installed.

Details

This issue was resolved by considering the "--subspace" cli parameter from BaseInstallAction as a selection, so the rush engine can detect that there are filters applied and doesn't try to do a global install. This MR also changes the way the "--subspace" parameter is treated, instead of a unique selector, it basically just maps to the same action as using the "--only subspace:my-subspace" selector.

How it was tested

This was tested on an existing subspace monorepo that was experiencing this issue.

Impacted documentation

public async getSelectedProjectsAsync(terminal: ITerminal): Promise<Set<RushConfigurationProject>> {
public async getSelectedProjectsAsync(
terminal: ITerminal,
subspaceName?: string
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of passing subspaceName, it would be more consistent for the constructor of SelectionParameterSet to accept an optional flag that tells it to create the special --subspace parameter. The design seems to be that SelectionParameterSet creates and owns its parameters rather than receiving their values as inputs to getSelectedProjectsAsync(), and it seems to me that --subspace is really just another selection parameter (albeit degenerate because it is only supported by some commands and uses a different syntax).

Copy link
Contributor

Choose a reason for hiding this comment

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

The main reason that SelectionParameterSet owns its own parameters is for DRY, since otherwise we were writing the same selection values over and over again.

Copy link
Collaborator

Choose a reason for hiding this comment

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

As of PR #4701, getSelectedProjectsAsync() calculates expressions using PNPM CLI operators like --filter ...my-app. These selections will malfunction with subspaces. As a workaround, when subspaces are enabled the args get overwritten with a flat list. For details, see fb2c242

In a future PR, Rush will need to (1) calculate the flat list of projects (without relying on PNPM operators) and (2) somehow communicate this list to pnpm install without exceeding the Windows maximum command length.

terminal,
parameterName: 'subspace'
})
: [];
Copy link
Collaborator

Choose a reason for hiding this comment

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

@dmichon-msft is there a perf concern if this sort of expression explodes into a set with 1000+ items? Does the Selection system have some efficient way to handle such sets? Or is it fast in practice?

Copy link
Contributor

Choose a reason for hiding this comment

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

If it becomes a problem we can replace the project selection with a bitvector, which makes set theoretic operations much faster.

Selection.union is O(elements)
Selection.expandAllDependencies is O(projects * directDependencies)
Selection.expandAllConsumers is O(projects * directConsumers)

So performance is bounded at O(projects^2). We can profile, but likely not a significant issue compared to some of the places in Webpack that were doing complex set arithmetic.

libraries/rush-lib/src/cli/actions/InstallAction.ts Outdated Show resolved Hide resolved
public async getSelectedProjectsAsync(terminal: ITerminal): Promise<Set<RushConfigurationProject>> {
public async getSelectedProjectsAsync(
terminal: ITerminal,
subspaceName?: string
Copy link
Contributor

Choose a reason for hiding this comment

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

The main reason that SelectionParameterSet owns its own parameters is for DRY, since otherwise we were writing the same selection values over and over again.

terminal,
parameterName: 'subspace'
})
: [];
Copy link
Contributor

Choose a reason for hiding this comment

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

If it becomes a problem we can replace the project selection with a bitvector, which makes set theoretic operations much faster.

Selection.union is O(elements)
Selection.expandAllDependencies is O(projects * directDependencies)
Selection.expandAllConsumers is O(projects * directConsumers)

So performance is bounded at O(projects^2). We can profile, but likely not a significant issue compared to some of the places in Webpack that were doing complex set arithmetic.

@octogonz
Copy link
Collaborator

This PR looks like a better approach than #4689. We should close that PR and pursue this one.

@william2958 william2958 marked this pull request as ready for review May 14, 2024 20:55
…13-20-35.json

Co-authored-by: Ian Clanton-Thuon <iclanton@users.noreply.github.com>
libraries/rush-lib/src/cli/actions/InstallAction.ts Outdated Show resolved Hide resolved
Comment on lines 296 to 302
console.log();
// eslint-disable-next-line no-console
console.log(
Colorize.red(
`The "${this._subspaceParameter?.longName}" parameter can only be passed if "subspacesEnabled" is set to true in subspaces.json.`
)
);
Copy link
Member

Choose a reason for hiding this comment

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

Sorta weird that stuff may be printed to the console when someone calls a get<something> function.

Copy link
Collaborator

Choose a reason for hiding this comment

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

🤔 True.

But this is a private API only used by CLI parsing code. And it's conceptually throwing an exception, just using the AlreadyReportedError formalism for better formatting.

We could rename getSelectedProjectsAsync() to something like getAndValidateProjectsAsync() but I wouldn't bother in this PR.

// Enable filtering to reduce evaluation cost
enableFiltering: true
},
false
Copy link
Member

Choose a reason for hiding this comment

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

Why can't someone run rush build --subspace my-subspace?

Copy link
Collaborator

Choose a reason for hiding this comment

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

They can do rush build --only subspace:my-subspace. But that is an "unsafe" selector, because it does not guarantee that dependencies get built. Thus a convenient --subspace macro isn't a good idea.

…ubspace:x" and change preventSelectingAllSubspaces to consider the command-line rather than the final selection
william2958 and others added 2 commits May 14, 2024 19:17
Make "rush install --subspace x" equivalent to "rush install --only subspace:x"
@octogonz octogonz changed the title Pass subspace parameter directly to SelectionParameterSet [rush] Pass subspace parameter directly to SelectionParameterSet May 15, 2024
@octogonz octogonz merged commit 2fb00ea into microsoft:main May 15, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

None yet

4 participants