@wordpress/env 10.38.1-next.v.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +158 -75
- package/lib/cli.js +85 -24
- package/lib/commands/clean.js +16 -38
- package/lib/commands/cleanup.js +79 -0
- package/lib/commands/destroy.js +33 -41
- package/lib/commands/index.js +6 -2
- package/lib/commands/logs.js +20 -62
- package/lib/commands/reset.js +46 -0
- package/lib/commands/run.js +16 -117
- package/lib/commands/start.js +78 -243
- package/lib/commands/status.js +160 -0
- package/lib/commands/stop.js +17 -19
- package/lib/config/get-config-from-environment-vars.js +2 -5
- package/lib/config/load-config.js +35 -5
- package/lib/config/parse-config.js +53 -21
- package/lib/config/post-process-config.js +38 -16
- package/lib/config/test/__snapshots__/config-integration.js.snap +16 -0
- package/lib/config/test/parse-config.js +33 -0
- package/lib/config/test/post-process-config.js +52 -0
- package/lib/download-sources.js +9 -53
- package/lib/{build-docker-compose-config.js → runtime/docker/build-docker-compose-config.js} +167 -128
- package/lib/runtime/docker/download-sources.js +63 -0
- package/lib/{download-wp-phpunit.js → runtime/docker/download-wp-phpunit.js} +4 -1
- package/lib/runtime/docker/index.js +863 -0
- package/lib/{init-config.js → runtime/docker/init-config.js} +22 -14
- package/lib/runtime/docker/wordpress.js +309 -0
- package/lib/runtime/errors.js +28 -0
- package/lib/runtime/index.js +91 -0
- package/lib/runtime/playground/blueprint-builder.js +158 -0
- package/lib/runtime/playground/index.js +530 -0
- package/lib/test/build-docker-compose-config.js +150 -3
- package/lib/test/cli.js +49 -13
- package/lib/wordpress.js +1 -297
- package/package.json +6 -3
- package/lib/commands/install-path.js +0 -21
- /package/lib/{get-host-user.js → runtime/docker/get-host-user.js} +0 -0
- /package/lib/{validate-run-container.js → runtime/docker/validate-run-container.js} +0 -0
package/lib/commands/clean.js
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* External dependencies
|
|
4
4
|
*/
|
|
5
|
-
const
|
|
5
|
+
const path = require( 'path' );
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Internal dependencies
|
|
9
9
|
*/
|
|
10
|
-
const initConfig = require( '../init-config' );
|
|
11
|
-
const { configureWordPress, resetDatabase } = require( '../wordpress' );
|
|
12
10
|
const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
|
|
11
|
+
const { loadConfig } = require( '../config' );
|
|
12
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @typedef {import('../wordpress').WPEnvironment} WPEnvironment
|
|
@@ -17,57 +17,35 @@ const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* @deprecated Use `reset` instead.
|
|
21
|
+
*
|
|
22
|
+
* Resets the development server's database, the tests server's database, or both.
|
|
21
23
|
*
|
|
22
24
|
* @param {Object} options
|
|
23
|
-
* @param {WPEnvironmentSelection} options.environment The environment to
|
|
25
|
+
* @param {WPEnvironmentSelection} options.environment The environment to reset. Either 'development', 'tests', or 'all'.
|
|
24
26
|
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
25
27
|
* @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
|
|
26
28
|
* @param {boolean} options.debug True if debug mode is enabled.
|
|
29
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
27
30
|
*/
|
|
28
31
|
module.exports = async function clean( {
|
|
29
32
|
environment,
|
|
30
33
|
spinner,
|
|
31
34
|
scripts,
|
|
32
35
|
debug,
|
|
36
|
+
config: customConfigPath,
|
|
33
37
|
} ) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const description = `${ environment } environment${
|
|
37
|
-
environment === 'all' ? 's' : ''
|
|
38
|
-
}`;
|
|
39
|
-
spinner.text = `Cleaning ${ description }.`;
|
|
40
|
-
|
|
41
|
-
const tasks = [];
|
|
42
|
-
|
|
43
|
-
// Start the database first to avoid race conditions where all tasks create
|
|
44
|
-
// different docker networks with the same name.
|
|
45
|
-
await dockerCompose.upOne( 'mysql', {
|
|
46
|
-
config: config.dockerComposeConfigPath,
|
|
47
|
-
log: config.debug,
|
|
48
|
-
} );
|
|
38
|
+
spinner.warn( 'The `clean` command is deprecated. Use `reset` instead.' );
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
.catch( () => {} )
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if ( environment === 'all' || environment === 'tests' ) {
|
|
59
|
-
tasks.push(
|
|
60
|
-
resetDatabase( 'tests', config )
|
|
61
|
-
.then( () => configureWordPress( 'tests', config ) )
|
|
62
|
-
.catch( () => {} )
|
|
63
|
-
);
|
|
64
|
-
}
|
|
40
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
41
|
+
const runtime = getRuntime(
|
|
42
|
+
await detectRuntime( config.workDirectoryPath )
|
|
43
|
+
);
|
|
65
44
|
|
|
66
|
-
await
|
|
45
|
+
await runtime.clean( config, { environment, spinner, debug } );
|
|
67
46
|
|
|
47
|
+
// Execute afterClean for backwards compatibility.
|
|
68
48
|
if ( scripts ) {
|
|
69
49
|
await executeLifecycleScript( 'afterClean', config, spinner );
|
|
70
50
|
}
|
|
71
|
-
|
|
72
|
-
spinner.text = `Cleaned ${ description }.`;
|
|
73
51
|
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const fs = require( 'fs' ).promises;
|
|
6
|
+
const path = require( 'path' );
|
|
7
|
+
const { confirm } = require( '@inquirer/prompts' );
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
const { loadConfig } = require( '../config' );
|
|
13
|
+
const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
|
|
14
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cleanup the development server.
|
|
18
|
+
*
|
|
19
|
+
* Removes Docker containers, volumes, networks, and local files,
|
|
20
|
+
* but preserves Docker images for faster re-starts.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} options
|
|
23
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
24
|
+
* @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
|
|
25
|
+
* @param {boolean} options.force If true, skips the confirmation prompt.
|
|
26
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
27
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
28
|
+
*/
|
|
29
|
+
module.exports = async function cleanup( {
|
|
30
|
+
spinner,
|
|
31
|
+
scripts,
|
|
32
|
+
force,
|
|
33
|
+
debug,
|
|
34
|
+
config: customConfigPath,
|
|
35
|
+
} ) {
|
|
36
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
await fs.readdir( config.workDirectoryPath );
|
|
40
|
+
} catch {
|
|
41
|
+
spinner.text = 'Could not find any files to remove.';
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const runtime = getRuntime(
|
|
46
|
+
await detectRuntime( config.workDirectoryPath )
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
spinner.info( runtime.getCleanupWarningMessage() );
|
|
50
|
+
|
|
51
|
+
let yesDelete = force;
|
|
52
|
+
if ( ! force ) {
|
|
53
|
+
try {
|
|
54
|
+
yesDelete = await confirm( {
|
|
55
|
+
message: 'Are you sure you want to continue?',
|
|
56
|
+
default: false,
|
|
57
|
+
} );
|
|
58
|
+
} catch ( error ) {
|
|
59
|
+
if ( error.name === 'ExitPromptError' ) {
|
|
60
|
+
console.log( 'Cancelled.' );
|
|
61
|
+
process.exit( 1 );
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
spinner.start();
|
|
68
|
+
|
|
69
|
+
if ( ! yesDelete ) {
|
|
70
|
+
spinner.text = 'Cancelled.';
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await runtime.cleanup( config, { spinner, debug } );
|
|
75
|
+
|
|
76
|
+
if ( scripts ) {
|
|
77
|
+
await executeLifecycleScript( 'afterCleanup', config, spinner );
|
|
78
|
+
}
|
|
79
|
+
};
|
package/lib/commands/destroy.js
CHANGED
|
@@ -2,32 +2,35 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* External dependencies
|
|
4
4
|
*/
|
|
5
|
-
const { v2: dockerCompose } = require( 'docker-compose' );
|
|
6
5
|
const fs = require( 'fs' ).promises;
|
|
7
6
|
const path = require( 'path' );
|
|
8
7
|
const { confirm } = require( '@inquirer/prompts' );
|
|
9
8
|
|
|
10
|
-
/**
|
|
11
|
-
* Promisified dependencies
|
|
12
|
-
*/
|
|
13
|
-
const { rimraf } = require( 'rimraf' );
|
|
14
|
-
|
|
15
9
|
/**
|
|
16
10
|
* Internal dependencies
|
|
17
11
|
*/
|
|
18
12
|
const { loadConfig } = require( '../config' );
|
|
19
13
|
const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
|
|
14
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
20
15
|
|
|
21
16
|
/**
|
|
22
17
|
* Destroy the development server.
|
|
23
18
|
*
|
|
24
|
-
* @param {Object}
|
|
25
|
-
* @param {Object}
|
|
26
|
-
* @param {boolean}
|
|
27
|
-
* @param {boolean}
|
|
19
|
+
* @param {Object} options
|
|
20
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
21
|
+
* @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
|
|
22
|
+
* @param {boolean} options.force If true, skips the confirmation prompt.
|
|
23
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
24
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
28
25
|
*/
|
|
29
|
-
module.exports = async function destroy( {
|
|
30
|
-
|
|
26
|
+
module.exports = async function destroy( {
|
|
27
|
+
spinner,
|
|
28
|
+
scripts,
|
|
29
|
+
force,
|
|
30
|
+
debug,
|
|
31
|
+
config: customConfigPath,
|
|
32
|
+
} ) {
|
|
33
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
31
34
|
|
|
32
35
|
try {
|
|
33
36
|
await fs.readdir( config.workDirectoryPath );
|
|
@@ -36,22 +39,26 @@ module.exports = async function destroy( { spinner, scripts, debug } ) {
|
|
|
36
39
|
return;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
const runtime = getRuntime(
|
|
43
|
+
await detectRuntime( config.workDirectoryPath )
|
|
41
44
|
);
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
spinner.info( runtime.getDestroyWarningMessage() );
|
|
47
|
+
|
|
48
|
+
let yesDelete = force;
|
|
49
|
+
if ( ! force ) {
|
|
50
|
+
try {
|
|
51
|
+
yesDelete = await confirm( {
|
|
52
|
+
message: 'Are you sure you want to continue?',
|
|
53
|
+
default: false,
|
|
54
|
+
} );
|
|
55
|
+
} catch ( error ) {
|
|
56
|
+
if ( error.name === 'ExitPromptError' ) {
|
|
57
|
+
console.log( 'Cancelled.' );
|
|
58
|
+
process.exit( 1 );
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
53
61
|
}
|
|
54
|
-
throw error;
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
spinner.start();
|
|
@@ -61,24 +68,9 @@ module.exports = async function destroy( { spinner, scripts, debug } ) {
|
|
|
61
68
|
return;
|
|
62
69
|
}
|
|
63
70
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
await dockerCompose.down( {
|
|
67
|
-
config: config.dockerComposeConfigPath,
|
|
68
|
-
commandOptions: [ '--volumes', '--remove-orphans', '--rmi', 'all' ],
|
|
69
|
-
log: debug,
|
|
70
|
-
} );
|
|
71
|
-
|
|
72
|
-
spinner.text = 'Removing local files.';
|
|
73
|
-
// Note: there is a race condition where docker compose actually hasn't finished
|
|
74
|
-
// by this point, which causes rimraf to fail. We need to wait at least 2.5-5s,
|
|
75
|
-
// but using 10s in case it's dependant on the machine.
|
|
76
|
-
await new Promise( ( resolve ) => setTimeout( resolve, 10000 ) );
|
|
77
|
-
await rimraf( config.workDirectoryPath );
|
|
71
|
+
await runtime.destroy( config, { spinner, debug } );
|
|
78
72
|
|
|
79
73
|
if ( scripts ) {
|
|
80
74
|
await executeLifecycleScript( 'afterDestroy', config, spinner );
|
|
81
75
|
}
|
|
82
|
-
|
|
83
|
-
spinner.text = 'Removed WordPress environment.';
|
|
84
76
|
};
|
package/lib/commands/index.js
CHANGED
|
@@ -4,18 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const start = require( './start' );
|
|
6
6
|
const stop = require( './stop' );
|
|
7
|
+
const reset = require( './reset' );
|
|
7
8
|
const clean = require( './clean' );
|
|
8
9
|
const run = require( './run' );
|
|
9
10
|
const destroy = require( './destroy' );
|
|
11
|
+
const cleanup = require( './cleanup' );
|
|
10
12
|
const logs = require( './logs' );
|
|
11
|
-
const
|
|
13
|
+
const status = require( './status' );
|
|
12
14
|
|
|
13
15
|
module.exports = {
|
|
14
16
|
start,
|
|
15
17
|
stop,
|
|
18
|
+
reset,
|
|
16
19
|
clean,
|
|
17
20
|
run,
|
|
18
21
|
destroy,
|
|
22
|
+
cleanup,
|
|
19
23
|
logs,
|
|
20
|
-
|
|
24
|
+
status,
|
|
21
25
|
};
|
package/lib/commands/logs.js
CHANGED
|
@@ -2,76 +2,34 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* External dependencies
|
|
4
4
|
*/
|
|
5
|
-
const
|
|
5
|
+
const path = require( 'path' );
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Internal dependencies
|
|
9
9
|
*/
|
|
10
|
-
const
|
|
10
|
+
const { loadConfig } = require( '../config' );
|
|
11
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Displays the Docker & PHP logs on the given environment.
|
|
14
15
|
*
|
|
15
|
-
* @param {Object}
|
|
16
|
-
* @param {Object}
|
|
17
|
-
* @param {Object}
|
|
18
|
-
* @param {Object}
|
|
19
|
-
* @param {boolean}
|
|
16
|
+
* @param {Object} options
|
|
17
|
+
* @param {Object} options.environment The environment to run the command in (develop or tests).
|
|
18
|
+
* @param {Object} options.watch If true, follow along with log output.
|
|
19
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
20
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
21
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
20
22
|
*/
|
|
21
|
-
module.exports = async function logs( {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const servicesToWatch =
|
|
32
|
-
environment === 'all'
|
|
33
|
-
? [ 'tests-wordpress', 'wordpress' ]
|
|
34
|
-
: [ environment === 'tests' ? 'tests-wordpress' : 'wordpress' ];
|
|
35
|
-
|
|
36
|
-
const output = await Promise.all( [
|
|
37
|
-
...servicesToWatch.map( ( service ) =>
|
|
38
|
-
dockerCompose.logs( service, {
|
|
39
|
-
config: config.dockerComposeConfigPath,
|
|
40
|
-
log: watch, // Must log inline if we are watching the log output.
|
|
41
|
-
commandOptions: watch ? [ '--follow' ] : [],
|
|
42
|
-
} )
|
|
43
|
-
),
|
|
44
|
-
] );
|
|
45
|
-
|
|
46
|
-
// Combine the results from each docker output.
|
|
47
|
-
const result = output.reduce(
|
|
48
|
-
( acc, current ) => {
|
|
49
|
-
if ( current.out ) {
|
|
50
|
-
acc.out = acc.out.concat( current.out );
|
|
51
|
-
}
|
|
52
|
-
if ( current.err ) {
|
|
53
|
-
acc.err = acc.err.concat( current.err );
|
|
54
|
-
}
|
|
55
|
-
if ( current.exitCode !== 0 ) {
|
|
56
|
-
acc.hasNon0ExitCode = true;
|
|
57
|
-
}
|
|
58
|
-
return acc;
|
|
59
|
-
},
|
|
60
|
-
{ out: '', err: '', hasNon0ExitCode: false }
|
|
23
|
+
module.exports = async function logs( {
|
|
24
|
+
environment,
|
|
25
|
+
watch,
|
|
26
|
+
spinner,
|
|
27
|
+
debug,
|
|
28
|
+
config: customConfigPath,
|
|
29
|
+
} ) {
|
|
30
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
31
|
+
const runtime = getRuntime(
|
|
32
|
+
await detectRuntime( config.workDirectoryPath )
|
|
61
33
|
);
|
|
62
|
-
|
|
63
|
-
if ( result.out.length ) {
|
|
64
|
-
console.log(
|
|
65
|
-
process.stdout.isTTY ? `\n\n${ result.out }\n\n` : result.out
|
|
66
|
-
);
|
|
67
|
-
} else if ( result.err.length ) {
|
|
68
|
-
console.error(
|
|
69
|
-
process.stdout.isTTY ? `\n\n${ result.err }\n\n` : result.err
|
|
70
|
-
);
|
|
71
|
-
if ( result.hasNon0ExitCode ) {
|
|
72
|
-
throw result.err;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
spinner.text = 'Finished showing logs.';
|
|
34
|
+
await runtime.logs( config, { environment, watch, spinner, debug } );
|
|
77
35
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const path = require( 'path' );
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
|
|
11
|
+
const { loadConfig } = require( '../config' );
|
|
12
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {import('../wordpress').WPEnvironment} WPEnvironment
|
|
16
|
+
* @typedef {import('../wordpress').WPEnvironmentSelection} WPEnvironmentSelection
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resets the development server's database, the tests server's database, or both.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} options
|
|
23
|
+
* @param {WPEnvironmentSelection} options.environment The environment to reset. Either 'development', 'tests', or 'all'.
|
|
24
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
25
|
+
* @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
|
|
26
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
27
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
28
|
+
*/
|
|
29
|
+
module.exports = async function reset( {
|
|
30
|
+
environment,
|
|
31
|
+
spinner,
|
|
32
|
+
scripts,
|
|
33
|
+
debug,
|
|
34
|
+
config: customConfigPath,
|
|
35
|
+
} ) {
|
|
36
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
37
|
+
const runtime = getRuntime(
|
|
38
|
+
await detectRuntime( config.workDirectoryPath )
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
await runtime.clean( config, { environment, spinner, debug } );
|
|
42
|
+
|
|
43
|
+
if ( scripts ) {
|
|
44
|
+
await executeLifecycleScript( 'afterReset', config, spinner );
|
|
45
|
+
}
|
|
46
|
+
};
|
package/lib/commands/run.js
CHANGED
|
@@ -2,29 +2,25 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* External dependencies
|
|
4
4
|
*/
|
|
5
|
-
const { spawn } = require( 'child_process' );
|
|
6
5
|
const path = require( 'path' );
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Internal dependencies
|
|
10
9
|
*/
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {import('../config').WPConfig} WPConfig
|
|
16
|
-
*/
|
|
10
|
+
const { loadConfig } = require( '../config' );
|
|
11
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
17
12
|
|
|
18
13
|
/**
|
|
19
14
|
* Runs an arbitrary command on the given Docker container.
|
|
20
15
|
*
|
|
21
|
-
* @param {Object}
|
|
22
|
-
* @param {string}
|
|
23
|
-
* @param {string[]}
|
|
24
|
-
* @param {string[]}
|
|
25
|
-
* @param {string}
|
|
26
|
-
* @param {Object}
|
|
27
|
-
* @param {boolean}
|
|
16
|
+
* @param {Object} options
|
|
17
|
+
* @param {string} options.container The Docker container to run the command on.
|
|
18
|
+
* @param {string[]} options.command The command to run.
|
|
19
|
+
* @param {string[]} options.'--' Any arguments that were passed after a double dash.
|
|
20
|
+
* @param {string} options.envCwd The working directory for the command to be executed from.
|
|
21
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
22
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
23
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
28
24
|
*/
|
|
29
25
|
module.exports = async function run( {
|
|
30
26
|
container,
|
|
@@ -33,8 +29,12 @@ module.exports = async function run( {
|
|
|
33
29
|
envCwd,
|
|
34
30
|
spinner,
|
|
35
31
|
debug,
|
|
32
|
+
config: customConfigPath,
|
|
36
33
|
} ) {
|
|
37
|
-
const config = await
|
|
34
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
35
|
+
const runtime = getRuntime(
|
|
36
|
+
await detectRuntime( config.workDirectoryPath )
|
|
37
|
+
);
|
|
38
38
|
|
|
39
39
|
// Include any double dashed arguments in the command so that we can pass them to Docker.
|
|
40
40
|
// This lets users pass options that the command defines without them being parsed.
|
|
@@ -42,106 +42,5 @@ module.exports = async function run( {
|
|
|
42
42
|
command.push( ...doubleDashedArgs );
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
const joinedCommand = command.join( ' ' );
|
|
47
|
-
showCommandTips( joinedCommand, container, spinner );
|
|
48
|
-
|
|
49
|
-
await spawnCommandDirectly( config, container, command, envCwd, spinner );
|
|
50
|
-
|
|
51
|
-
spinner.text = `Ran \`${ joinedCommand }\` in '${ container }'.`;
|
|
45
|
+
await runtime.run( config, { container, command, envCwd, spinner, debug } );
|
|
52
46
|
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Runs an arbitrary command on the given Docker container.
|
|
56
|
-
*
|
|
57
|
-
* @param {WPConfig} config The wp-env configuration.
|
|
58
|
-
* @param {string} container The Docker container to run the command on.
|
|
59
|
-
* @param {string[]} command The command to run.
|
|
60
|
-
* @param {string} envCwd The working directory for the command to be executed from.
|
|
61
|
-
* @param {Object} spinner A CLI spinner which indicates progress.
|
|
62
|
-
*/
|
|
63
|
-
function spawnCommandDirectly( config, container, command, envCwd, spinner ) {
|
|
64
|
-
// Both the `wordpress` and `tests-wordpress` containers have the host's
|
|
65
|
-
// user so that they can maintain ownership parity with the host OS.
|
|
66
|
-
// We should run any commands as that user so that they are able
|
|
67
|
-
// to interact with the files mounted from the host.
|
|
68
|
-
const hostUser = getHostUser();
|
|
69
|
-
|
|
70
|
-
// Since Docker requires absolute paths, we should resolve the input to a POSIX path.
|
|
71
|
-
// This is needed because Windows resolves relative paths from the C: drive.
|
|
72
|
-
envCwd = path.posix.resolve(
|
|
73
|
-
// Not all containers have the same starting working directory.
|
|
74
|
-
container === 'mysql' || container === 'tests-mysql'
|
|
75
|
-
? '/'
|
|
76
|
-
: '/var/www/html',
|
|
77
|
-
// Remove spaces and single quotes from both ends of the path.
|
|
78
|
-
// This is needed because Windows treats single quotes as a literal character.
|
|
79
|
-
envCwd.trim().replace( /^'|'$/g, '' )
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const composeCommand = [
|
|
83
|
-
'compose',
|
|
84
|
-
'-f',
|
|
85
|
-
config.dockerComposeConfigPath,
|
|
86
|
-
'exec',
|
|
87
|
-
'-w',
|
|
88
|
-
envCwd,
|
|
89
|
-
'--user',
|
|
90
|
-
hostUser.fullUser,
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
if ( ! process.stdout.isTTY ) {
|
|
94
|
-
composeCommand.push( '-T' );
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
composeCommand.push( container, ...command );
|
|
98
|
-
|
|
99
|
-
return new Promise( ( resolve, reject ) => {
|
|
100
|
-
// Note: since the npm docker-compose package uses the -T option, we
|
|
101
|
-
// cannot use it to spawn an interactive command. Thus, we run docker-
|
|
102
|
-
// compose on the CLI directly.
|
|
103
|
-
const childProc = spawn(
|
|
104
|
-
'docker',
|
|
105
|
-
composeCommand,
|
|
106
|
-
{ stdio: 'inherit' },
|
|
107
|
-
spinner
|
|
108
|
-
);
|
|
109
|
-
childProc.on( 'error', reject );
|
|
110
|
-
childProc.on( 'exit', ( code ) => {
|
|
111
|
-
// Code 130 is set if the user tries to exit with ctrl-c before using
|
|
112
|
-
// ctrl-d (so it is not an error which should fail the script.)
|
|
113
|
-
if ( code === 0 || code === 130 ) {
|
|
114
|
-
resolve();
|
|
115
|
-
} else {
|
|
116
|
-
reject( `Command failed with exit code ${ code }` );
|
|
117
|
-
}
|
|
118
|
-
} );
|
|
119
|
-
} );
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* This shows a contextual tip for the command being run. Certain commands (like
|
|
124
|
-
* bash) may have weird behavior (exit with ctrl-d instead of ctrl-c or ctrl-z),
|
|
125
|
-
* so we want the user to have that information without having to ask someone.
|
|
126
|
-
*
|
|
127
|
-
* @param {string} joinedCommand The command for which to show a tip joined by spaces.
|
|
128
|
-
* @param {string} container The container the command will be run on.
|
|
129
|
-
* @param {Object} spinner A spinner object to show progress.
|
|
130
|
-
*/
|
|
131
|
-
function showCommandTips( joinedCommand, container, spinner ) {
|
|
132
|
-
if ( ! joinedCommand.length ) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const tip = `Starting '${ joinedCommand }' on the ${ container } container. ${ ( () => {
|
|
137
|
-
switch ( joinedCommand ) {
|
|
138
|
-
case 'bash':
|
|
139
|
-
return 'Exit bash with ctrl-d.';
|
|
140
|
-
case 'wp shell':
|
|
141
|
-
return 'Exit the WordPress shell with ctrl-c.';
|
|
142
|
-
default:
|
|
143
|
-
return '';
|
|
144
|
-
}
|
|
145
|
-
} )() }\n`;
|
|
146
|
-
spinner.info( tip );
|
|
147
|
-
}
|