-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Preferentially Execute Local wp-env
#50980
Conversation
Instead of always running the chosen version of `wp-env` we are going to try and find a local version in the current directory. This prevents the global `wp-env` from being used when a different local version is expected.
Size Change: -19.2 kB (-1%) Total Size: 1.39 MB
ℹ️ View Unchanged
|
packages/env/bin/wp-env
Outdated
// Rather than just executing the current CLI we will attempt to find a local version | ||
// and execute that one instead. This prevents users from accidentally using the | ||
// global CLI when a potentially different local version is expected. | ||
const localPath = path.resolve( './node_modules/@wordpress/env/lib/cli.js' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we use require.resolve( '@wordpress/env' )
instead? I think this will throw an error if the module can't be found, in which case we could revert to ../lib/cli.js
. In my testing from a nested directory in a project, this is the result:
> require.resolve('@wordpress/env')
'/Users/noahallen/source/wp-calypso/node_modules/@wordpress/env/lib/env.js'
(And then we can change env to cli.)
require.resolve should handle more cases because it's using the Node module resolution algorithm, whereas the current approach probably won't fork in child directories
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will throw an error if the module can't be found, in which case we could revert to ../lib/cli.js
Using path.resolve()
in this case will just resolve an absolute path relative to process.cwd()
. Since all we're doing is creating a path string, the fs.existsSync( localPath )
check below will protect us from trying to do something with a module that doesn't exist.
An interesting point though is that perhaps it might make sense be more explicit about what we're doing and use path.join( process.cwd(), 'node_modules/@wordpress/env/lib/cli.js
? I'm going to make that change.
require.resolve should handle more cases because it's using the Node module resolution algorithm, whereas the current approach probably won't fork in child directories
I would worry that require.resolve
is too heavy-handed. Node's module resolution algorithm includes searching the current directory and every parent directory for a module in a node_modules
directory. Imagine that a package has a .wp-env.json
built with a global version of X in mind, but, it's in a directory with a project at a higher-level that (for whatever reason) has a different wp-env
version.
Since wp-env
commands only care about the current working directory, I think it makes sense for this override to only apply in the current one as well. For instance, even though npx wp-env start
will find the root instance if ran in a subdirectory, the command won't actually work because there's no package there.
Ultimately the question here is whether or not the user should expect it to find the current directory's package, or, if it should find the nearest one (traversing to the global install if it can't find one). Given that this is the typical behavior of NPM commands though, you might be right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, you make a good point about wp-env being directory based. However, this makes me think of another scenario: monorepos! For example, I have a plugin in a monorepo -- the .wp-env.json
file is under a path like ./apps/this-plugin
. But node modules for that plugin would be stored in ./node_modules
(since yarn will put all monorepo deps in the same place.) While I need to run .wp-env
from the apps/plugin directory, this new feature wouldn't work unless we used require.resolve.
Imagine that a package has a .wp-env.json built with a global version of X in mind, but, it's in a directory with a project at a higher-level that (for whatever reason) has a different wp-env version.
Also a good point, but it's important to have explicit dependencies if you really need to depend on a specific version!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I agree with your last line, that the expected behavior is probably to resolve the current project's wp-env copy from node_modules, even if it's in a different directory. (And while it would be unexpected to resolve from outside the project in a parent directory, that doesn't seem like a common use case)
Co-authored-by: Noah Allen <noahtallen@gmail.com>
This changes the path resolution to use Node's module resolution algorithm to be consistent with other usages of Node CLI tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tests great for me!
Flaky tests detected in c359fd4. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5094375396
|
What?
This pull request causes
wp-env
commands to be executed by the local package's version if one is available.Why?
When someone has a global
wp-env
that is a different version than the one installed in the package, runningwp-env
commands can be problematic. There may be compatibility problems for instance.How?
Rather than relying on something like
execSync
, this PR loads thelib/cli.js
file from the local package if it is available. This makes the entire execution seamless.Testing Instructions
version
inpackages/env/package.json
to20.0.0
.npm pack
inpackages/env
.npm -g I ./wordpress-env-20.0.0.tgz
and install this package globally.version
back to what it was before.wp-env --version
inpackages/env/lib
and confirm it is20.0.0.0
.wp-env --version
inpackages/env
and confirm it is the local version, probably8.0.0
.