@wordpress/env 11.0.2-next.v.202602241322.0 → 11.1.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.
@@ -0,0 +1,136 @@
1
+ 'use strict';
2
+ /**
3
+ * Internal dependencies
4
+ */
5
+ const { findAvailablePort, isPortAvailable } = require( './port-utils' );
6
+
7
+ /**
8
+ * Port definitions to resolve. Each entry maps a config path to its
9
+ * environment and property. MySQL ports are excluded because they
10
+ * already support Docker-native auto-assignment via `null`.
11
+ */
12
+ const PORT_DEFINITIONS = [
13
+ { env: 'development', property: 'port' },
14
+ { env: 'tests', property: 'port' },
15
+ { env: 'development', property: 'phpmyadminPort' },
16
+ { env: 'tests', property: 'phpmyadminPort' },
17
+ ];
18
+
19
+ /**
20
+ * Well-known preferred ports for auto-resolved HTTP port properties.
21
+ * Auto-port tries these first and then scans upward to find a free port.
22
+ */
23
+ const PREFERRED_PORTS = {
24
+ 'development.port': 8888,
25
+ 'tests.port': 8889,
26
+ };
27
+
28
+ /**
29
+ * Creates a port resolver that tracks used ports.
30
+ *
31
+ * The resolver is designed to be called during config post-processing,
32
+ * after environments have been merged but before URLs are set. This
33
+ * allows `appendPortToWPConfigs` to use the resolved ports directly.
34
+ *
35
+ * @param {Object} spinner A CLI spinner for displaying progress.
36
+ * @return {Object} A port resolver with a `resolve` method.
37
+ */
38
+ function createPortResolver( spinner ) {
39
+ const usedPorts = [];
40
+
41
+ return {
42
+ /**
43
+ * Resolves a single port, finding an alternative if it's busy.
44
+ *
45
+ * @param {number} preferredPort The preferred port to use.
46
+ * @param {string} configPath Config path for error messages (e.g. "env.development.port").
47
+ * @param {boolean} strict When true, fail if the port is busy instead of finding an alternative.
48
+ * @return {Promise<number>} The resolved port number.
49
+ */
50
+ async resolve( preferredPort, configPath, strict = false ) {
51
+ if ( spinner ) {
52
+ spinner.text = `Checking ${ configPath } availability.`;
53
+ }
54
+
55
+ // When the user set an explicit port, only use that port.
56
+ if ( strict ) {
57
+ if ( usedPorts.includes( preferredPort ) ) {
58
+ throw new Error(
59
+ `Port ${ preferredPort } (${ configPath }) conflicts with another wp-env service. ` +
60
+ `Set a different port or enable automatic port selection with --auto-port or "autoPort": true.`
61
+ );
62
+ }
63
+ const available = await isPortAvailable( preferredPort );
64
+ if ( ! available ) {
65
+ throw new Error(
66
+ `Port ${ preferredPort } (${ configPath }) is busy. ` +
67
+ `Free the port, set a different one, or enable automatic port selection with --auto-port or "autoPort": true.`
68
+ );
69
+ }
70
+ usedPorts.push( preferredPort );
71
+ return preferredPort;
72
+ }
73
+
74
+ try {
75
+ const resolvedPort = await findAvailablePort( {
76
+ preferredPort,
77
+ exclude: usedPorts,
78
+ } );
79
+
80
+ usedPorts.push( resolvedPort );
81
+
82
+ return resolvedPort;
83
+ } catch ( error ) {
84
+ throw new Error(
85
+ `Could not find available port for ${ configPath }: ${ error.message }`
86
+ );
87
+ }
88
+ },
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Resolves available ports on a config object. Iterates over the
94
+ * defined port properties and resolves each one that has a value.
95
+ *
96
+ * @param {Object} config The config object (after mergeRootToEnvironments).
97
+ * @param {Object} portResolver A port resolver created by `createPortResolver`.
98
+ * @return {Promise<Object>} The config with resolved ports.
99
+ */
100
+ async function resolveConfigPorts( config, portResolver ) {
101
+ for ( const { env, property } of PORT_DEFINITIONS ) {
102
+ const currentValue = config.env[ env ][ property ];
103
+
104
+ // Skip unconfigured ports (phpmyadminPort defaults to null
105
+ // and should stay null when not explicitly set).
106
+ if ( currentValue === undefined ) {
107
+ continue;
108
+ }
109
+
110
+ // Use a well-known preferred port when one isn't explicitly set.
111
+ // For explicit ports, use the configured value.
112
+ const key = `${ env }.${ property }`;
113
+ const preferredPort = currentValue ?? PREFERRED_PORTS[ key ];
114
+
115
+ // Still null after lookup (e.g. phpmyadminPort set to null).
116
+ if ( ! preferredPort ) {
117
+ continue;
118
+ }
119
+
120
+ // When --auto-port is active (the only time this runs),
121
+ // always auto-fallback to an available port.
122
+ const configPath = `env.${ key }`;
123
+ config.env[ env ][ property ] = await portResolver.resolve(
124
+ preferredPort,
125
+ configPath
126
+ );
127
+ }
128
+
129
+ return config;
130
+ }
131
+
132
+ module.exports = {
133
+ createPortResolver,
134
+ resolveConfigPorts,
135
+ PORT_DEFINITIONS,
136
+ };
@@ -10,7 +10,7 @@ const yaml = require( 'js-yaml' );
10
10
  /**
11
11
  * Internal dependencies
12
12
  */
13
- const { loadConfig, ValidationError } = require( '../../config' );
13
+ const { ValidationError } = require( '../../config' );
14
14
  const buildDockerComposeConfig = require( './build-docker-compose-config' );
15
15
 
16
16
  /**
@@ -18,109 +18,62 @@ const buildDockerComposeConfig = require( './build-docker-compose-config' );
18
18
  */
19
19
 
20
20
  /**
21
- * Initializes the local environment so that Docker commands can be run. Reads
22
- * ./.wp-env.json, creates ~/.wp-env, ~/.wp-env/docker-compose.yml, and
23
- * ~/.wp-env/Dockerfile.
21
+ * Writes Docker configuration files (docker-compose.yml and Dockerfiles) for
22
+ * a fully resolved config. Called only by the `start` command.
24
23
  *
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.
36
- * @return {WPConfig} The-env config object.
24
+ * The config must already have ports resolved, and `debug`, `xdebug`, and
25
+ * `spx` properties set before calling this function.
26
+ *
27
+ * @param {WPConfig} config A fully resolved wp-env config object.
28
+ * @return {WPConfig} The config object (unchanged).
37
29
  */
38
- module.exports = async function initConfig( {
39
- spinner,
40
- debug,
41
- xdebug = 'off',
42
- spx = 'off',
43
- writeChanges = false,
44
- customConfigPath = null,
45
- } ) {
46
- const config = await loadConfig( path.resolve( '.' ), customConfigPath );
47
- config.debug = debug;
48
-
49
- // Adding this to the config allows the start command to understand that the
50
- // config has changed when only the xdebug param has changed. This is needed
51
- // so that Docker will rebuild the image whenever the xdebug flag changes.
52
- config.xdebug = xdebug;
53
-
54
- // Adding this to the config allows the start command to understand that the
55
- // config has changed when only the spx param has changed. This is needed
56
- // so that Docker will rebuild the image whenever the spx flag changes.
57
- config.spx = spx;
58
-
30
+ async function writeDockerFiles( config ) {
59
31
  const dockerComposeConfig = buildDockerComposeConfig( config );
60
32
 
61
- if ( config.debug ) {
62
- spinner.info(
63
- `Config:\n${ JSON.stringify(
64
- config,
65
- null,
66
- 4
67
- ) }\n\nDocker Compose Config:\n${ JSON.stringify(
68
- dockerComposeConfig,
69
- null,
70
- 4
71
- ) }`
72
- );
73
- spinner.start();
74
- }
33
+ await mkdir( config.workDirectoryPath, { recursive: true } );
75
34
 
76
- /**
77
- * We avoid writing changes most of the time so that we can better pass params
78
- * to the start command. For example, say you start wp-env with Xdebug enabled.
79
- * If you then run another command, like opening bash in the wp instance, it
80
- * would turn off Xdebug in the Dockerfile because it wouldn't have the --xdebug
81
- * arg. This basically makes it such that wp-env start is the only command
82
- * which updates any of the Docker configuration.
83
- */
84
- if ( writeChanges ) {
85
- await mkdir( config.workDirectoryPath, { recursive: true } );
86
-
87
- await writeFile(
88
- config.dockerComposeConfigPath,
89
- yaml.dump( dockerComposeConfig )
90
- );
35
+ await writeFile(
36
+ config.dockerComposeConfigPath,
37
+ yaml.dump( dockerComposeConfig )
38
+ );
91
39
 
92
- // Write Dockerfiles for each service we provided.
93
- // (WordPress and CLI services, then a development and test environment for each.)
94
- for ( const imageType of [ 'WordPress', 'CLI' ] ) {
95
- for ( const envType of [ 'development', 'tests' ] ) {
96
- if (
97
- envType === 'tests' &&
98
- config.testsEnvironment === false
99
- ) {
100
- continue;
101
- }
102
- await writeFile(
103
- path.resolve(
104
- config.workDirectoryPath,
105
- `${
106
- envType === 'tests' ? 'Tests-' : ''
107
- }${ imageType }.Dockerfile`
108
- ),
109
- imageType === 'WordPress'
110
- ? wordpressDockerFileContents( envType, config )
111
- : cliDockerFileContents( envType, config )
112
- );
113
- }
40
+ // Write four Dockerfiles for each service we provided.
41
+ // (WordPress and CLI services, then a development and test environment for each.)
42
+ for ( const imageType of [ 'WordPress', 'CLI' ] ) {
43
+ for ( const envType of [ 'development', 'tests' ] ) {
44
+ await writeFile(
45
+ path.resolve(
46
+ config.workDirectoryPath,
47
+ `${
48
+ envType === 'tests' ? 'Tests-' : ''
49
+ }${ imageType }.Dockerfile`
50
+ ),
51
+ imageType === 'WordPress'
52
+ ? wordpressDockerFileContents( envType, config )
53
+ : cliDockerFileContents( envType, config )
54
+ );
114
55
  }
115
- } else if ( ! existsSync( config.workDirectoryPath ) ) {
56
+ }
57
+
58
+ return config;
59
+ }
60
+
61
+ /**
62
+ * Verifies that the Docker environment has been initialized (i.e. `wp-env
63
+ * start` has been run at least once). Exits with an error message when the
64
+ * work directory does not exist.
65
+ *
66
+ * @param {WPConfig} config The wp-env config object.
67
+ * @param {Object} spinner A CLI spinner which indicates progress.
68
+ */
69
+ function ensureDockerInitialized( config, spinner ) {
70
+ if ( ! existsSync( config.workDirectoryPath ) ) {
116
71
  spinner.fail(
117
72
  'wp-env has not yet been initialized. Please run `wp-env start` to install the WordPress instance before using any other commands. This is only necessary to set up the environment for the first time; it is typically not necessary for the instance to be running after that in order to use other commands.'
118
73
  );
119
74
  process.exit( 1 );
120
75
  }
121
-
122
- return config;
123
- };
76
+ }
124
77
 
125
78
  /**
126
79
  * Generates the Dockerfile used by wp-env's `wordpress` and `tests-wordpress` instances.
@@ -377,3 +330,8 @@ RUN echo 'spx.http_ip_whitelist="*"' >> /usr/local/etc/php/php.ini
377
330
  RUN echo 'spx.data_dir="/tmp/spx"' >> /usr/local/etc/php/php.ini
378
331
  RUN mkdir -p /tmp/spx && chmod 777 /tmp/spx`;
379
332
  }
333
+
334
+ module.exports = {
335
+ writeDockerFiles,
336
+ ensureDockerInitialized,
337
+ };
@@ -16,7 +16,10 @@ const exec = util.promisify( require( 'child_process' ).exec );
16
16
  /**
17
17
  * Internal dependencies
18
18
  */
19
- const initConfig = require( './init-config' );
19
+ const {
20
+ writeDockerFiles,
21
+ ensureDockerInitialized,
22
+ } = require( './docker-config' );
20
23
  const getHostUser = require( './get-host-user' );
21
24
  const downloadSources = require( './download-sources' );
22
25
  const downloadWPPHPUnit = require( './download-wp-phpunit' );
@@ -94,23 +97,15 @@ class DockerRuntime {
94
97
  * @param {Object} options Start options.
95
98
  * @param {Object} options.spinner A CLI spinner which indicates progress.
96
99
  * @param {boolean} options.update If true, update sources.
97
- * @param {string} options.xdebug The Xdebug mode to set.
98
- * @param {string} options.spx The SPX mode to set.
99
- * @param {boolean} options.debug True if debug mode is enabled.
100
100
  * @return {Promise<Object>} Result object with message and siteUrl.
101
101
  */
102
- async start( config, { spinner, update, xdebug, spx, debug } ) {
103
- // Initialize Docker-specific files (docker-compose.yml, Dockerfiles)
104
- const fullConfig = await initConfig( {
105
- spinner,
106
- debug,
107
- xdebug,
108
- spx,
109
- writeChanges: true,
110
- customConfigPath: config.customConfigPath,
111
- } );
102
+ async start( config, { spinner, update } ) {
103
+ // Write Docker-specific files (docker-compose.yml, Dockerfiles).
104
+ // The config already has ports resolved and xdebug/spx set by start.js.
105
+ const fullConfig = await writeDockerFiles( config );
106
+ const debug = fullConfig.debug;
112
107
 
113
- const testsEnabled = fullConfig.testsEnvironment !== false;
108
+ const testsEnabled = config.testsEnvironment !== false;
114
109
 
115
110
  // Check if the hash of the config has changed. If so, run configuration.
116
111
  const configHash = md5( fullConfig );
@@ -404,16 +399,12 @@ class DockerRuntime {
404
399
  * @param {boolean} options.debug True if debug mode is enabled.
405
400
  */
406
401
  async stop( config, { spinner, debug } ) {
407
- const { dockerComposeConfigPath } = await initConfig( {
408
- spinner,
409
- debug,
410
- customConfigPath: config.customConfigPath,
411
- } );
402
+ ensureDockerInitialized( config, spinner );
412
403
 
413
404
  spinner.text = 'Stopping WordPress.';
414
405
 
415
406
  await dockerCompose.down( {
416
- config: dockerComposeConfigPath,
407
+ config: config.dockerComposeConfigPath,
417
408
  log: debug,
418
409
  } );
419
410
 
@@ -485,13 +476,9 @@ class DockerRuntime {
485
476
  * @param {boolean} options.debug True if debug mode is enabled.
486
477
  */
487
478
  async clean( config, { environment, spinner, debug } ) {
488
- const fullConfig = await initConfig( {
489
- spinner,
490
- debug,
491
- customConfigPath: config.customConfigPath,
492
- } );
479
+ ensureDockerInitialized( config, spinner );
493
480
 
494
- const testsEnabled = fullConfig.testsEnvironment !== false;
481
+ const testsEnabled = config.testsEnvironment !== false;
495
482
 
496
483
  if ( ! testsEnabled && environment === 'tests' ) {
497
484
  throw new Error(
@@ -522,16 +509,14 @@ class DockerRuntime {
522
509
  }
523
510
 
524
511
  await dockerCompose.upMany( mysqlServices, {
525
- config: fullConfig.dockerComposeConfigPath,
526
- log: fullConfig.debug,
512
+ config: config.dockerComposeConfigPath,
513
+ log: debug,
527
514
  } );
528
515
 
529
516
  if ( environment === 'all' || environment === 'development' ) {
530
517
  tasks.push(
531
- resetDatabase( 'development', fullConfig )
532
- .then( () =>
533
- configureWordPress( 'development', fullConfig )
534
- )
518
+ resetDatabase( 'development', config )
519
+ .then( () => configureWordPress( 'development', config ) )
535
520
  .catch( () => {} )
536
521
  );
537
522
  }
@@ -541,8 +526,8 @@ class DockerRuntime {
541
526
  ( environment === 'all' || environment === 'tests' )
542
527
  ) {
543
528
  tasks.push(
544
- resetDatabase( 'tests', fullConfig )
545
- .then( () => configureWordPress( 'tests', fullConfig ) )
529
+ resetDatabase( 'tests', config )
530
+ .then( () => configureWordPress( 'tests', config ) )
546
531
  .catch( () => {} )
547
532
  );
548
533
  }
@@ -570,9 +555,8 @@ class DockerRuntime {
570
555
  * @param {string[]} options.command The command to run.
571
556
  * @param {string} options.envCwd The working directory.
572
557
  * @param {Object} options.spinner A CLI spinner which indicates progress.
573
- * @param {boolean} options.debug True if debug mode is enabled.
574
558
  */
575
- async run( config, { container, command, envCwd, spinner, debug } ) {
559
+ async run( config, { container, command, envCwd, spinner } ) {
576
560
  // Validate the container name (throws for deprecated containers)
577
561
  validateRunContainer( container );
578
562
 
@@ -585,22 +569,13 @@ class DockerRuntime {
585
569
  );
586
570
  }
587
571
 
588
- const fullConfig = await initConfig( {
589
- spinner,
590
- debug,
591
- customConfigPath: config.customConfigPath,
592
- } );
572
+ ensureDockerInitialized( config, spinner );
593
573
 
594
574
  // Shows a contextual tip for the given command.
595
575
  const joinedCommand = command.join( ' ' );
596
576
  this._showCommandTips( joinedCommand, container, spinner );
597
577
 
598
- await this._spawnCommandDirectly(
599
- fullConfig,
600
- container,
601
- command,
602
- envCwd
603
- );
578
+ await this._spawnCommandDirectly( config, container, command, envCwd );
604
579
 
605
580
  spinner.text = `Ran \`${ joinedCommand }\` in '${ container }'.`;
606
581
  }
@@ -613,16 +588,11 @@ class DockerRuntime {
613
588
  * @param {string} options.environment The environment to show logs for.
614
589
  * @param {boolean} options.watch If true, follow along with log output.
615
590
  * @param {Object} options.spinner A CLI spinner which indicates progress.
616
- * @param {boolean} options.debug True if debug mode is enabled.
617
591
  */
618
- async logs( config, { environment, watch, spinner, debug } ) {
619
- const fullConfig = await initConfig( {
620
- spinner,
621
- debug,
622
- customConfigPath: config.customConfigPath,
623
- } );
592
+ async logs( config, { environment, watch, spinner } ) {
593
+ ensureDockerInitialized( config, spinner );
624
594
 
625
- const testsEnabled = fullConfig.testsEnvironment !== false;
595
+ const testsEnabled = config.testsEnvironment !== false;
626
596
 
627
597
  if ( ! testsEnabled && environment === 'tests' ) {
628
598
  throw new Error(
@@ -651,7 +621,7 @@ class DockerRuntime {
651
621
  const output = await Promise.all( [
652
622
  ...servicesToWatch.map( ( service ) =>
653
623
  dockerCompose.logs( service, {
654
- config: fullConfig.dockerComposeConfigPath,
624
+ config: config.dockerComposeConfigPath,
655
625
  log: watch, // Must log inline if we are watching the log output.
656
626
  commandOptions: watch ? [ '--follow' ] : [],
657
627
  } )
@@ -703,18 +673,17 @@ class DockerRuntime {
703
673
  async getStatus( config, { spinner, debug } ) {
704
674
  spinner.text = 'Getting environment status.';
705
675
 
706
- const fullConfig = await initConfig( {
707
- spinner,
708
- debug,
709
- customConfigPath: config.customConfigPath,
710
- } );
676
+ ensureDockerInitialized( config, spinner );
677
+
711
678
  const dockerComposeConfig = {
712
- config: fullConfig.dockerComposeConfigPath,
679
+ config: config.dockerComposeConfigPath,
713
680
  log: debug,
714
681
  };
715
682
 
716
683
  // Check if containers are running by trying to get a port.
717
684
  let isRunning = false;
685
+ let developmentPort = null;
686
+ let testsPort = null;
718
687
  let mySQLPort = null;
719
688
  let phpmyadminPort = null;
720
689
 
@@ -726,7 +695,19 @@ class DockerRuntime {
726
695
  );
727
696
  isRunning = true;
728
697
 
729
- if ( fullConfig.env.development.phpmyadmin ) {
698
+ developmentPort = await this._getPublicDockerPort(
699
+ 'wordpress',
700
+ 80,
701
+ dockerComposeConfig
702
+ );
703
+
704
+ testsPort = await this._getPublicDockerPort(
705
+ 'tests-wordpress',
706
+ 80,
707
+ dockerComposeConfig
708
+ );
709
+
710
+ if ( config.env.development.phpmyadmin ) {
730
711
  phpmyadminPort = await this._getPublicDockerPort(
731
712
  'phpmyadmin',
732
713
  80,
@@ -737,9 +718,9 @@ class DockerRuntime {
737
718
  // Containers are not running.
738
719
  }
739
720
 
740
- const siteUrl = fullConfig.env.development.config.WP_SITEURL;
721
+ const siteUrl = config.env.development.config.WP_SITEURL;
741
722
 
742
- const testsEnabled = fullConfig.testsEnvironment !== false;
723
+ const testsEnabled = config.testsEnvironment !== false;
743
724
 
744
725
  return {
745
726
  status: isRunning ? 'running' : 'stopped',
@@ -752,18 +733,18 @@ class DockerRuntime {
752
733
  : null,
753
734
  },
754
735
  ports: {
755
- development: fullConfig.env.development.port,
736
+ development: developmentPort,
756
737
  ...( testsEnabled && {
757
- tests: fullConfig.env.tests.port,
738
+ tests: testsPort,
758
739
  } ),
759
740
  mysql: mySQLPort,
760
741
  },
761
742
  config: {
762
- multisite: fullConfig.env.development.multisite,
763
- xdebug: fullConfig.xdebug || 'off',
743
+ multisite: config.env.development.multisite,
744
+ xdebug: config.xdebug || 'off',
764
745
  },
765
- configPath: fullConfig.configDirectoryPath,
766
- installPath: fullConfig.workDirectoryPath,
746
+ configPath: config.configDirectoryPath,
747
+ installPath: config.workDirectoryPath,
767
748
  };
768
749
  }
769
750
 
@@ -87,13 +87,11 @@ class PlaygroundRuntime {
87
87
  /**
88
88
  * Start the WordPress Playground environment.
89
89
  *
90
- * @param {Object} config The wp-env config object.
91
- * @param {Object} options Start options.
92
- * @param {Object} options.spinner A CLI spinner which indicates progress.
93
- * @param {boolean} options.debug True if debug mode is enabled.
94
- * @param {string} options.xdebug The Xdebug mode to set.
90
+ * @param {Object} config The wp-env config object.
91
+ * @param {Object} options Start options.
92
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
95
93
  */
96
- async start( config, { spinner, debug, xdebug } ) {
94
+ async start( config, { spinner } ) {
97
95
  const envConfig = config.env.development;
98
96
 
99
97
  spinner.text = 'Starting WordPress Playground.';
@@ -127,7 +125,7 @@ class PlaygroundRuntime {
127
125
  downloadSource( source, {
128
126
  onProgress: () => {}, // Progress tracking could be added
129
127
  spinner,
130
- debug,
128
+ debug: config.debug,
131
129
  } )
132
130
  )
133
131
  );
@@ -148,7 +146,6 @@ class PlaygroundRuntime {
148
146
  // Get mount arguments
149
147
  const mountArgs = getMountArgs( config );
150
148
 
151
- // Determine port
152
149
  const port = envConfig.port || 8888;
153
150
  const phpVersion = envConfig.phpVersion || '8.2';
154
151
 
@@ -166,7 +163,7 @@ class PlaygroundRuntime {
166
163
  ...mountArgs,
167
164
  ];
168
165
 
169
- if ( debug ) {
166
+ if ( config.debug ) {
170
167
  cliArgs.push( '--verbosity', 'debug' );
171
168
  }
172
169
 
@@ -174,7 +171,7 @@ class PlaygroundRuntime {
174
171
  cliArgs.push( '--phpmyadmin' );
175
172
  }
176
173
 
177
- if ( xdebug ) {
174
+ if ( config.xdebug && config.xdebug !== 'off' ) {
178
175
  cliArgs.push( '--xdebug' );
179
176
  }
180
177
 
@@ -425,17 +422,16 @@ class PlaygroundRuntime {
425
422
  /**
426
423
  * Reset the WordPress database.
427
424
  *
428
- * @param {Object} config The wp-env config object.
429
- * @param {Object} options Reset options.
430
- * @param {Object} options.spinner A CLI spinner which indicates progress.
431
- * @param {boolean} options.debug True if debug mode is enabled.
425
+ * @param {Object} config The wp-env config object.
426
+ * @param {Object} options Reset options.
427
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
432
428
  */
433
- async clean( config, { spinner, debug } ) {
429
+ async clean( config, { spinner } ) {
434
430
  spinner.text = 'Resetting WordPress Playground environment.';
435
431
 
436
432
  // For Playground, we restart the server to reset the database
437
433
  await this.stop( config, { spinner } );
438
- await this.start( config, { spinner, debug } );
434
+ await this.start( config, { spinner } );
439
435
 
440
436
  spinner.text = 'Reset WordPress Playground environment.';
441
437
  }
package/lib/test/cli.js CHANGED
@@ -34,8 +34,21 @@ describe( 'env cli', () => {
34
34
 
35
35
  it( 'parses start commands.', () => {
36
36
  cli().parse( [ 'start' ] );
37
- const { spinner } = env.start.mock.calls[ 0 ][ 0 ];
37
+ const { spinner, autoPort } = env.start.mock.calls[ 0 ][ 0 ];
38
38
  expect( spinner.text ).toBe( '' );
39
+ expect( autoPort ).toBeUndefined();
40
+ } );
41
+
42
+ it( 'parses start commands with --auto-port.', () => {
43
+ cli().parse( [ 'start', '--auto-port' ] );
44
+ const { autoPort } = env.start.mock.calls[ 0 ][ 0 ];
45
+ expect( autoPort ).toBe( true );
46
+ } );
47
+
48
+ it( 'parses start commands with --no-auto-port.', () => {
49
+ cli().parse( [ 'start', '--no-auto-port' ] );
50
+ const { autoPort } = env.start.mock.calls[ 0 ][ 0 ];
51
+ expect( autoPort ).toBe( false );
39
52
  } );
40
53
 
41
54
  it( 'parses stop commands.', () => {