@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/start.js
CHANGED
|
@@ -2,53 +2,34 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* External dependencies
|
|
4
4
|
*/
|
|
5
|
-
const { v2: dockerCompose } = require( 'docker-compose' );
|
|
6
|
-
const util = require( 'util' );
|
|
7
|
-
const path = require( 'path' );
|
|
8
5
|
const fs = require( 'fs' ).promises;
|
|
6
|
+
const path = require( 'path' );
|
|
9
7
|
const { confirm } = require( '@inquirer/prompts' );
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Promisified dependencies
|
|
13
|
-
*/
|
|
14
|
-
const sleep = util.promisify( setTimeout );
|
|
15
8
|
const { rimraf } = require( 'rimraf' );
|
|
16
|
-
const exec = util.promisify( require( 'child_process' ).exec );
|
|
17
9
|
|
|
18
10
|
/**
|
|
19
11
|
* Internal dependencies
|
|
20
12
|
*/
|
|
21
|
-
const
|
|
22
|
-
const stop = require( './stop' );
|
|
23
|
-
const initConfig = require( '../init-config' );
|
|
24
|
-
const downloadSources = require( '../download-sources' );
|
|
25
|
-
const downloadWPPHPUnit = require( '../download-wp-phpunit' );
|
|
26
|
-
const {
|
|
27
|
-
checkDatabaseConnection,
|
|
28
|
-
configureWordPress,
|
|
29
|
-
setupWordPressDirectories,
|
|
30
|
-
readWordPressVersion,
|
|
31
|
-
canAccessWPORG,
|
|
32
|
-
} = require( '../wordpress' );
|
|
33
|
-
const { didCacheChange, setCache } = require( '../cache' );
|
|
34
|
-
const md5 = require( '../md5' );
|
|
13
|
+
const { loadConfig } = require( '../config' );
|
|
35
14
|
const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
|
|
15
|
+
const { getRuntime, getSavedRuntime, saveRuntime } = require( '../runtime' );
|
|
36
16
|
|
|
37
17
|
/**
|
|
38
18
|
* @typedef {import('../config').WPConfig} WPConfig
|
|
39
19
|
*/
|
|
40
|
-
const CONFIG_CACHE_KEY = 'config_checksum';
|
|
41
20
|
|
|
42
21
|
/**
|
|
43
22
|
* Starts the development server.
|
|
44
23
|
*
|
|
45
|
-
* @param {Object}
|
|
46
|
-
* @param {Object}
|
|
47
|
-
* @param {boolean}
|
|
48
|
-
* @param {string}
|
|
49
|
-
* @param {string}
|
|
50
|
-
* @param {boolean}
|
|
51
|
-
* @param {boolean}
|
|
24
|
+
* @param {Object} options
|
|
25
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
26
|
+
* @param {boolean} options.update If true, update sources.
|
|
27
|
+
* @param {string} options.xdebug The Xdebug mode to set.
|
|
28
|
+
* @param {string} options.spx The SPX mode to set.
|
|
29
|
+
* @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
|
|
30
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
31
|
+
* @param {string} options.runtime The runtime to use ('docker' or 'playground').
|
|
32
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
52
33
|
*/
|
|
53
34
|
module.exports = async function start( {
|
|
54
35
|
spinner,
|
|
@@ -57,250 +38,104 @@ module.exports = async function start( {
|
|
|
57
38
|
spx,
|
|
58
39
|
scripts,
|
|
59
40
|
debug,
|
|
41
|
+
runtime: runtimeName = 'docker',
|
|
42
|
+
config: customConfigPath,
|
|
60
43
|
} ) {
|
|
61
44
|
spinner.text = 'Reading configuration.';
|
|
62
|
-
await checkForLegacyInstall( spinner );
|
|
63
45
|
|
|
64
|
-
const
|
|
65
|
-
spinner,
|
|
66
|
-
debug,
|
|
67
|
-
xdebug,
|
|
68
|
-
spx,
|
|
69
|
-
writeChanges: true,
|
|
70
|
-
} );
|
|
46
|
+
const runtime = getRuntime( runtimeName );
|
|
71
47
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
spinner
|
|
75
|
-
`Warning: could not find a .wp-env.json configuration file and could not determine if '${ configDirectoryPath }' is a WordPress installation, a plugin, or a theme.`
|
|
76
|
-
);
|
|
77
|
-
spinner.start();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Check if the hash of the config has changed. If so, run configuration.
|
|
81
|
-
const configHash = md5( config );
|
|
82
|
-
const { workDirectoryPath, dockerComposeConfigPath } = config;
|
|
83
|
-
const shouldConfigureWp =
|
|
84
|
-
( update ||
|
|
85
|
-
( await didCacheChange( CONFIG_CACHE_KEY, configHash, {
|
|
86
|
-
workDirectoryPath,
|
|
87
|
-
} ) ) ) &&
|
|
88
|
-
// Don't reconfigure everything when we can't connect to the internet because
|
|
89
|
-
// the majority of update tasks involve connecting to the internet. (Such
|
|
90
|
-
// as downloading sources and pulling docker images.)
|
|
91
|
-
( await canAccessWPORG() );
|
|
92
|
-
|
|
93
|
-
const dockerComposeConfig = {
|
|
94
|
-
config: dockerComposeConfigPath,
|
|
95
|
-
log: config.debug,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
if ( ! ( await canAccessWPORG() ) ) {
|
|
99
|
-
spinner.info( 'wp-env is offline' );
|
|
48
|
+
// Check for legacy Docker installs (Docker-specific UI concern)
|
|
49
|
+
if ( runtimeName === 'docker' ) {
|
|
50
|
+
await checkForLegacyInstall( spinner );
|
|
100
51
|
}
|
|
101
52
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
* deleted, the start command will not complete successfully. Stopping
|
|
105
|
-
* the container before continuing allows the docker entrypoint script,
|
|
106
|
-
* which restores the files, to run again when we start the containers.
|
|
107
|
-
*
|
|
108
|
-
* Additionally, this serves as a way to restart the container entirely
|
|
109
|
-
* should the need arise.
|
|
110
|
-
*
|
|
111
|
-
* @see https://github.com/WordPress/gutenberg/pull/20253#issuecomment-587228440
|
|
112
|
-
*/
|
|
113
|
-
if ( shouldConfigureWp ) {
|
|
114
|
-
await stop( { spinner, debug } );
|
|
115
|
-
// Update the images before starting the services again.
|
|
116
|
-
spinner.text = 'Updating docker images.';
|
|
117
|
-
|
|
118
|
-
const directoryHash = path.basename( workDirectoryPath );
|
|
119
|
-
|
|
120
|
-
// Note: when the base docker image is updated, we want that operation to
|
|
121
|
-
// also update WordPress. Since we store wordpress/tests-wordpress files
|
|
122
|
-
// as docker volumes, simply updating the image will not change those
|
|
123
|
-
// files. Thus, we need to remove those volumes in order for the files
|
|
124
|
-
// to be updated when pulling the new images.
|
|
125
|
-
const volumesToRemove = `${ directoryHash }_wordpress ${ directoryHash }_tests-wordpress`;
|
|
53
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
54
|
+
config.debug = debug;
|
|
126
55
|
|
|
56
|
+
// Check if switching runtimes and prompt user to destroy old environment first.
|
|
57
|
+
const savedRuntime = await getSavedRuntime( config.workDirectoryPath );
|
|
58
|
+
if ( savedRuntime && savedRuntime !== runtimeName ) {
|
|
59
|
+
spinner.stop();
|
|
60
|
+
let shouldDestroy = false;
|
|
127
61
|
try {
|
|
128
|
-
|
|
129
|
-
|
|
62
|
+
shouldDestroy = await confirm( {
|
|
63
|
+
message: `Environment was previously started with '${ savedRuntime }' runtime. Destroy it and start with '${ runtimeName }'?`,
|
|
64
|
+
default: true,
|
|
65
|
+
} );
|
|
66
|
+
} catch ( error ) {
|
|
67
|
+
if ( error.name === 'ExitPromptError' ) {
|
|
68
|
+
console.log( 'Cancelled.' );
|
|
69
|
+
process.exit( 1 );
|
|
130
70
|
}
|
|
131
|
-
|
|
132
|
-
} catch {
|
|
133
|
-
// Note: we do not care about this error condition because it will
|
|
134
|
-
// mostly happen when the volume already exists. This error would not
|
|
135
|
-
// stop wp-env from working correctly.
|
|
71
|
+
throw error;
|
|
136
72
|
}
|
|
137
73
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
dockerCompose.upOne( 'mysql', {
|
|
144
|
-
...dockerComposeConfig,
|
|
145
|
-
commandOptions: shouldConfigureWp
|
|
146
|
-
? [ '--build', '--force-recreate' ]
|
|
147
|
-
: [],
|
|
148
|
-
} ),
|
|
149
|
-
shouldConfigureWp && downloadSources( config, spinner ),
|
|
150
|
-
] );
|
|
151
|
-
|
|
152
|
-
if ( shouldConfigureWp ) {
|
|
153
|
-
spinner.text = 'Setting up WordPress directories';
|
|
154
|
-
|
|
155
|
-
await setupWordPressDirectories( config );
|
|
156
|
-
|
|
157
|
-
// Use the WordPress versions to download the PHPUnit suite.
|
|
158
|
-
const wpVersions = await Promise.all( [
|
|
159
|
-
readWordPressVersion(
|
|
160
|
-
config.env.development.coreSource,
|
|
161
|
-
spinner,
|
|
162
|
-
debug
|
|
163
|
-
),
|
|
164
|
-
readWordPressVersion( config.env.tests.coreSource, spinner, debug ),
|
|
165
|
-
] );
|
|
166
|
-
await downloadWPPHPUnit(
|
|
167
|
-
config,
|
|
168
|
-
{ development: wpVersions[ 0 ], tests: wpVersions[ 1 ] },
|
|
169
|
-
spinner,
|
|
170
|
-
debug
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
spinner.text = 'Starting WordPress.';
|
|
175
|
-
|
|
176
|
-
await dockerCompose.upMany(
|
|
177
|
-
[ 'wordpress', 'tests-wordpress', 'cli', 'tests-cli' ],
|
|
178
|
-
{
|
|
179
|
-
...dockerComposeConfig,
|
|
180
|
-
commandOptions: shouldConfigureWp
|
|
181
|
-
? [ '--build', '--force-recreate' ]
|
|
182
|
-
: [],
|
|
74
|
+
if ( ! shouldDestroy ) {
|
|
75
|
+
spinner.fail(
|
|
76
|
+
`Aborted. Run 'wp-env destroy' manually or start with '--runtime=${ savedRuntime }'.`
|
|
77
|
+
);
|
|
78
|
+
process.exit( 1 );
|
|
183
79
|
}
|
|
184
|
-
);
|
|
185
80
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
: [],
|
|
192
|
-
} );
|
|
81
|
+
// User confirmed - destroy old runtime first.
|
|
82
|
+
spinner.start();
|
|
83
|
+
spinner.text = `Destroying previous ${ savedRuntime } environment.`;
|
|
84
|
+
const oldRuntime = getRuntime( savedRuntime );
|
|
85
|
+
await oldRuntime.destroy( config, { spinner } );
|
|
193
86
|
}
|
|
194
87
|
|
|
195
|
-
if ( config.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
} );
|
|
88
|
+
if ( ! config.detectedLocalConfig ) {
|
|
89
|
+
const { configDirectoryPath } = config;
|
|
90
|
+
spinner.warn(
|
|
91
|
+
`Warning: could not find a .wp-env.json configuration file and could not determine if '${ configDirectoryPath }' is a WordPress installation, a plugin, or a theme.`
|
|
92
|
+
);
|
|
93
|
+
spinner.start();
|
|
202
94
|
}
|
|
203
95
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
96
|
+
if ( config.testsEnvironment !== false ) {
|
|
97
|
+
spinner.warn(
|
|
98
|
+
'Warning: wp-env starts both development and tests environments by default.\n' +
|
|
99
|
+
'This behavior is deprecated and will be removed in a future version.\n' +
|
|
100
|
+
'To avoid this warning, add "testsEnvironment": false to your .wp-env.json.\n' +
|
|
101
|
+
'The "env", "testsPort", and "testsEnvironment" options are also deprecated.\n' +
|
|
102
|
+
'Use the --config option with a separate config file for test environments instead.\n'
|
|
103
|
+
);
|
|
104
|
+
spinner.start();
|
|
207
105
|
}
|
|
208
106
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
107
|
+
let result;
|
|
108
|
+
try {
|
|
109
|
+
result = await runtime.start( config, {
|
|
110
|
+
spinner,
|
|
111
|
+
update,
|
|
112
|
+
xdebug,
|
|
113
|
+
spx,
|
|
114
|
+
debug,
|
|
115
|
+
} );
|
|
212
116
|
|
|
117
|
+
// Save the runtime type after successful start.
|
|
118
|
+
await saveRuntime( runtimeName, config.workDirectoryPath );
|
|
119
|
+
} catch ( error ) {
|
|
120
|
+
// Attempt to stop any partially-started environment so that
|
|
121
|
+
// processes do not linger after a failed start.
|
|
213
122
|
try {
|
|
214
|
-
await
|
|
215
|
-
} catch
|
|
216
|
-
//
|
|
217
|
-
await retry( () => checkDatabaseConnection( config ), {
|
|
218
|
-
times: 30,
|
|
219
|
-
delay: 1000,
|
|
220
|
-
} );
|
|
221
|
-
|
|
222
|
-
// It takes 3-4 seconds for MySQL to be ready after it starts accepting connections.
|
|
223
|
-
await sleep( 4000 );
|
|
123
|
+
await runtime.stop( config, { spinner } );
|
|
124
|
+
} catch {
|
|
125
|
+
// Ignore cleanup errors.
|
|
224
126
|
}
|
|
225
|
-
|
|
226
|
-
// Retry WordPress installation in case MySQL *still* wasn't ready.
|
|
227
|
-
await Promise.all( [
|
|
228
|
-
retry( () => configureWordPress( 'development', config, spinner ), {
|
|
229
|
-
times: 2,
|
|
230
|
-
} ),
|
|
231
|
-
retry( () => configureWordPress( 'tests', config, spinner ), {
|
|
232
|
-
times: 2,
|
|
233
|
-
} ),
|
|
234
|
-
] );
|
|
235
|
-
|
|
236
|
-
// Set the cache key once everything has been configured.
|
|
237
|
-
await setCache( CONFIG_CACHE_KEY, configHash, {
|
|
238
|
-
workDirectoryPath,
|
|
239
|
-
} );
|
|
127
|
+
throw error;
|
|
240
128
|
}
|
|
241
129
|
|
|
242
130
|
if ( scripts ) {
|
|
243
131
|
await executeLifecycleScript( 'afterStart', config, spinner );
|
|
244
132
|
}
|
|
245
133
|
|
|
246
|
-
|
|
247
|
-
const testsSiteUrl = config.env.tests.config.WP_SITEURL;
|
|
248
|
-
|
|
249
|
-
const mySQLPort = await getPublicDockerPort(
|
|
250
|
-
'mysql',
|
|
251
|
-
3306,
|
|
252
|
-
dockerComposeConfig
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
const testsMySQLPort = await getPublicDockerPort(
|
|
256
|
-
'tests-mysql',
|
|
257
|
-
3306,
|
|
258
|
-
dockerComposeConfig
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
const phpmyadminPort = config.env.development.phpmyadminPort
|
|
262
|
-
? await getPublicDockerPort( 'phpmyadmin', 80, dockerComposeConfig )
|
|
263
|
-
: null;
|
|
264
|
-
|
|
265
|
-
const testsPhpmyadminPort = config.env.tests.phpmyadminPort
|
|
266
|
-
? await getPublicDockerPort(
|
|
267
|
-
'tests-phpmyadmin',
|
|
268
|
-
80,
|
|
269
|
-
dockerComposeConfig
|
|
270
|
-
)
|
|
271
|
-
: null;
|
|
272
|
-
|
|
273
|
-
spinner.prefixText = [
|
|
274
|
-
'WordPress development site started' +
|
|
275
|
-
( siteUrl ? ` at ${ siteUrl }` : '.' ),
|
|
276
|
-
'WordPress test site started' +
|
|
277
|
-
( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' ),
|
|
278
|
-
`MySQL is listening on port ${ mySQLPort }`,
|
|
279
|
-
`MySQL for automated testing is listening on port ${ testsMySQLPort }`,
|
|
280
|
-
phpmyadminPort &&
|
|
281
|
-
`phpMyAdmin started at http://localhost:${ phpmyadminPort }`,
|
|
282
|
-
testsPhpmyadminPort &&
|
|
283
|
-
`phpMyAdmin for automated testing started at http://localhost:${ testsPhpmyadminPort }`,
|
|
284
|
-
]
|
|
285
|
-
.filter( Boolean )
|
|
286
|
-
.join( '\n' );
|
|
134
|
+
spinner.prefixText = result.message;
|
|
287
135
|
spinner.prefixText += '\n\n';
|
|
288
136
|
spinner.text = 'Done!';
|
|
289
137
|
};
|
|
290
138
|
|
|
291
|
-
async function getPublicDockerPort(
|
|
292
|
-
service,
|
|
293
|
-
containerPort,
|
|
294
|
-
dockerComposeConfig
|
|
295
|
-
) {
|
|
296
|
-
const { out: address } = await dockerCompose.port(
|
|
297
|
-
service,
|
|
298
|
-
containerPort,
|
|
299
|
-
dockerComposeConfig
|
|
300
|
-
);
|
|
301
|
-
return address.split( ':' ).pop().trim();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
139
|
/**
|
|
305
140
|
* Checks for legacy installs and provides
|
|
306
141
|
* the user the option to delete them.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const path = require( 'path' );
|
|
6
|
+
const { existsSync } = require( 'fs' );
|
|
7
|
+
const chalk = require( 'chalk' );
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
const { loadConfig } = require( '../config' );
|
|
13
|
+
const { getRuntime, detectRuntime } = require( '../runtime' );
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if an environment has been initialized by looking for runtime-specific files.
|
|
17
|
+
*
|
|
18
|
+
* @param {Object} config The wp-env configuration object.
|
|
19
|
+
* @return {boolean} True if the environment has been initialized.
|
|
20
|
+
*/
|
|
21
|
+
function isEnvironmentInitialized( config ) {
|
|
22
|
+
// Check for Docker's docker-compose.yml
|
|
23
|
+
if ( existsSync( config.dockerComposeConfigPath ) ) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check for Playground's blueprint file
|
|
28
|
+
const playgroundBlueprintPath = path.join(
|
|
29
|
+
config.workDirectoryPath,
|
|
30
|
+
'playground-blueprint.json'
|
|
31
|
+
);
|
|
32
|
+
if ( existsSync( playgroundBlueprintPath ) ) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Outputs the status of the wp-env environment.
|
|
41
|
+
*
|
|
42
|
+
* @param {Object} options
|
|
43
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
44
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
45
|
+
* @param {boolean} options.json True to output as JSON.
|
|
46
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
47
|
+
*/
|
|
48
|
+
module.exports = async function status( {
|
|
49
|
+
spinner,
|
|
50
|
+
debug,
|
|
51
|
+
json,
|
|
52
|
+
config: customConfigPath,
|
|
53
|
+
} ) {
|
|
54
|
+
spinner.text = 'Getting environment status.';
|
|
55
|
+
|
|
56
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
57
|
+
|
|
58
|
+
// Check if environment is initialized by looking for runtime-specific files.
|
|
59
|
+
// We check for these files specifically because the work directory may exist
|
|
60
|
+
// just from caching the WordPress version, but these files are only created
|
|
61
|
+
// when `wp-env start` is actually run.
|
|
62
|
+
if ( ! isEnvironmentInitialized( config ) ) {
|
|
63
|
+
spinner.stop();
|
|
64
|
+
if ( json ) {
|
|
65
|
+
console.log(
|
|
66
|
+
JSON.stringify( {
|
|
67
|
+
status: 'uninitialized',
|
|
68
|
+
installPath: config.workDirectoryPath,
|
|
69
|
+
configPath: config.configDirectoryPath,
|
|
70
|
+
} )
|
|
71
|
+
);
|
|
72
|
+
} else {
|
|
73
|
+
console.log( formatNotInitialized( config ) );
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Detect and get runtime.
|
|
79
|
+
const runtimeName = await detectRuntime( config.workDirectoryPath );
|
|
80
|
+
const runtime = getRuntime( runtimeName );
|
|
81
|
+
|
|
82
|
+
// Get status from runtime.
|
|
83
|
+
const statusData = await runtime.getStatus( config, { spinner, debug } );
|
|
84
|
+
|
|
85
|
+
spinner.stop();
|
|
86
|
+
if ( json ) {
|
|
87
|
+
console.log( JSON.stringify( statusData ) );
|
|
88
|
+
} else {
|
|
89
|
+
console.log( formatStatus( statusData ) );
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Format status for human-readable output when not initialized.
|
|
95
|
+
*
|
|
96
|
+
* @param {Object} config The config object.
|
|
97
|
+
* @return {string} Formatted output.
|
|
98
|
+
*/
|
|
99
|
+
function formatNotInitialized( config ) {
|
|
100
|
+
const indent = ' - ';
|
|
101
|
+
return `
|
|
102
|
+
${ chalk.bold( 'status' ) }: ${ chalk.red( 'uninitialized' ) }
|
|
103
|
+
${ indent }install path: ${ chalk.dim( config.workDirectoryPath ) }
|
|
104
|
+
${ indent }config: ${ chalk.dim( config.configDirectoryPath ) }
|
|
105
|
+
|
|
106
|
+
${ chalk.dim( 'Run `wp-env start` to initialize the environment.' ) }
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Format status data for human-readable output.
|
|
112
|
+
*
|
|
113
|
+
* @param {Object} status The status object from runtime.
|
|
114
|
+
* @return {string} Formatted output.
|
|
115
|
+
*/
|
|
116
|
+
function formatStatus( status ) {
|
|
117
|
+
const statusColor = status.status === 'running' ? chalk.green : chalk.red;
|
|
118
|
+
const indent = ' - ';
|
|
119
|
+
|
|
120
|
+
let output = `
|
|
121
|
+
${ chalk.bold( 'status' ) }: ${ statusColor( status.status ) }
|
|
122
|
+
${ indent }runtime: ${ chalk.dim( status.runtime ) }
|
|
123
|
+
${ indent }install path: ${ chalk.dim( status.installPath ) }
|
|
124
|
+
${ indent }config: ${ chalk.dim( status.configPath ) }
|
|
125
|
+
`;
|
|
126
|
+
|
|
127
|
+
// Environment section.
|
|
128
|
+
output += `\n${ chalk.bold( 'environment' ) }:\n`;
|
|
129
|
+
if ( status.urls?.development ) {
|
|
130
|
+
output += `${ indent }url: ${ chalk.dim( status.urls.development ) }\n`;
|
|
131
|
+
}
|
|
132
|
+
output += `${ indent }multisite: ${ chalk.dim(
|
|
133
|
+
status.config?.multisite ? 'yes' : 'no'
|
|
134
|
+
) }\n`;
|
|
135
|
+
output += `${ indent }xdebug: ${ chalk.dim(
|
|
136
|
+
status.config?.xdebug || 'off'
|
|
137
|
+
) }\n`;
|
|
138
|
+
if ( status.ports?.development ) {
|
|
139
|
+
output += `${ indent }http port: ${ chalk.dim(
|
|
140
|
+
status.ports.development
|
|
141
|
+
) }\n`;
|
|
142
|
+
}
|
|
143
|
+
if ( status.urls?.phpmyadmin ) {
|
|
144
|
+
output += `${ indent }phpmyadmin url: ${ chalk.dim(
|
|
145
|
+
status.urls.phpmyadmin
|
|
146
|
+
) }\n`;
|
|
147
|
+
}
|
|
148
|
+
if ( status.ports?.mysql ) {
|
|
149
|
+
output += `${ indent }mysql port: ${ chalk.dim(
|
|
150
|
+
status.ports.mysql
|
|
151
|
+
) }\n`;
|
|
152
|
+
}
|
|
153
|
+
if ( status.ports?.tests ) {
|
|
154
|
+
output += `${ indent }test http port: ${ chalk.dim(
|
|
155
|
+
status.ports.tests
|
|
156
|
+
) }\n`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return output;
|
|
160
|
+
}
|
package/lib/commands/stop.js
CHANGED
|
@@ -2,32 +2,30 @@
|
|
|
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
|
* Stops the development server.
|
|
14
15
|
*
|
|
15
|
-
* @param {Object}
|
|
16
|
-
* @param {Object}
|
|
17
|
-
* @param {boolean}
|
|
16
|
+
* @param {Object} options
|
|
17
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
18
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
19
|
+
* @param {string|null} options.config Path to a custom .wp-env.json configuration file.
|
|
18
20
|
*/
|
|
19
|
-
module.exports = async function stop( {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
log: debug,
|
|
30
|
-
} );
|
|
31
|
-
|
|
32
|
-
spinner.text = 'Stopped WordPress.';
|
|
21
|
+
module.exports = async function stop( {
|
|
22
|
+
spinner,
|
|
23
|
+
debug,
|
|
24
|
+
config: customConfigPath,
|
|
25
|
+
} ) {
|
|
26
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
27
|
+
const runtime = getRuntime(
|
|
28
|
+
await detectRuntime( config.workDirectoryPath )
|
|
29
|
+
);
|
|
30
|
+
await runtime.stop( config, { spinner, debug } );
|
|
33
31
|
};
|
|
@@ -23,7 +23,6 @@ const { checkPort, checkVersion, checkString } = require( './validate-config' );
|
|
|
23
23
|
* @property {?number} phpmyadminPort An override for the development environment's phpMyAdmin port.
|
|
24
24
|
* @property {?WPSource} coreSource An override for all environment's coreSource.
|
|
25
25
|
* @property {?string} phpVersion An override for all environment's PHP version.
|
|
26
|
-
* @property {?boolean} multisite An override for if environmen should be multisite.
|
|
27
26
|
* @property {?Object.<string, string>} lifecycleScripts An override for various lifecycle scripts.
|
|
28
27
|
*/
|
|
29
28
|
|
|
@@ -69,10 +68,6 @@ module.exports = function getConfigFromEnvironmentVars( cacheDirectoryPath ) {
|
|
|
69
68
|
environmentConfig.phpVersion = process.env.WP_ENV_PHP_VERSION;
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
if ( process.env.WP_ENV_MULTISITE ) {
|
|
73
|
-
environmentConfig.multisite = !! process.env.WP_ENV_MULTISITE;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
71
|
return environmentConfig;
|
|
77
72
|
};
|
|
78
73
|
|
|
@@ -108,6 +103,8 @@ function getLifecycleScriptOverrides() {
|
|
|
108
103
|
const lifecycleEnvironmentVars = {
|
|
109
104
|
WP_ENV_LIFECYCLE_SCRIPT_AFTER_START: 'afterStart',
|
|
110
105
|
WP_ENV_LIFECYCLE_SCRIPT_AFTER_CLEAN: 'afterClean',
|
|
106
|
+
WP_ENV_LIFECYCLE_SCRIPT_AFTER_RESET: 'afterReset',
|
|
107
|
+
WP_ENV_LIFECYCLE_SCRIPT_AFTER_CLEANUP: 'afterCleanup',
|
|
111
108
|
WP_ENV_LIFECYCLE_SCRIPT_AFTER_DESTROY: 'afterDestroy',
|
|
112
109
|
};
|
|
113
110
|
for ( const envVar in lifecycleEnvironmentVars ) {
|
|
@@ -11,6 +11,7 @@ const fs = require( 'fs' ).promises;
|
|
|
11
11
|
const getCacheDirectory = require( './get-cache-directory' );
|
|
12
12
|
const md5 = require( '../md5' );
|
|
13
13
|
const { parseConfig, getConfigFilePath } = require( './parse-config' );
|
|
14
|
+
const { ValidationError } = require( './validate-config' );
|
|
14
15
|
const postProcessConfig = require( './post-process-config' );
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -35,12 +36,31 @@ const postProcessConfig = require( './post-process-config' );
|
|
|
35
36
|
/**
|
|
36
37
|
* Loads any configuration from a given directory.
|
|
37
38
|
*
|
|
38
|
-
* @param {string}
|
|
39
|
+
* @param {string} configDirectoryPath The directory we want to load the config from.
|
|
40
|
+
* @param {string|null} customConfigPath Optional custom config file path.
|
|
39
41
|
*
|
|
40
42
|
* @return {Promise<WPConfig>} The config object we've loaded.
|
|
41
43
|
*/
|
|
42
|
-
module.exports = async function loadConfig(
|
|
43
|
-
|
|
44
|
+
module.exports = async function loadConfig(
|
|
45
|
+
configDirectoryPath,
|
|
46
|
+
customConfigPath = null
|
|
47
|
+
) {
|
|
48
|
+
const configFilePath = getConfigFilePath(
|
|
49
|
+
configDirectoryPath,
|
|
50
|
+
'local',
|
|
51
|
+
customConfigPath
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// If a custom config path was provided, verify the file exists.
|
|
55
|
+
if ( customConfigPath ) {
|
|
56
|
+
try {
|
|
57
|
+
await fs.stat( configFilePath );
|
|
58
|
+
} catch ( error ) {
|
|
59
|
+
throw new ValidationError(
|
|
60
|
+
`Config file not found: ${ configFilePath }`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
44
64
|
|
|
45
65
|
const cacheDirectoryPath = path.resolve(
|
|
46
66
|
await getCacheDirectory(),
|
|
@@ -49,7 +69,11 @@ module.exports = async function loadConfig( configDirectoryPath ) {
|
|
|
49
69
|
|
|
50
70
|
// Parse any configuration we found in the given directory.
|
|
51
71
|
// This comes merged and prepared for internal consumption.
|
|
52
|
-
let config = await parseConfig(
|
|
72
|
+
let config = await parseConfig(
|
|
73
|
+
configDirectoryPath,
|
|
74
|
+
cacheDirectoryPath,
|
|
75
|
+
customConfigPath
|
|
76
|
+
);
|
|
53
77
|
|
|
54
78
|
// Make sure to perform any additional post-processing that
|
|
55
79
|
// may be needed before the config object is ready for
|
|
@@ -64,9 +88,15 @@ module.exports = async function loadConfig( configDirectoryPath ) {
|
|
|
64
88
|
),
|
|
65
89
|
configDirectoryPath,
|
|
66
90
|
workDirectoryPath: cacheDirectoryPath,
|
|
91
|
+
customConfigPath,
|
|
92
|
+
testsEnvironment: config.testsEnvironment !== false,
|
|
67
93
|
detectedLocalConfig: await hasLocalConfig( [
|
|
68
94
|
configFilePath,
|
|
69
|
-
getConfigFilePath(
|
|
95
|
+
getConfigFilePath(
|
|
96
|
+
configDirectoryPath,
|
|
97
|
+
'override',
|
|
98
|
+
customConfigPath
|
|
99
|
+
),
|
|
70
100
|
] ),
|
|
71
101
|
lifecycleScripts: config.lifecycleScripts,
|
|
72
102
|
env: config.env,
|