From fd91308634c74e2b368d0d24fdc40f9094a0e6c0 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Thu, 22 Feb 2024 11:11:06 -0800 Subject: [PATCH 1/4] 'volta use' to replace 'install' and 'pin' --- text/0000-volta-use.md | 103 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 text/0000-volta-use.md diff --git a/text/0000-volta-use.md b/text/0000-volta-use.md new file mode 100644 index 0000000..f4de68a --- /dev/null +++ b/text/0000-volta-use.md @@ -0,0 +1,103 @@ +- Feature Name: volta_use +- Start Date: 2024-02-22 +- RFC PR: (leave this empty) +- Volta Issue: (leave this empty) + +# Summary + +[summary]: #summary + +Adding a new command, `volta use`, which combines the effects of `volta install` and `volta pin` into a single command that is more intuitive and better matches the mental model of Volta. + +# Motivation + +[motivation]: #motivation + +Early on in Volta's history, we picked the verb `install` to represent choosing the default version of tools (i.e. the version used when outside of a pinned project). This was chosen, in part, to align with users' expectations from other similar tools. However, due to Volta's auto-download behavior when it detects a version that isn't currently cached, `install` centers the wrong action. The more important part of `volta install` is the selecting a default version. + +This has led to some confusion for users. We get questions fairly regularly asking how users should select an "active" version of Node, once they have installed them using `volta install`. Additionally, by centering the install action, rather than the selection, `volta install` doesn't help users internalize Volta's mental model of "select a version and Volta will automatically download and make sure it's available." + +Selecting a different verb for the action of choosing a tool version should reduce confusion and make it more clear how Volta is intended to work. + +# Pedagogy + +[pedagogy]: #pedagogy + +This will be a fairly large change to our recommended workflows. As `volta use` will work for both pinning _and_ selecting a default version, we will need to update the documentation throughout to take advantage of the new command. We will also likely want to write a blog post for the release which includes this change, explaining the reasoning and the new workflows. + +Notably, we will _not_ be removing the existing `volta install` and `volta pin` commands right away. They will continue to work as they already do. In the future, we might consider adding notifications to them to point users to the updated command, but for the initial implementation we don't want to disrupt current users' workflows. + +All that said, the new command should simplify things a lot, especially for new users. It also will do a better job of living up to our website by truly having a _single_ command that users can use to get set up. + +# Details + +[details]: #details + +## Command definition + +``` +USAGE: + volta use [FLAGS] ... + +FLAGS: + -g, --global Select the global version of a tool, which is used everywhere outside of pinned projects + -p, --pin Pin a version of a tool to the local project, creating a Volta entry in package.json + +ARGS: + ... Tools to make available, like `node@lts` or `yarn@^1.14` +``` + +## Behavior + +The behavior of `volta use` will ultimately be the same as the current `volta install` or `volta pin`. However, when run without flags, it will be contextual, based on where the command is being run. So if a user runs `volta use node@18` in a pinned project, the project will be updated to reflect the newly selected version. If they instead run `volta use node@18` _outside_ of a pinned project, then the default Node version will be updated. This ensures that running `volta use node@version` will always update the version that is currently active, meaning the next run of `node` will use that updated version. + +Notably, if a user runs `volta use node` within a project that doesn't currently have a pinned version (i.e. has no `"volta"` entry in `package.json`), then the command will update the global / default version of Node, it will _not_ create a pin if one doesn't exist. + +If a user wants to change a version that isn't currently active, they can use the flags to change the behavior. + +### `--global` + +Running `volta use --global` will work identically to the existing `volta install`, updating the default version regardless of whether the current directory is part of a pinned project. + +### `--pin` + +Similarly, `volta use --pin` will work identically to the current `volta pin`, always updating the current project. This includes creating a `volta` key in `package.json` if it isn't there already. + +## Implementation + +The technical implementation of `volta use` should be fairly straightforward. The new command will use the flags and context (i.e. if we are currently in a pinned project or did the user pass `--global`) to determine whether the behavior should be equivalent to `volta install` or `volta pin`. It will then delegate to the appropriate existing command behavior based on that determination. The ultimate flow should be: + +- If `--global` was set -> use `volta install` behavior +- If `--pin` was set -> use `volta pin` behavior +- If _both_ were set, error (this can be handled by Clap I believe by making the two flags exclusive) +- If neither flag was set: + - If we are in a pinned project (one that already has a `"volta"` key in `package.json`) -> use `volta pin` behavior. + - Otherwise, use `volta install` behavior. + +# Critique + +[critique]: #critique + +## Confusion around omitting version + +One nice part about the existing `volta install` and `volta pin` commands is that they naturally work well with choosing a tool without selecting a version. For example, running `volta install node` makes intuitive sense as "pick whatever version and make it available." By contrast, `volta use node` doesn't immediately (to me, at least!) jump out as _picking_ a version of Node. `volta use node@lts` or similar, _do_ make sense, but omitting the version feels a little more awkward with `use` as the verb. + +## Changing only the verb for `install` + +One alternative would be to only change the verb for `install`, leaving `pin` completely untouched. This would be the least disruptive change, however it's very dependent on the verb / command that we choose. With the proposal of `volta use`, it would feel very unintuitive to run `volta use node@21` in a project, and then immediately get a message that it's set as the global but your local settings override. As a user, I would expect `volta use node@21` to mean the next call to `node --version` to display Node 21 is running. In order to make that work as users expect, we need to unify the two so that `volta use` _does_ actually change the Node for the current context. + +Another difficulty of the unified behavior is that it's more difficult to explain when users run into edge cases. Right now there's a clear separation between "local" and "global" with two different commands. Unifying them means we'll need to clearly document how `volta use` behaves in each situation, and how to override that (with the `--global` or `--pin` flags). + +## `volta default` or `volta global` + +In the vein of replacing the verb for `install`, I also considered `default` or `global` for the command. The major issue with those is that they're adjectives, rather than verbs, so it's not immediately clear what the command means. Does `volta default node` mean "choose a default node" or "list the current default node"? That confusion is ultimately why I decided against using either of these for the command. + +## `volta set` + +Another possibility for the command would be to make it more verbose, e.g. `volta set default node`. That solves the problems around `volta default` or `volta global` by adding a verb to make it very clear what you are doing. However, it makes the commands a fair bit more cumbersome to use, which I feel is ultimately a net negative compared to a single command. + +# Unresolved questions + +[unresolved]: #unresolved-questions + +- How do we handle the fact that you can install a 3rd-party package globally, but for a pinned project, we require users to install them normally using their package manager of choice? That is, what should we do when a user runs `volta use typescript` while they are in a package that is pinned? From 2f1fbd770d1547e282c95715c744ed86568ae8d1 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Thu, 22 Feb 2024 11:18:54 -0800 Subject: [PATCH 2/4] Minor wording change to pedagogy section --- text/0000-volta-use.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-volta-use.md b/text/0000-volta-use.md index f4de68a..f212a36 100644 --- a/text/0000-volta-use.md +++ b/text/0000-volta-use.md @@ -27,7 +27,7 @@ This will be a fairly large change to our recommended workflows. As `volta use` Notably, we will _not_ be removing the existing `volta install` and `volta pin` commands right away. They will continue to work as they already do. In the future, we might consider adding notifications to them to point users to the updated command, but for the initial implementation we don't want to disrupt current users' workflows. -All that said, the new command should simplify things a lot, especially for new users. It also will do a better job of living up to our website by truly having a _single_ command that users can use to get set up. +All that said, the new command should simplify things a lot, especially for new users. It will allow us to explain Volta by saying that you pick a version with `volta use`, and don't worry about installing it: Volta will handle making it available. It also should do a better job of living up to the claim on our website by truly having a _single_ command that users can run to get set up. # Details From d0f8cfe90844239861cc5615437ca3ffc76e3463 Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Thu, 3 Oct 2024 09:21:33 -0700 Subject: [PATCH 3/4] Update proposal to 'volta pin --default' --- text/0000-volta-use.md | 69 +++++++++++------------------------------- 1 file changed, 18 insertions(+), 51 deletions(-) diff --git a/text/0000-volta-use.md b/text/0000-volta-use.md index f212a36..4314a68 100644 --- a/text/0000-volta-use.md +++ b/text/0000-volta-use.md @@ -7,7 +7,7 @@ [summary]: #summary -Adding a new command, `volta use`, which combines the effects of `volta install` and `volta pin` into a single command that is more intuitive and better matches the mental model of Volta. +Updating `volta pin` by adding a `--default` flag to support pinning the _default_ version of a tool (instead of the local project version). Combining the behavior of `volta pin` and `volta install` into a single `pin` command that is more intuitive and better matches the mental model of Volta. # Motivation @@ -17,87 +17,54 @@ Early on in Volta's history, we picked the verb `install` to represent choosing This has led to some confusion for users. We get questions fairly regularly asking how users should select an "active" version of Node, once they have installed them using `volta install`. Additionally, by centering the install action, rather than the selection, `volta install` doesn't help users internalize Volta's mental model of "select a version and Volta will automatically download and make sure it's available." -Selecting a different verb for the action of choosing a tool version should reduce confusion and make it more clear how Volta is intended to work. +Using the existing `pin` verb for this action should make it more clear how Volta is intended to work. # Pedagogy [pedagogy]: #pedagogy -This will be a fairly large change to our recommended workflows. As `volta use` will work for both pinning _and_ selecting a default version, we will need to update the documentation throughout to take advantage of the new command. We will also likely want to write a blog post for the release which includes this change, explaining the reasoning and the new workflows. +This will be a fairly large change to our recommended workflows. As `volta pin` will work for selecting both local _and_ default versions, we will need to update the documentation throughout to take advantage of the new flag. We will also likely want to write a blog post for the release which includes this change, explaining the reasoning and the new workflows. -Notably, we will _not_ be removing the existing `volta install` and `volta pin` commands right away. They will continue to work as they already do. In the future, we might consider adding notifications to them to point users to the updated command, but for the initial implementation we don't want to disrupt current users' workflows. +Notably, we will _not_ be removing the existing `volta install` command right away. They will continue to work as they already do. In the future, we might consider adding notifications to them to point users to the updated command, but for the initial implementation we don't want to disrupt current users' workflows. -All that said, the new command should simplify things a lot, especially for new users. It will allow us to explain Volta by saying that you pick a version with `volta use`, and don't worry about installing it: Volta will handle making it available. It also should do a better job of living up to the claim on our website by truly having a _single_ command that users can run to get set up. +All that said, the new behavior should simplify things a lot, especially for new users. It will allow us to explain Volta by saying that you pick a version with `volta pin`, and don't worry about installing it: Volta will handle making it available. It also should do a better job of living up to the claim on our website by truly having a _single_ command that users can run to get set up. # Details [details]: #details -## Command definition +## New flag -``` -USAGE: - volta use [FLAGS] ... - -FLAGS: - -g, --global Select the global version of a tool, which is used everywhere outside of pinned projects - -p, --pin Pin a version of a tool to the local project, creating a Volta entry in package.json - -ARGS: - ... Tools to make available, like `node@lts` or `yarn@^1.14` -``` +A new flag, `-d` or `--default`, added to the `volta pin` command that will cause Volta to pin the _default_ version of a tool, rather than the _project_ version. ## Behavior -The behavior of `volta use` will ultimately be the same as the current `volta install` or `volta pin`. However, when run without flags, it will be contextual, based on where the command is being run. So if a user runs `volta use node@18` in a pinned project, the project will be updated to reflect the newly selected version. If they instead run `volta use node@18` _outside_ of a pinned project, then the default Node version will be updated. This ensures that running `volta use node@version` will always update the version that is currently active, meaning the next run of `node` will use that updated version. - -Notably, if a user runs `volta use node` within a project that doesn't currently have a pinned version (i.e. has no `"volta"` entry in `package.json`), then the command will update the global / default version of Node, it will _not_ create a pin if one doesn't exist. - -If a user wants to change a version that isn't currently active, they can use the flags to change the behavior. - -### `--global` - -Running `volta use --global` will work identically to the existing `volta install`, updating the default version regardless of whether the current directory is part of a pinned project. +### Without flag -### `--pin` +The behavior of `volta pin` without the flag will remain unchanged: we will resolve the version and attempt to pin it to the local project. If there is no project (i.e. we can't locate a `package.json` file), then we will continue to show an error rather than contextually switching to the `--default` behavior. The error message should be updated to include a suggestion of using the `--default` flag, however. -Similarly, `volta use --pin` will work identically to the current `volta pin`, always updating the current project. This includes creating a `volta` key in `package.json` if it isn't there already. +### With flag -## Implementation +When called with `--default`, `volta pin` should work identically to the current behavior of `volta install`: resolve the version and write the default version into the `VOLTA_HOME` directory. We should also keep the contextual notifications that we show the user, letting them know if a local project has a different version. -The technical implementation of `volta use` should be fairly straightforward. The new command will use the flags and context (i.e. if we are currently in a pinned project or did the user pass `--global`) to determine whether the behavior should be equivalent to `volta install` or `volta pin`. It will then delegate to the appropriate existing command behavior based on that determination. The ultimate flow should be: +### 3rd-party packages -- If `--global` was set -> use `volta install` behavior -- If `--pin` was set -> use `volta pin` behavior -- If _both_ were set, error (this can be handled by Clap I believe by making the two flags exclusive) -- If neither flag was set: - - If we are in a pinned project (one that already has a `"volta"` key in `package.json`) -> use `volta pin` behavior. - - Otherwise, use `volta install` behavior. +One notable difference between the current `volta install` behavior and the new `volta pin` is that `pin` will not support installing 3rd-party packages (e.g. `ember-cli`). The current behavior of `volta pin` does not support those, and keeping the consistency with that behavior should more clearly separate pinning tool versions and installing global shims. # Critique [critique]: #critique -## Confusion around omitting version +## Using `--global` rather than `--default` -One nice part about the existing `volta install` and `volta pin` commands is that they naturally work well with choosing a tool without selecting a version. For example, running `volta install node` makes intuitive sense as "pick whatever version and make it available." By contrast, `volta use node` doesn't immediately (to me, at least!) jump out as _picking_ a version of Node. `volta use node@lts` or similar, _do_ make sense, but omitting the version feels a little more awkward with `use` as the verb. +A different possibility for the flag itself would be to use `--global`, which aligns well with existing tools (e.g. `npm install --global`). This may be more intuitive for users who already know what `--global` typically means. However, we have intentionally used `default` rather than `global` in all of our messaging within Volta, to avoid the negative connotations associated with "global" installs in the existing ecosystem. -## Changing only the verb for `install` +## Changing both `pin` and `install` to a different combined verb -One alternative would be to only change the verb for `install`, leaving `pin` completely untouched. This would be the least disruptive change, however it's very dependent on the verb / command that we choose. With the proposal of `volta use`, it would feel very unintuitive to run `volta use node@21` in a project, and then immediately get a message that it's set as the global but your local settings override. As a user, I would expect `volta use node@21` to mean the next call to `node --version` to display Node 21 is running. In order to make that work as users expect, we need to unify the two so that `volta use` _does_ actually change the Node for the current context. +An earlier version of this RFC proposed combining `volta pin` and `volta install` into a single new command: `volta use`. That proposal had the behavior of the new command contextual based on whether the user was in a project or not. In the discussion, we felt that behavior was too surprising and resulted in a bad user experience around edge cases. -Another difficulty of the unified behavior is that it's more difficult to explain when users run into edge cases. Right now there's a clear separation between "local" and "global" with two different commands. Unifying them means we'll need to clearly document how `volta use` behaves in each situation, and how to override that (with the `--global` or `--pin` flags). - -## `volta default` or `volta global` - -In the vein of replacing the verb for `install`, I also considered `default` or `global` for the command. The major issue with those is that they're adjectives, rather than verbs, so it's not immediately clear what the command means. Does `volta default node` mean "choose a default node" or "list the current default node"? That confusion is ultimately why I decided against using either of these for the command. - -## `volta set` - -Another possibility for the command would be to make it more verbose, e.g. `volta set default node`. That solves the problems around `volta default` or `volta global` by adding a verb to make it very clear what you are doing. However, it makes the commands a fair bit more cumbersome to use, which I feel is ultimately a net negative compared to a single command. +Combining the commands into `volta pin` with an explicit flag means that the behavior is clear and expected, while still taking advantage of the fact that `pin` is a verb that fits better into Volta's model. # Unresolved questions [unresolved]: #unresolved-questions - -- How do we handle the fact that you can install a 3rd-party package globally, but for a pinned project, we require users to install them normally using their package manager of choice? That is, what should we do when a user runs `volta use typescript` while they are in a package that is pinned? From f69050b7487965f037c5101f187f4f1eb0fb276d Mon Sep 17 00:00:00 2001 From: Charles Pierce Date: Wed, 30 Oct 2024 12:48:43 -0700 Subject: [PATCH 4/4] Add line about short flag to the discussion of --global --- text/0000-volta-use.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0000-volta-use.md b/text/0000-volta-use.md index 4314a68..01501a0 100644 --- a/text/0000-volta-use.md +++ b/text/0000-volta-use.md @@ -59,6 +59,8 @@ One notable difference between the current `volta install` behavior and the new A different possibility for the flag itself would be to use `--global`, which aligns well with existing tools (e.g. `npm install --global`). This may be more intuitive for users who already know what `--global` typically means. However, we have intentionally used `default` rather than `global` in all of our messaging within Volta, to avoid the negative connotations associated with "global" installs in the existing ecosystem. +One point in favor of `--global`, however, is that it has a more intuitive short flag (`-g`) than `--default` (`-d`). At least for myself, if I wasn't already aware, I would expect `-d` to do a "delete" operation, rather than setting a default. + ## Changing both `pin` and `install` to a different combined verb An earlier version of this RFC proposed combining `volta pin` and `volta install` into a single new command: `volta use`. That proposal had the behavior of the new command contextual based on whether the user was in a project or not. In the discussion, we felt that behavior was too surprising and resulted in a bad user experience around edge cases.