Skip to content

Commit 3a09159

Browse files
committed
Build/Test Tools: Improve dev environment's CLI in speed, non-interactive usage, and argument handling.
* Start `cli` container when running `env:start`. This greatly speeds up calls to WP-CLI since the container is already running rather than having to start up for each call. * Facilitate calls to `env:cli` in non-interactive context (non-TTY) to allow piping content into commands or use in shell scripts. * Fix passing arguments to WP-CLI from `env:cli` so that arguments with spaces are passed as expected. * Fix JSHint issues. This aligns the wordpress-develop environment closer to wp-env. See WordPress/gutenberg#50007. Props westonruter, jorbin, SirLouen, sandeepdahiya. Fixes #63564. git-svn-id: https://develop.svn.wordpress.org/trunk@60308 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 8a0f8df commit 3a09159

File tree

7 files changed

+92
-28
lines changed

7 files changed

+92
-28
lines changed

.github/workflows/reusable-test-local-docker-environment-v1.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ jobs:
155155
run: npm run env:restart
156156

157157
- name: Test a CLI command
158-
run: npm run env:cli wp option get siteurl
158+
run: npm run env:cli option get siteurl
159159

160160
- name: Test logs command
161161
run: npm run env:logs

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ services:
111111
volumes:
112112
- ./:/var/www
113113

114+
# Keeps the service alive.
115+
command: 'sleep infinity'
116+
114117
# The init directive ensures the command runs with a PID > 1, so Ctrl+C works correctly.
115118
init: true
116119

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
"env:clean": "node ./tools/local-env/scripts/docker.js down -v --remove-orphans",
185185
"env:reset": "node ./tools/local-env/scripts/docker.js down --rmi all -v --remove-orphans",
186186
"env:install": "node ./tools/local-env/scripts/install.js",
187-
"env:cli": "node ./tools/local-env/scripts/docker.js run --rm cli",
187+
"env:cli": "node ./tools/local-env/scripts/docker.js exec cli wp --allow-root",
188188
"env:logs": "node ./tools/local-env/scripts/docker.js logs",
189189
"env:pull": "node ./tools/local-env/scripts/docker.js pull",
190190
"test:performance": "wp-scripts test-playwright --config tests/performance/playwright.config.js",

tools/local-env/scripts/docker.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
1-
const dotenv = require( 'dotenv' );
1+
/* jshint node:true */
2+
3+
const dotenv = require( 'dotenv' );
24
const dotenvExpand = require( 'dotenv-expand' );
3-
const { execSync } = require( 'child_process' );
5+
const { spawnSync } = require( 'child_process' );
46
const local_env_utils = require( './utils' );
57

68
dotenvExpand.expand( dotenv.config() );
79

810
const composeFiles = local_env_utils.get_compose_files();
911

10-
if (process.argv.includes('--coverage-html')) {
12+
if ( process.argv.includes( '--coverage-html' ) ) {
1113
process.env.LOCAL_PHP_XDEBUG = 'true';
1214
process.env.LOCAL_PHP_XDEBUG_MODE = 'coverage';
1315
}
1416

15-
// This try-catch prevents the superfluous Node.js debugging information from being shown if the command fails.
16-
try {
17-
// Execute any Docker compose command passed to this script.
18-
execSync( 'docker compose ' + composeFiles + ' ' + process.argv.slice( 2 ).join( ' ' ), { stdio: 'inherit' } );
19-
} catch ( error ) {
20-
process.exit( 1 );
17+
// Add --no-TTY (-T) arg after exec and run commands when STDIN is not a TTY.
18+
const dockerCommand = process.argv.slice( 2 );
19+
if ( [ 'exec', 'run' ].includes( dockerCommand[0] ) && ! process.stdin.isTTY ) {
20+
dockerCommand.splice( 1, 0, '--no-TTY' );
2121
}
22+
23+
// Execute any Docker compose command passed to this script.
24+
const returns = spawnSync(
25+
'docker',
26+
[
27+
'compose',
28+
...composeFiles
29+
.map( ( composeFile ) => [ '-f', composeFile ] )
30+
.flat(),
31+
...dockerCommand,
32+
],
33+
{ stdio: 'inherit' }
34+
);
35+
36+
process.exit( returns.status );

tools/local-env/scripts/install.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ dotenvExpand.expand( dotenv.config() );
1313
local_env_utils.determine_auth_option();
1414

1515
// Create wp-config.php.
16-
wp_cli( `config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --force --config-file=${process.env.LOCAL_DIR}/../wp-config.php` );
16+
wp_cli( `config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --force --config-file="wp-config.php"` );
17+
18+
// Since WP-CLI runs as root, the wp-config.php created above will be read-only. This needs to be writable for the sake of E2E tests.
19+
execSync( 'node ./tools/local-env/scripts/docker.js exec cli chmod 666 wp-config.php' );
1720

1821
// Add the debug settings to wp-config.php.
1922
// Windows requires this to be done as an additional step, rather than using the --extra-php option in the previous step.
@@ -61,7 +64,5 @@ wait_on( {
6164
* @param {string} cmd The WP-CLI command to run.
6265
*/
6366
function wp_cli( cmd ) {
64-
const composeFiles = local_env_utils.get_compose_files();
65-
66-
execSync( `docker compose ${composeFiles} run --quiet-pull --rm cli ${cmd} --path=/var/www/${process.env.LOCAL_DIR}`, { stdio: 'inherit' } );
67+
execSync( `npm --silent run env:cli -- ${cmd} --path=/var/www/${process.env.LOCAL_DIR}`, { stdio: 'inherit' } );
6768
}

tools/local-env/scripts/start.js

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
/* jshint node:true */
2+
13
const dotenv = require( 'dotenv' );
24
const dotenvExpand = require( 'dotenv-expand' );
3-
const { execSync } = require( 'child_process' );
5+
const { execSync, spawnSync } = require( 'child_process' );
46
const local_env_utils = require( './utils' );
57
const { constants, copyFile } = require( 'node:fs' );
68

79
// Copy the default .env file when one is not present.
8-
copyFile( '.env.example', '.env', constants.COPYFILE_EXCL, (e) => {
10+
copyFile( '.env.example', '.env', constants.COPYFILE_EXCL, () => {
911
console.log( '.env file already exists. .env.example was not copied.' );
1012
});
1113

@@ -28,18 +30,38 @@ try {
2830
}
2931

3032
// Start the local-env containers.
31-
const containers = ( process.env.LOCAL_PHP_MEMCACHED === 'true' )
32-
? 'wordpress-develop memcached'
33-
: 'wordpress-develop';
34-
execSync( `docker compose ${composeFiles} up --quiet-pull -d ${containers}`, { stdio: 'inherit' } );
33+
const containers = [ 'wordpress-develop', 'cli' ];
34+
if ( process.env.LOCAL_PHP_MEMCACHED === 'true' ) {
35+
containers.push( 'memcached' );
36+
}
37+
38+
spawnSync(
39+
'docker',
40+
[
41+
'compose',
42+
...composeFiles.map( ( composeFile ) => [ '-f', composeFile ] ).flat(),
43+
'up',
44+
'--quiet-pull',
45+
'-d',
46+
...containers,
47+
],
48+
{ stdio: 'inherit' }
49+
);
3550

3651
// If Docker Toolbox is being used, we need to manually forward LOCAL_PORT to the Docker VM.
3752
if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) {
3853
// VBoxManage is added to the PATH on every platform except Windows.
39-
const vboxmanage = process.env.VBOX_MSI_INSTALL_PATH ? `${ process.env.VBOX_MSI_INSTALL_PATH }/VBoxManage` : 'VBoxManage'
54+
const vboxmanage = process.env.VBOX_MSI_INSTALL_PATH ? `${ process.env.VBOX_MSI_INSTALL_PATH }/VBoxManage` : 'VBoxManage';
4055

4156
// Check if the port forwarding is already configured for this port.
42-
const vminfoBuffer = execSync( `"${ vboxmanage }" showvminfo "${ process.env.DOCKER_MACHINE_NAME }" --machinereadable` );
57+
const vminfoBuffer = spawnSync(
58+
vboxmanage,
59+
[
60+
'showvminfo',
61+
process.env.DOCKER_MACHINE_NAME,
62+
'--machinereadable'
63+
]
64+
).stdout;
4365
const vminfo = vminfoBuffer.toString().split( /[\r\n]+/ );
4466

4567
vminfo.forEach( ( info ) => {
@@ -53,10 +75,29 @@ if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) {
5375

5476
// Delete rules that are using the port we need.
5577
if ( rule[ 3 ] === process.env.LOCAL_PORT || rule[ 5 ] === process.env.LOCAL_PORT ) {
56-
execSync( `"${ vboxmanage }" controlvm "${ process.env.DOCKER_MACHINE_NAME }" natpf1 delete ${ rule[ 0 ] }`, { stdio: 'inherit' } );
78+
spawnSync(
79+
vboxmanage,
80+
[
81+
'controlvm',
82+
process.env.DOCKER_MACHINE_NAME,
83+
'natpf1',
84+
'delete',
85+
rule[ 0 ]
86+
],
87+
{ stdio: 'inherit' }
88+
);
5789
}
5890
} );
5991

6092
// Add our port forwarding rule.
61-
execSync( `"${ vboxmanage }" controlvm "${ process.env.DOCKER_MACHINE_NAME }" natpf1 "tcp-port${ process.env.LOCAL_PORT },tcp,127.0.0.1,${ process.env.LOCAL_PORT },,${ process.env.LOCAL_PORT }"`, { stdio: 'inherit' } );
93+
spawnSync(
94+
vboxmanage,
95+
[
96+
'controlvm',
97+
process.env.DOCKER_MACHINE_NAME,
98+
'natpf1',
99+
`tcp-port${ process.env.LOCAL_PORT },tcp,127.0.0.1,${ process.env.LOCAL_PORT },,${ process.env.LOCAL_PORT }`
100+
],
101+
{ stdio: 'inherit' }
102+
);
62103
}

tools/local-env/scripts/utils.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* jshint node:true */
2+
13
const { existsSync } = require( 'node:fs' );
24

35
const local_env_utils = {
@@ -10,12 +12,14 @@ const local_env_utils = {
1012
*
1113
* When PHP 7.2 or 7.3 is used in combination with MySQL 8.4, an override file will also be returned to ensure
1214
* that the mysql_native_password plugin authentication plugin is on and available for use.
15+
*
16+
* @return {string[]} Compose files.
1317
*/
1418
get_compose_files: function() {
15-
var composeFiles = '-f docker-compose.yml';
19+
const composeFiles = [ 'docker-compose.yml' ];
1620

1721
if ( existsSync( 'docker-compose.override.yml' ) ) {
18-
composeFiles = composeFiles + ' -f docker-compose.override.yml';
22+
composeFiles.push( 'docker-compose.override.yml' );
1923
}
2024

2125
if ( process.env.LOCAL_DB_TYPE !== 'mysql' ) {
@@ -28,7 +32,7 @@ const local_env_utils = {
2832

2933
// PHP 7.2/7.3 in combination with MySQL 8.4 requires additional configuration to function properly.
3034
if ( process.env.LOCAL_DB_VERSION === '8.4' ) {
31-
composeFiles = composeFiles + ' -f tools/local-env/old-php-mysql-84.override.yml';
35+
composeFiles.push( 'tools/local-env/old-php-mysql-84.override.yml' );
3236
}
3337

3438
return composeFiles;

0 commit comments

Comments
 (0)