diff --git a/packages/env/CHANGELOG.md b/packages/env/CHANGELOG.md index 50943d92016352..bb68681c18f0fd 100644 --- a/packages/env/CHANGELOG.md +++ b/packages/env/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Breaking Changes + +- `run` command now has a `--env-cwd` option to set the working directory in the container for the command to execute from. + ## 5.16.0 (2023-04-12) ## 5.15.0 (2023-03-29) diff --git a/packages/env/README.md b/packages/env/README.md index 5c2ac83708a132..7a22dfe88428cf 100644 --- a/packages/env/README.md +++ b/packages/env/README.md @@ -316,7 +316,7 @@ The run command can be used to open shell sessions or invoke WP-CLI commands.
In some cases, `wp-env` may consume options that you are attempting to pass to the container. This happens with options that `wp-env` has already declared, -such as `--debug`, `--help`, and `--version`. When this happens, you should fall +such as `--env-cwd`, `--debug`, `--help`, and `--version`. When this happens, you should fall back to using quotation marks; `wp-env` considers everything inside the quotation marks to be command argument. @@ -349,6 +349,9 @@ Options: --help Show help [boolean] --version Show version number [boolean] --debug Enable debug output. [boolean] [default: false] + --env-cwd The command's working directory inside of the container. Paths + without a leading slash are relative to the WordPress root. + [string] [default: "."] ``` For example: diff --git a/packages/env/lib/cli.js b/packages/env/lib/cli.js index abca20c9b3619a..68316855c6bede 100644 --- a/packages/env/lib/cli.js +++ b/packages/env/lib/cli.js @@ -174,6 +174,13 @@ module.exports = function cli() { 'run [command..]', 'Runs an arbitrary command in one of the underlying Docker containers. The "container" param should reference one of the underlying Docker services like "development", "tests", or "cli". To run a wp-cli command, use the "cli" or "tests-cli" service. You can also use this command to open shell sessions like bash and the WordPress shell in the WordPress instance. For example, `wp-env run cli bash` will open bash in the development WordPress instance. When using long commands with arguments and quotation marks, you need to wrap the "command" param in quotation marks. For example: `wp-env run tests-cli "wp post create --post_type=page --post_title=\'Test\'"` will create a post on the tests WordPress instance.', ( args ) => { + args.option( 'env-cwd', { + type: 'string', + requiresArg: true, + default: '.', + describe: + "The command's working directory inside of the container. Paths without a leading slash are relative to the WordPress root.", + } ); args.positional( 'container', { type: 'string', describe: 'The container to run the command on.', diff --git a/packages/env/lib/commands/run.js b/packages/env/lib/commands/run.js index f944d8de84fa53..fd0f800041cb91 100644 --- a/packages/env/lib/commands/run.js +++ b/packages/env/lib/commands/run.js @@ -2,6 +2,7 @@ * External dependencies */ const { spawn } = require( 'child_process' ); +const path = require( 'path' ); /** * Internal dependencies @@ -18,10 +19,17 @@ const initConfig = require( '../init-config' ); * @param {Object} options * @param {string} options.container The Docker container to run the command on. * @param {string[]} options.command The command to run. + * @param {string} options.envCwd The working directory for the command to be executed from. * @param {Object} options.spinner A CLI spinner which indicates progress. * @param {boolean} options.debug True if debug mode is enabled. */ -module.exports = async function run( { container, command, spinner, debug } ) { +module.exports = async function run( { + container, + command, + envCwd, + spinner, + debug, +} ) { const config = await initConfig( { spinner, debug } ); command = command.join( ' ' ); @@ -29,12 +37,7 @@ module.exports = async function run( { container, command, spinner, debug } ) { // Shows a contextual tip for the given command. showCommandTips( command, container, spinner ); - await spawnCommandDirectly( { - container, - command, - spinner, - config, - } ); + await spawnCommandDirectly( config, container, command, envCwd, spinner ); spinner.text = `Ran \`${ command }\` in '${ container }'.`; }; @@ -42,17 +45,22 @@ module.exports = async function run( { container, command, spinner, debug } ) { /** * Runs an arbitrary command on the given Docker container. * - * @param {Object} options - * @param {string} options.container The Docker container to run the command on. - * @param {string} options.command The command to run. - * @param {WPConfig} options.config The wp-env configuration. - * @param {Object} options.spinner A CLI spinner which indicates progress. + * @param {WPConfig} config The wp-env configuration. + * @param {string} container The Docker container to run the command on. + * @param {string} command The command to run. + * @param {string} envCwd The working directory for the command to be executed from. + * @param {Object} spinner A CLI spinner which indicates progress. */ -function spawnCommandDirectly( { container, command, config, spinner } ) { +function spawnCommandDirectly( config, container, command, envCwd, spinner ) { + // We need to pass absolute paths to the container. + envCwd = path.resolve( '/var/www/html', envCwd ); + const composeCommand = [ '-f', config.dockerComposeConfigPath, 'run', + '-w', + envCwd, '--rm', container, ...command.split( ' ' ), // The command will fail if passed as a complete string.