@wordpress/env 10.39.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 +127 -76
- package/lib/cli.js +67 -10
- package/lib/commands/clean.js +13 -4
- package/lib/commands/cleanup.js +79 -0
- package/lib/commands/destroy.js +30 -18
- package/lib/commands/index.js +6 -2
- package/lib/commands/logs.js +17 -8
- package/lib/commands/reset.js +46 -0
- package/lib/commands/run.js +13 -9
- package/lib/commands/start.js +54 -14
- package/lib/commands/status.js +160 -0
- package/lib/commands/stop.js +13 -6
- 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/runtime/docker/build-docker-compose-config.js +164 -125
- package/lib/runtime/docker/download-sources.js +5 -1
- package/lib/runtime/docker/download-wp-phpunit.js +3 -0
- package/lib/runtime/docker/index.js +281 -91
- package/lib/runtime/docker/init-config.js +20 -12
- package/lib/runtime/docker/wordpress.js +0 -15
- package/lib/runtime/errors.js +11 -0
- package/lib/runtime/index.js +40 -18
- package/lib/runtime/playground/blueprint-builder.js +25 -33
- package/lib/runtime/playground/index.js +82 -4
- package/lib/test/build-docker-compose-config.js +147 -0
- package/lib/test/cli.js +49 -13
- package/package.json +2 -2
- package/lib/commands/install-path.js +0 -33
|
@@ -11,7 +11,6 @@ const { rimraf } = require( 'rimraf' );
|
|
|
11
11
|
/**
|
|
12
12
|
* Promisified dependencies
|
|
13
13
|
*/
|
|
14
|
-
const sleep = util.promisify( setTimeout );
|
|
15
14
|
const exec = util.promisify( require( 'child_process' ).exec );
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -26,7 +25,6 @@ const {
|
|
|
26
25
|
validateRunContainer,
|
|
27
26
|
} = require( './validate-run-container' );
|
|
28
27
|
const {
|
|
29
|
-
checkDatabaseConnection,
|
|
30
28
|
configureWordPress,
|
|
31
29
|
resetDatabase,
|
|
32
30
|
setupWordPressDirectories,
|
|
@@ -109,8 +107,11 @@ class DockerRuntime {
|
|
|
109
107
|
xdebug,
|
|
110
108
|
spx,
|
|
111
109
|
writeChanges: true,
|
|
110
|
+
customConfigPath: config.customConfigPath,
|
|
112
111
|
} );
|
|
113
112
|
|
|
113
|
+
const testsEnabled = fullConfig.testsEnvironment !== false;
|
|
114
|
+
|
|
114
115
|
// Check if the hash of the config has changed. If so, run configuration.
|
|
115
116
|
const configHash = md5( fullConfig );
|
|
116
117
|
const { workDirectoryPath, dockerComposeConfigPath } = fullConfig;
|
|
@@ -139,13 +140,19 @@ class DockerRuntime {
|
|
|
139
140
|
* the container before continuing allows the docker entrypoint script,
|
|
140
141
|
* which restores the files, to run again when we start the containers.
|
|
141
142
|
*
|
|
142
|
-
* Additionally,
|
|
143
|
-
*
|
|
143
|
+
* Additionally, --remove-orphans ensures containers from services that
|
|
144
|
+
* were removed in the new config (e.g., tests-* after setting
|
|
145
|
+
* testsEnvironment: false) are properly stopped.
|
|
144
146
|
*
|
|
145
147
|
* @see https://github.com/WordPress/gutenberg/pull/20253#issuecomment-587228440
|
|
146
148
|
*/
|
|
147
149
|
if ( shouldConfigureWp ) {
|
|
148
|
-
|
|
150
|
+
spinner.text = 'Stopping WordPress.';
|
|
151
|
+
await dockerCompose.down( {
|
|
152
|
+
config: dockerComposeConfigPath,
|
|
153
|
+
log: debug,
|
|
154
|
+
commandOptions: [ '--remove-orphans' ],
|
|
155
|
+
} );
|
|
149
156
|
// Update the images before starting the services again.
|
|
150
157
|
spinner.text = 'Updating docker images.';
|
|
151
158
|
|
|
@@ -156,7 +163,9 @@ class DockerRuntime {
|
|
|
156
163
|
// as docker volumes, simply updating the image will not change those
|
|
157
164
|
// files. Thus, we need to remove those volumes in order for the files
|
|
158
165
|
// to be updated when pulling the new images.
|
|
159
|
-
const volumesToRemove =
|
|
166
|
+
const volumesToRemove = testsEnabled
|
|
167
|
+
? `${ directoryHash }_wordpress ${ directoryHash }_tests-wordpress`
|
|
168
|
+
: `${ directoryHash }_wordpress`;
|
|
160
169
|
|
|
161
170
|
try {
|
|
162
171
|
if ( fullConfig.debug ) {
|
|
@@ -173,8 +182,12 @@ class DockerRuntime {
|
|
|
173
182
|
spinner.text = 'Downloading sources.';
|
|
174
183
|
}
|
|
175
184
|
|
|
185
|
+
const mysqlServices = [ 'mysql' ];
|
|
186
|
+
if ( testsEnabled ) {
|
|
187
|
+
mysqlServices.push( 'tests-mysql' );
|
|
188
|
+
}
|
|
176
189
|
await Promise.all( [
|
|
177
|
-
dockerCompose.
|
|
190
|
+
dockerCompose.upMany( mysqlServices, {
|
|
178
191
|
...dockerComposeConfig,
|
|
179
192
|
commandOptions: shouldConfigureWp
|
|
180
193
|
? [ '--build', '--force-recreate' ]
|
|
@@ -189,37 +202,44 @@ class DockerRuntime {
|
|
|
189
202
|
await setupWordPressDirectories( fullConfig );
|
|
190
203
|
|
|
191
204
|
// Use the WordPress versions to download the PHPUnit suite.
|
|
192
|
-
const
|
|
205
|
+
const wpVersionPromises = [
|
|
193
206
|
readWordPressVersion(
|
|
194
207
|
fullConfig.env.development.coreSource,
|
|
195
208
|
spinner,
|
|
196
209
|
debug
|
|
197
210
|
),
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
];
|
|
212
|
+
if ( testsEnabled ) {
|
|
213
|
+
wpVersionPromises.push(
|
|
214
|
+
readWordPressVersion(
|
|
215
|
+
fullConfig.env.tests.coreSource,
|
|
216
|
+
spinner,
|
|
217
|
+
debug
|
|
218
|
+
)
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
const wpVersions = await Promise.all( wpVersionPromises );
|
|
222
|
+
const wpVersionMap = {
|
|
223
|
+
development: wpVersions[ 0 ],
|
|
224
|
+
};
|
|
225
|
+
if ( testsEnabled ) {
|
|
226
|
+
wpVersionMap.tests = wpVersions[ 1 ];
|
|
227
|
+
}
|
|
228
|
+
await downloadWPPHPUnit( fullConfig, wpVersionMap, spinner, debug );
|
|
210
229
|
}
|
|
211
230
|
|
|
212
231
|
spinner.text = 'Starting WordPress.';
|
|
213
232
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
233
|
+
const wpServices = [ 'wordpress', 'cli' ];
|
|
234
|
+
if ( testsEnabled ) {
|
|
235
|
+
wpServices.push( 'tests-wordpress', 'tests-cli' );
|
|
236
|
+
}
|
|
237
|
+
await dockerCompose.upMany( wpServices, {
|
|
238
|
+
...dockerComposeConfig,
|
|
239
|
+
commandOptions: shouldConfigureWp
|
|
240
|
+
? [ '--build', '--force-recreate' ]
|
|
241
|
+
: [],
|
|
242
|
+
} );
|
|
223
243
|
|
|
224
244
|
if ( fullConfig.env.development.phpmyadminPort ) {
|
|
225
245
|
await dockerCompose.upOne( 'phpmyadmin', {
|
|
@@ -230,7 +250,7 @@ class DockerRuntime {
|
|
|
230
250
|
} );
|
|
231
251
|
}
|
|
232
252
|
|
|
233
|
-
if ( fullConfig.env.tests.phpmyadminPort ) {
|
|
253
|
+
if ( testsEnabled && fullConfig.env.tests.phpmyadminPort ) {
|
|
234
254
|
await dockerCompose.upOne( 'tests-phpmyadmin', {
|
|
235
255
|
...dockerComposeConfig,
|
|
236
256
|
commandOptions: shouldConfigureWp
|
|
@@ -250,21 +270,8 @@ class DockerRuntime {
|
|
|
250
270
|
if ( shouldConfigureWp ) {
|
|
251
271
|
spinner.text = 'Configuring WordPress.';
|
|
252
272
|
|
|
253
|
-
try {
|
|
254
|
-
await checkDatabaseConnection( fullConfig );
|
|
255
|
-
} catch ( error ) {
|
|
256
|
-
// Wait 30 seconds for MySQL to accept connections.
|
|
257
|
-
await retry( () => checkDatabaseConnection( fullConfig ), {
|
|
258
|
-
times: 30,
|
|
259
|
-
delay: 1000,
|
|
260
|
-
} );
|
|
261
|
-
|
|
262
|
-
// It takes 3-4 seconds for MySQL to be ready after it starts accepting connections.
|
|
263
|
-
await sleep( 4000 );
|
|
264
|
-
}
|
|
265
|
-
|
|
266
273
|
// Retry WordPress installation in case MySQL *still* wasn't ready.
|
|
267
|
-
|
|
274
|
+
const configTasks = [
|
|
268
275
|
retry(
|
|
269
276
|
() =>
|
|
270
277
|
configureWordPress(
|
|
@@ -276,13 +283,19 @@ class DockerRuntime {
|
|
|
276
283
|
times: 2,
|
|
277
284
|
}
|
|
278
285
|
),
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
+
];
|
|
287
|
+
if ( testsEnabled ) {
|
|
288
|
+
configTasks.push(
|
|
289
|
+
retry(
|
|
290
|
+
() =>
|
|
291
|
+
configureWordPress( 'tests', fullConfig, spinner ),
|
|
292
|
+
{
|
|
293
|
+
times: 2,
|
|
294
|
+
}
|
|
295
|
+
)
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
await Promise.all( configTasks );
|
|
286
299
|
|
|
287
300
|
// Set the cache key once everything has been configured.
|
|
288
301
|
await setCache( CONFIG_CACHE_KEY, configHash, {
|
|
@@ -292,7 +305,6 @@ class DockerRuntime {
|
|
|
292
305
|
|
|
293
306
|
// Get port information for the result message
|
|
294
307
|
const siteUrl = fullConfig.env.development.config.WP_SITEURL;
|
|
295
|
-
const testsSiteUrl = fullConfig.env.tests.config.WP_SITEURL;
|
|
296
308
|
|
|
297
309
|
const mySQLPort = await this._getPublicDockerPort(
|
|
298
310
|
'mysql',
|
|
@@ -300,12 +312,6 @@ class DockerRuntime {
|
|
|
300
312
|
dockerComposeConfig
|
|
301
313
|
);
|
|
302
314
|
|
|
303
|
-
const testsMySQLPort = await this._getPublicDockerPort(
|
|
304
|
-
'tests-mysql',
|
|
305
|
-
3306,
|
|
306
|
-
dockerComposeConfig
|
|
307
|
-
);
|
|
308
|
-
|
|
309
315
|
const phpmyadminPort = fullConfig.env.development.phpmyadminPort
|
|
310
316
|
? await this._getPublicDockerPort(
|
|
311
317
|
'phpmyadmin',
|
|
@@ -314,31 +320,42 @@ class DockerRuntime {
|
|
|
314
320
|
)
|
|
315
321
|
: null;
|
|
316
322
|
|
|
317
|
-
const testsPhpmyadminPort = fullConfig.env.tests.phpmyadminPort
|
|
318
|
-
? await this._getPublicDockerPort(
|
|
319
|
-
'tests-phpmyadmin',
|
|
320
|
-
80,
|
|
321
|
-
dockerComposeConfig
|
|
322
|
-
)
|
|
323
|
-
: null;
|
|
324
|
-
|
|
325
323
|
const message = [
|
|
326
324
|
'WordPress development site started' +
|
|
327
325
|
( siteUrl ? ` at ${ siteUrl }` : '.' ),
|
|
328
|
-
'WordPress test site started' +
|
|
329
|
-
( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' ),
|
|
330
326
|
`MySQL is listening on port ${ mySQLPort }`,
|
|
331
|
-
`MySQL for automated testing is listening on port ${ testsMySQLPort }`,
|
|
332
327
|
phpmyadminPort &&
|
|
333
328
|
`phpMyAdmin started at http://localhost:${ phpmyadminPort }`,
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
.
|
|
329
|
+
];
|
|
330
|
+
|
|
331
|
+
if ( testsEnabled ) {
|
|
332
|
+
const testsSiteUrl = fullConfig.env.tests.config.WP_SITEURL;
|
|
333
|
+
const testsMySQLPort = await this._getPublicDockerPort(
|
|
334
|
+
'tests-mysql',
|
|
335
|
+
3306,
|
|
336
|
+
dockerComposeConfig
|
|
337
|
+
);
|
|
338
|
+
const testsPhpmyadminPort = fullConfig.env.tests.phpmyadminPort
|
|
339
|
+
? await this._getPublicDockerPort(
|
|
340
|
+
'tests-phpmyadmin',
|
|
341
|
+
80,
|
|
342
|
+
dockerComposeConfig
|
|
343
|
+
)
|
|
344
|
+
: null;
|
|
345
|
+
|
|
346
|
+
message.push(
|
|
347
|
+
'WordPress test site started' +
|
|
348
|
+
( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' ),
|
|
349
|
+
`MySQL for automated testing is listening on port ${ testsMySQLPort }`,
|
|
350
|
+
testsPhpmyadminPort &&
|
|
351
|
+
`phpMyAdmin for automated testing started at http://localhost:${ testsPhpmyadminPort }`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const formattedMessage = message.filter( Boolean ).join( '\n' );
|
|
339
356
|
|
|
340
357
|
return {
|
|
341
|
-
message,
|
|
358
|
+
message: formattedMessage,
|
|
342
359
|
siteUrl,
|
|
343
360
|
};
|
|
344
361
|
}
|
|
@@ -369,6 +386,15 @@ class DockerRuntime {
|
|
|
369
386
|
return 'WARNING! This will remove Docker containers, volumes, networks, and images associated with the WordPress instance.';
|
|
370
387
|
}
|
|
371
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Get the warning message for cleanup confirmation.
|
|
391
|
+
*
|
|
392
|
+
* @return {string} Warning message.
|
|
393
|
+
*/
|
|
394
|
+
getCleanupWarningMessage() {
|
|
395
|
+
return 'WARNING! This will remove Docker containers, volumes, networks, and local files associated with the WordPress instance. Docker images will be preserved.';
|
|
396
|
+
}
|
|
397
|
+
|
|
372
398
|
/**
|
|
373
399
|
* Stop the Docker containers.
|
|
374
400
|
*
|
|
@@ -381,6 +407,7 @@ class DockerRuntime {
|
|
|
381
407
|
const { dockerComposeConfigPath } = await initConfig( {
|
|
382
408
|
spinner,
|
|
383
409
|
debug,
|
|
410
|
+
customConfigPath: config.customConfigPath,
|
|
384
411
|
} );
|
|
385
412
|
|
|
386
413
|
spinner.text = 'Stopping WordPress.';
|
|
@@ -413,7 +440,8 @@ class DockerRuntime {
|
|
|
413
440
|
spinner.text = 'Removing local files.';
|
|
414
441
|
// Note: there is a race condition where docker compose actually hasn't finished
|
|
415
442
|
// by this point, which causes rimraf to fail. We need to wait at least 2.5-5s,
|
|
416
|
-
// but using 10s in case it's
|
|
443
|
+
// but using 10s in case it's dependent on the machine. Removing images takes
|
|
444
|
+
// longer so we use a longer wait time here.
|
|
417
445
|
await new Promise( ( resolve ) => setTimeout( resolve, 10000 ) );
|
|
418
446
|
await rimraf( config.workDirectoryPath );
|
|
419
447
|
|
|
@@ -421,27 +449,79 @@ class DockerRuntime {
|
|
|
421
449
|
}
|
|
422
450
|
|
|
423
451
|
/**
|
|
424
|
-
*
|
|
452
|
+
* Cleanup the Docker containers and remove local files, but preserve images.
|
|
453
|
+
*
|
|
454
|
+
* @param {WPConfig} config The wp-env config object.
|
|
455
|
+
* @param {Object} options Cleanup options.
|
|
456
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
457
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
458
|
+
*/
|
|
459
|
+
async cleanup( config, { spinner, debug } ) {
|
|
460
|
+
spinner.text = 'Removing docker containers, volumes, and networks.';
|
|
461
|
+
|
|
462
|
+
await dockerCompose.down( {
|
|
463
|
+
config: config.dockerComposeConfigPath,
|
|
464
|
+
commandOptions: [ '--volumes', '--remove-orphans' ],
|
|
465
|
+
log: debug,
|
|
466
|
+
} );
|
|
467
|
+
|
|
468
|
+
spinner.text = 'Removing local files.';
|
|
469
|
+
// Note: there is a race condition where docker compose actually hasn't finished
|
|
470
|
+
// by this point, which causes rimraf to fail. We need to wait at least 2.5-5s,
|
|
471
|
+
// but since we're not removing images, the wait can be shorter.
|
|
472
|
+
await new Promise( ( resolve ) => setTimeout( resolve, 3000 ) );
|
|
473
|
+
await rimraf( config.workDirectoryPath );
|
|
474
|
+
|
|
475
|
+
spinner.text = 'Cleaned up WordPress environment.';
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Reset the WordPress database.
|
|
425
480
|
*
|
|
426
481
|
* @param {WPConfig} config The wp-env config object.
|
|
427
|
-
* @param {Object} options
|
|
428
|
-
* @param {string} options.environment The environment to
|
|
482
|
+
* @param {Object} options Reset options.
|
|
483
|
+
* @param {string} options.environment The environment to reset.
|
|
429
484
|
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
430
485
|
* @param {boolean} options.debug True if debug mode is enabled.
|
|
431
486
|
*/
|
|
432
487
|
async clean( config, { environment, spinner, debug } ) {
|
|
433
|
-
const fullConfig = await initConfig( {
|
|
488
|
+
const fullConfig = await initConfig( {
|
|
489
|
+
spinner,
|
|
490
|
+
debug,
|
|
491
|
+
customConfigPath: config.customConfigPath,
|
|
492
|
+
} );
|
|
493
|
+
|
|
494
|
+
const testsEnabled = fullConfig.testsEnvironment !== false;
|
|
495
|
+
|
|
496
|
+
if ( ! testsEnabled && environment === 'tests' ) {
|
|
497
|
+
throw new Error(
|
|
498
|
+
'Cannot reset the tests environment because it is disabled in the configuration.'
|
|
499
|
+
);
|
|
500
|
+
}
|
|
434
501
|
|
|
435
502
|
const description = `${ environment } environment${
|
|
436
503
|
environment === 'all' ? 's' : ''
|
|
437
504
|
}`;
|
|
438
|
-
spinner.text = `
|
|
505
|
+
spinner.text = `Resetting ${ description }.`;
|
|
439
506
|
|
|
440
507
|
const tasks = [];
|
|
441
508
|
|
|
442
|
-
// Start the
|
|
443
|
-
//
|
|
444
|
-
|
|
509
|
+
// Start the appropriate MySQL service(s) first to avoid race conditions
|
|
510
|
+
// where parallel tasks try to create docker networks with the same name.
|
|
511
|
+
// The dependency chain (cli -> wordpress -> mysql with service_healthy)
|
|
512
|
+
// ensures MySQL is ready before database operations run.
|
|
513
|
+
const mysqlServices = [];
|
|
514
|
+
if ( environment === 'all' || environment === 'development' ) {
|
|
515
|
+
mysqlServices.push( 'mysql' );
|
|
516
|
+
}
|
|
517
|
+
if (
|
|
518
|
+
testsEnabled &&
|
|
519
|
+
( environment === 'all' || environment === 'tests' )
|
|
520
|
+
) {
|
|
521
|
+
mysqlServices.push( 'tests-mysql' );
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
await dockerCompose.upMany( mysqlServices, {
|
|
445
525
|
config: fullConfig.dockerComposeConfigPath,
|
|
446
526
|
log: fullConfig.debug,
|
|
447
527
|
} );
|
|
@@ -456,7 +536,10 @@ class DockerRuntime {
|
|
|
456
536
|
);
|
|
457
537
|
}
|
|
458
538
|
|
|
459
|
-
if (
|
|
539
|
+
if (
|
|
540
|
+
testsEnabled &&
|
|
541
|
+
( environment === 'all' || environment === 'tests' )
|
|
542
|
+
) {
|
|
460
543
|
tasks.push(
|
|
461
544
|
resetDatabase( 'tests', fullConfig )
|
|
462
545
|
.then( () => configureWordPress( 'tests', fullConfig ) )
|
|
@@ -466,7 +549,7 @@ class DockerRuntime {
|
|
|
466
549
|
|
|
467
550
|
await Promise.all( tasks );
|
|
468
551
|
|
|
469
|
-
spinner.text = `
|
|
552
|
+
spinner.text = `Reset ${ description }.`;
|
|
470
553
|
}
|
|
471
554
|
|
|
472
555
|
/**
|
|
@@ -493,7 +576,20 @@ class DockerRuntime {
|
|
|
493
576
|
// Validate the container name (throws for deprecated containers)
|
|
494
577
|
validateRunContainer( container );
|
|
495
578
|
|
|
496
|
-
|
|
579
|
+
if (
|
|
580
|
+
config.testsEnvironment === false &&
|
|
581
|
+
container.startsWith( 'tests-' )
|
|
582
|
+
) {
|
|
583
|
+
throw new Error(
|
|
584
|
+
`Cannot run commands on "${ container }" because the tests environment is disabled in the configuration.`
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const fullConfig = await initConfig( {
|
|
589
|
+
spinner,
|
|
590
|
+
debug,
|
|
591
|
+
customConfigPath: config.customConfigPath,
|
|
592
|
+
} );
|
|
497
593
|
|
|
498
594
|
// Shows a contextual tip for the given command.
|
|
499
595
|
const joinedCommand = command.join( ' ' );
|
|
@@ -520,7 +616,19 @@ class DockerRuntime {
|
|
|
520
616
|
* @param {boolean} options.debug True if debug mode is enabled.
|
|
521
617
|
*/
|
|
522
618
|
async logs( config, { environment, watch, spinner, debug } ) {
|
|
523
|
-
const fullConfig = await initConfig( {
|
|
619
|
+
const fullConfig = await initConfig( {
|
|
620
|
+
spinner,
|
|
621
|
+
debug,
|
|
622
|
+
customConfigPath: config.customConfigPath,
|
|
623
|
+
} );
|
|
624
|
+
|
|
625
|
+
const testsEnabled = fullConfig.testsEnvironment !== false;
|
|
626
|
+
|
|
627
|
+
if ( ! testsEnabled && environment === 'tests' ) {
|
|
628
|
+
throw new Error(
|
|
629
|
+
'Cannot show logs for the tests environment because it is disabled in the configuration.'
|
|
630
|
+
);
|
|
631
|
+
}
|
|
524
632
|
|
|
525
633
|
// If we show text while watching the logs, it will continue showing up every
|
|
526
634
|
// few lines in the logs as they happen, which isn't a good look. So only
|
|
@@ -529,10 +637,16 @@ class DockerRuntime {
|
|
|
529
637
|
spinner.text = `Showing logs for the ${ environment } environment.`;
|
|
530
638
|
}
|
|
531
639
|
|
|
532
|
-
|
|
533
|
-
|
|
640
|
+
let servicesToWatch;
|
|
641
|
+
if ( environment === 'all' ) {
|
|
642
|
+
servicesToWatch = testsEnabled
|
|
534
643
|
? [ 'tests-wordpress', 'wordpress' ]
|
|
535
|
-
: [
|
|
644
|
+
: [ 'wordpress' ];
|
|
645
|
+
} else {
|
|
646
|
+
servicesToWatch = [
|
|
647
|
+
environment === 'tests' ? 'tests-wordpress' : 'wordpress',
|
|
648
|
+
];
|
|
649
|
+
}
|
|
536
650
|
|
|
537
651
|
const output = await Promise.all( [
|
|
538
652
|
...servicesToWatch.map( ( service ) =>
|
|
@@ -577,6 +691,82 @@ class DockerRuntime {
|
|
|
577
691
|
spinner.text = 'Finished showing logs.';
|
|
578
692
|
}
|
|
579
693
|
|
|
694
|
+
/**
|
|
695
|
+
* Get the status of the Docker environment.
|
|
696
|
+
*
|
|
697
|
+
* @param {WPConfig} config The wp-env config object.
|
|
698
|
+
* @param {Object} options Status options.
|
|
699
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
700
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
701
|
+
* @return {Promise<Object>} Status object with environment information.
|
|
702
|
+
*/
|
|
703
|
+
async getStatus( config, { spinner, debug } ) {
|
|
704
|
+
spinner.text = 'Getting environment status.';
|
|
705
|
+
|
|
706
|
+
const fullConfig = await initConfig( {
|
|
707
|
+
spinner,
|
|
708
|
+
debug,
|
|
709
|
+
customConfigPath: config.customConfigPath,
|
|
710
|
+
} );
|
|
711
|
+
const dockerComposeConfig = {
|
|
712
|
+
config: fullConfig.dockerComposeConfigPath,
|
|
713
|
+
log: debug,
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
// Check if containers are running by trying to get a port.
|
|
717
|
+
let isRunning = false;
|
|
718
|
+
let mySQLPort = null;
|
|
719
|
+
let phpmyadminPort = null;
|
|
720
|
+
|
|
721
|
+
try {
|
|
722
|
+
mySQLPort = await this._getPublicDockerPort(
|
|
723
|
+
'mysql',
|
|
724
|
+
3306,
|
|
725
|
+
dockerComposeConfig
|
|
726
|
+
);
|
|
727
|
+
isRunning = true;
|
|
728
|
+
|
|
729
|
+
if ( fullConfig.env.development.phpmyadminPort ) {
|
|
730
|
+
phpmyadminPort = await this._getPublicDockerPort(
|
|
731
|
+
'phpmyadmin',
|
|
732
|
+
80,
|
|
733
|
+
dockerComposeConfig
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
} catch {
|
|
737
|
+
// Containers are not running.
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const siteUrl = fullConfig.env.development.config.WP_SITEURL;
|
|
741
|
+
|
|
742
|
+
const testsEnabled = fullConfig.testsEnvironment !== false;
|
|
743
|
+
|
|
744
|
+
return {
|
|
745
|
+
status: isRunning ? 'running' : 'stopped',
|
|
746
|
+
runtime: 'docker',
|
|
747
|
+
urls: {
|
|
748
|
+
development: isRunning ? siteUrl : null,
|
|
749
|
+
phpmyadmin:
|
|
750
|
+
isRunning && phpmyadminPort
|
|
751
|
+
? `http://localhost:${ phpmyadminPort }`
|
|
752
|
+
: null,
|
|
753
|
+
},
|
|
754
|
+
ports: {
|
|
755
|
+
development: fullConfig.env.development.port,
|
|
756
|
+
...( testsEnabled && {
|
|
757
|
+
tests: fullConfig.env.tests.port,
|
|
758
|
+
} ),
|
|
759
|
+
mysql: mySQLPort,
|
|
760
|
+
},
|
|
761
|
+
config: {
|
|
762
|
+
multisite: fullConfig.env.development.multisite,
|
|
763
|
+
xdebug: fullConfig.xdebug || 'off',
|
|
764
|
+
},
|
|
765
|
+
configPath: fullConfig.configDirectoryPath,
|
|
766
|
+
installPath: fullConfig.workDirectoryPath,
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
|
|
580
770
|
/**
|
|
581
771
|
* Runs an arbitrary command on the given Docker container.
|
|
582
772
|
*
|
|
@@ -22,16 +22,17 @@ const buildDockerComposeConfig = require( './build-docker-compose-config' );
|
|
|
22
22
|
* ./.wp-env.json, creates ~/.wp-env, ~/.wp-env/docker-compose.yml, and
|
|
23
23
|
* ~/.wp-env/Dockerfile.
|
|
24
24
|
*
|
|
25
|
-
* @param {Object}
|
|
26
|
-
* @param {Object}
|
|
27
|
-
* @param {boolean}
|
|
28
|
-
* @param {string}
|
|
29
|
-
* @param {string}
|
|
30
|
-
* @param {boolean}
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
25
|
+
* @param {Object} options
|
|
26
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
27
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
28
|
+
* @param {string} options.xdebug The Xdebug mode to set. Defaults to "off".
|
|
29
|
+
* @param {string} options.spx The SPX mode to set. Defaults to "off".
|
|
30
|
+
* @param {boolean} options.writeChanges If true, writes the parsed config to the
|
|
31
|
+
* required docker files like docker-compose
|
|
32
|
+
* and Dockerfile. By default, this is false
|
|
33
|
+
* and only the `start` command writes any
|
|
34
|
+
* changes.
|
|
35
|
+
* @param {string|null} options.customConfigPath Path to a custom .wp-env.json configuration file.
|
|
35
36
|
* @return {WPConfig} The-env config object.
|
|
36
37
|
*/
|
|
37
38
|
module.exports = async function initConfig( {
|
|
@@ -40,8 +41,9 @@ module.exports = async function initConfig( {
|
|
|
40
41
|
xdebug = 'off',
|
|
41
42
|
spx = 'off',
|
|
42
43
|
writeChanges = false,
|
|
44
|
+
customConfigPath = null,
|
|
43
45
|
} ) {
|
|
44
|
-
const config = await loadConfig( path.resolve( '.' ) );
|
|
46
|
+
const config = await loadConfig( path.resolve( '.' ), customConfigPath );
|
|
45
47
|
config.debug = debug;
|
|
46
48
|
|
|
47
49
|
// Adding this to the config allows the start command to understand that the
|
|
@@ -87,10 +89,16 @@ module.exports = async function initConfig( {
|
|
|
87
89
|
yaml.dump( dockerComposeConfig )
|
|
88
90
|
);
|
|
89
91
|
|
|
90
|
-
// Write
|
|
92
|
+
// Write Dockerfiles for each service we provided.
|
|
91
93
|
// (WordPress and CLI services, then a development and test environment for each.)
|
|
92
94
|
for ( const imageType of [ 'WordPress', 'CLI' ] ) {
|
|
93
95
|
for ( const envType of [ 'development', 'tests' ] ) {
|
|
96
|
+
if (
|
|
97
|
+
envType === 'tests' &&
|
|
98
|
+
config.testsEnvironment === false
|
|
99
|
+
) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
94
102
|
await writeFile(
|
|
95
103
|
path.resolve(
|
|
96
104
|
config.workDirectoryPath,
|
|
@@ -47,20 +47,6 @@ function isWPMajorMinorVersionLower( version, compareVersion ) {
|
|
|
47
47
|
return versionNumber < compareVersionNumber;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/**
|
|
51
|
-
* Checks a WordPress database connection. An error is thrown if the test is
|
|
52
|
-
* unsuccessful.
|
|
53
|
-
*
|
|
54
|
-
* @param {WPConfig} config The wp-env config object.
|
|
55
|
-
*/
|
|
56
|
-
async function checkDatabaseConnection( { dockerComposeConfigPath, debug } ) {
|
|
57
|
-
await dockerCompose.run( 'cli', 'wp db check', {
|
|
58
|
-
config: dockerComposeConfigPath,
|
|
59
|
-
commandOptions: [ '--rm' ],
|
|
60
|
-
log: debug,
|
|
61
|
-
} );
|
|
62
|
-
}
|
|
63
|
-
|
|
64
50
|
/**
|
|
65
51
|
* Configures WordPress for the given environment by installing WordPress,
|
|
66
52
|
* activating all plugins, and activating the first theme. These steps are
|
|
@@ -316,7 +302,6 @@ async function copyCoreFiles( fromPath, toPath ) {
|
|
|
316
302
|
}
|
|
317
303
|
|
|
318
304
|
module.exports = {
|
|
319
|
-
checkDatabaseConnection,
|
|
320
305
|
configureWordPress,
|
|
321
306
|
resetDatabase,
|
|
322
307
|
setupWordPressDirectories,
|
package/lib/runtime/errors.js
CHANGED
|
@@ -12,6 +12,17 @@ class UnsupportedCommandError extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when the environment has not been initialized.
|
|
17
|
+
*/
|
|
18
|
+
class EnvironmentNotInitializedError extends Error {
|
|
19
|
+
constructor() {
|
|
20
|
+
super( 'Environment not initialized. Run `wp-env start` first.' );
|
|
21
|
+
this.name = 'EnvironmentNotInitializedError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
module.exports = {
|
|
16
26
|
UnsupportedCommandError,
|
|
27
|
+
EnvironmentNotInitializedError,
|
|
17
28
|
};
|