@wordpress/env 4.7.0 → 5.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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 5.0.0 (2022-07-27)
6
+
7
+ ### Breaking Changes
8
+ - Removed the `WP_PHPUNIT__TESTS_CONFIG` environment variable from the `phpunit` container. **This removes automatic support for the `wp-phpunit/wp-phpunit` Composer package. To continue using the package, set the following two environment variables in your `phpunit.xml` file or similar: `WP_TESTS_DIR=""` and `WP_PHPUNIT__TESTS_CONFIG="/wordpress-phpunit/wp-tests-config.php"`.**
9
+ - Removed the generated `/var/www/html/phpunit-wp-config.php` file from the environment.
10
+
11
+ ### Enhancement
12
+ - Read WordPress' version and include the corresponding PHPUnit test files in the environment.
13
+ - Set the `WP_TESTS_DIR` environment variable in all containers to point at the PHPUnit test files.
14
+
15
+ ### Bug Fix
16
+ - Restrict `WP_TESTS_DOMAIN` constant to just hostname rather than an entire URL (e.g. it now excludes scheme, port, etc.) ([#41039](https://github.com/WordPress/gutenberg/pull/41039)).
17
+
18
+ ## 4.8.0 (2022-06-01)
19
+
20
+ ### Enhancement
21
+ - Removed the need for quotation marks when passing options to `wp-env run`.
22
+ - Setting a `config` key to `null` will prevent adding the constant to `wp-config.php` even if a default value is defined by `wp-env`.
23
+
5
24
  ## 4.7.0 (2022-05-18)
6
25
 
7
26
  ### Enhancement
package/README.md CHANGED
@@ -188,6 +188,14 @@ wp-env start --debug
188
188
  ...
189
189
  ```
190
190
 
191
+ ## Using included WordPress PHPUnit test files
192
+
193
+ Out of the box `wp-env` includes the [WordPress' PHPUnit test files](https://develop.svn.wordpress.org/trunk/tests/phpunit/) corresponding to the version of WordPress installed. There is an environment variable, `WP_TESTS_DIR`, which points to the location of these files within each container. By including these files in the environment, we remove the need for you to use a package or install and mount them yourself. If you do not want to use these files, you should ignore the `WP_TESTS_DIR` environment variable and load them from the location of your choosing.
194
+
195
+ ### Customizing the `wp-tests-config.php` file
196
+
197
+ While we do provide a default `wp-tests-config.php` file within the environment, there may be cases where you want to use your own. WordPress provides a `WP_TESTS_CONFIG_FILE_PATH` constant that you can use to change the `wp-config.php` file used for testing. Set this to a desired path in your `bootstrap.php` file and the file you've chosen will be used instead of the one included in the environment.
198
+
191
199
  ## Using Xdebug
192
200
 
193
201
  Xdebug is installed in the wp-env environment, but it is turned off by default. To enable Xdebug, you can use the `--xdebug` flag with the `wp-env start` command. Here is a reference to how the flag works:
@@ -300,21 +308,23 @@ Positionals:
300
308
  The run command can be used to open shell sessions or invoke WP-CLI commands.
301
309
 
302
310
  <div class="callout callout-alert">
303
- To run a WP-CLI command that includes optional arguments, enclose the WP-CLI command in quotation marks; otherwise, the optional arguments are ignored. This is because flags are normally passed to `wp-env` itself, meaning that the flags are not considered part of the argument that specifies the WP-CLI command. With quotation marks, `wp-env` considers everything inside quotation marks the WP-CLI command argument.
311
+ In some cases, `wp-env` may consume options that you are attempting to pass to
312
+ the container. This happens with options that `wp-env` has already declared,
313
+ such as `--debug`, `--help`, and `--version`. When this happens, you should fall
314
+ back to using quotation marks; `wp-env` considers everything inside the
315
+ quotation marks to be command argument.
304
316
 
305
- For example, to list cron schedules with optional arguments that specify the fields returned and the format of the output:
317
+ For example, to ask `WP-CLI` for its help text:
306
318
 
307
319
  ```sh
308
- wp-env run cli "wp cron schedule list --fields=name --format=csv"
320
+ wp-env run cli "wp --help"
309
321
  ```
310
322
 
311
- Without the quotation marks, WP-CLI lists the schedule in its default format, ignoring the `fields` and `format` arguments.
323
+ Without the quotation marks, `wp-env` will print its own help text instead of
324
+ passing it to the container. If you experience any problems where the command
325
+ is not being passed correctly, fall back to using quotation marks.
312
326
  </div>
313
327
 
314
- Note that quotation marks are not required for a WP-CLI command that excludes optional arguments, although it does not hurt to include them. For example, the following command syntaxes return identical results: `wp-env run cli "wp cron schedule list"` or `wp-env run cli wp cron schedule list`.
315
-
316
- For more information about all the available commands, see [WP-CLI Commands](https://developer.wordpress.org/cli/commands/).
317
-
318
328
  ```sh
319
329
  wp-env run <container> [command..]
320
330
 
@@ -323,11 +333,7 @@ Runs an arbitrary command in one of the underlying Docker containers. The
323
333
  "development", "tests", or "cli". To run a wp-cli command, use the "cli" or
324
334
  "tests-cli" service. You can also use this command to open shell sessions like
325
335
  bash and the WordPress shell in the WordPress instance. For example, `wp-env run
326
- cli bash` will open bash in the development WordPress instance. When using long
327
- commands with arguments and quotation marks, you need to wrap the "command"
328
- param in quotation marks. For example: `wp-env run tests-cli "wp post create
329
- --post_type=page --post_title='Test'"` will create a post on the tests WordPress
330
- instance.
336
+ cli bash` will open bash in the development WordPress instance.
331
337
 
332
338
  Positionals:
333
339
  container The container to run the command on. [string] [required]
@@ -464,7 +470,7 @@ Several types of strings can be passed into the `core`, `plugins`, `themes`, and
464
470
  | ----------------- | -------------------------------------------- | -------------------------------------------------------- |
465
471
  | Relative path | `.<path>\|~<path>` | `"./a/directory"`, `"../a/directory"`, `"~/a/directory"` |
466
472
  | Absolute path | `/<path>\|<letter>:\<path>` | `"/a/directory"`, `"C:\\a\\directory"` |
467
- | GitHub repository | `<owner>/<repo>[#<ref>]` | `"WordPress/WordPress"`, `"WordPress/gutenberg#trunk"` |
473
+ | GitHub repository | `<owner>/<repo>[#<ref>]` | `"WordPress/WordPress"`, `"WordPress/gutenberg#trunk"`, if no branch is provided wp-env will fall back to the repos default branch |
468
474
  | SSH repository | `ssh://user@host/<owner>/<repo>.git[#<ref>]` | `"ssh://git@github.com/WordPress/WordPress.git"` |
469
475
  | ZIP File | `http[s]://<host>/<path>.zip` | `"https://wordpress.org/wordpress-5.4-beta2.zip"` |
470
476
 
@@ -513,13 +519,15 @@ SCRIPT_DEBUG: true,
513
519
  WP_PHP_BINARY: 'php',
514
520
  WP_TESTS_EMAIL: 'admin@example.org',
515
521
  WP_TESTS_TITLE: 'Test Blog',
516
- WP_TESTS_DOMAIN: 'http://localhost',
522
+ WP_TESTS_DOMAIN: 'localhost',
517
523
  WP_SITEURL: 'http://localhost',
518
524
  WP_HOME: 'http://localhost',
519
525
  ```
520
526
 
521
527
  On the test instance, all of the above are still defined, but `WP_DEBUG` and `SCRIPT_DEBUG` are set to false.
522
528
 
529
+ These can be overridden by setting a value within the `config` configuration. Setting it to `null` will prevent the constant being defined entirely.
530
+
523
531
  Additionally, the values referencing a URL include the specified port for the given environment. So if you set `testsPort: 3000, port: 2000`, `WP_HOME` (for example) will be `http://localhost:3000` on the tests instance and `http://localhost:2000` on the development instance.
524
532
 
525
533
  ### Examples
@@ -19,13 +19,18 @@ const { dbEnv } = require( './config' );
19
19
  /**
20
20
  * Gets the volume mounts for an individual service.
21
21
  *
22
- * @param {WPServiceConfig} config The service config to get the mounts from.
23
- * @param {string} wordpressDefault The default internal path for the WordPress
24
- * source code (such as tests-wordpress).
22
+ * @param {string} workDirectoryPath The working directory for wp-env.
23
+ * @param {WPServiceConfig} config The service config to get the mounts from.
24
+ * @param {string} wordpressDefault The default internal path for the WordPress
25
+ * source code (such as tests-wordpress).
25
26
  *
26
27
  * @return {string[]} An array of volumes to mount in string format.
27
28
  */
28
- function getMounts( config, wordpressDefault = 'wordpress' ) {
29
+ function getMounts(
30
+ workDirectoryPath,
31
+ config,
32
+ wordpressDefault = 'wordpress'
33
+ ) {
29
34
  // Top-level WordPress directory mounts (like wp-content/themes)
30
35
  const directoryMounts = Object.entries( config.mappings ).map(
31
36
  ( [ wpDir, source ] ) => `${ source.path }:/var/www/html/${ wpDir }`
@@ -45,9 +50,19 @@ function getMounts( config, wordpressDefault = 'wordpress' ) {
45
50
  config.coreSource ? config.coreSource.path : wordpressDefault
46
51
  }:/var/www/html`;
47
52
 
53
+ const corePHPUnitMount = `${ path.join(
54
+ workDirectoryPath,
55
+ wordpressDefault === 'wordpress'
56
+ ? 'WordPress-PHPUnit'
57
+ : 'tests-WordPress-PHPUnit',
58
+ 'tests',
59
+ 'phpunit'
60
+ ) }:/wordpress-phpunit`;
61
+
48
62
  return [
49
63
  ...new Set( [
50
64
  coreMount,
65
+ corePHPUnitMount,
51
66
  ...directoryMounts,
52
67
  ...pluginMounts,
53
68
  ...themeMounts,
@@ -64,8 +79,15 @@ function getMounts( config, wordpressDefault = 'wordpress' ) {
64
79
  * @return {Object} A docker-compose config object, ready to serialize into YAML.
65
80
  */
66
81
  module.exports = function buildDockerComposeConfig( config ) {
67
- const developmentMounts = getMounts( config.env.development );
68
- const testsMounts = getMounts( config.env.tests, 'tests-wordpress' );
82
+ const developmentMounts = getMounts(
83
+ config.workDirectoryPath,
84
+ config.env.development
85
+ );
86
+ const testsMounts = getMounts(
87
+ config.workDirectoryPath,
88
+ config.env.tests,
89
+ 'tests-wordpress'
90
+ );
69
91
 
70
92
  // When both tests and development reference the same WP source, we need to
71
93
  // ensure that tests pulls from a copy of the files so that it maintains
@@ -208,6 +230,7 @@ module.exports = function buildDockerComposeConfig( config ) {
208
230
  environment: {
209
231
  ...dbEnv.credentials,
210
232
  ...dbEnv.development,
233
+ WP_TESTS_DIR: '/wordpress-phpunit',
211
234
  },
212
235
  volumes: developmentMounts,
213
236
  },
@@ -218,6 +241,7 @@ module.exports = function buildDockerComposeConfig( config ) {
218
241
  environment: {
219
242
  ...dbEnv.credentials,
220
243
  ...dbEnv.tests,
244
+ WP_TESTS_DIR: '/wordpress-phpunit',
221
245
  },
222
246
  volumes: testsMounts,
223
247
  },
@@ -229,6 +253,7 @@ module.exports = function buildDockerComposeConfig( config ) {
229
253
  environment: {
230
254
  ...dbEnv.credentials,
231
255
  ...dbEnv.development,
256
+ WP_TESTS_DIR: '/wordpress-phpunit',
232
257
  },
233
258
  },
234
259
  'tests-cli': {
@@ -239,6 +264,7 @@ module.exports = function buildDockerComposeConfig( config ) {
239
264
  environment: {
240
265
  ...dbEnv.credentials,
241
266
  ...dbEnv.tests,
267
+ WP_TESTS_DIR: '/wordpress-phpunit',
242
268
  },
243
269
  },
244
270
  composer: {
@@ -256,8 +282,7 @@ module.exports = function buildDockerComposeConfig( config ) {
256
282
  ],
257
283
  environment: {
258
284
  LOCAL_DIR: 'html',
259
- WP_PHPUNIT__TESTS_CONFIG:
260
- '/var/www/html/phpunit-wp-config.php',
285
+ WP_TESTS_DIR: '/wordpress-phpunit',
261
286
  ...dbEnv.credentials,
262
287
  ...dbEnv.tests,
263
288
  },
package/lib/cli.js CHANGED
@@ -22,57 +22,61 @@ const wpRed = boldWhite.bgHex( '#d94f4f' );
22
22
  const wpYellow = boldWhite.bgHex( '#f0b849' );
23
23
 
24
24
  // Spinner.
25
- const withSpinner = ( command ) => ( ...args ) => {
26
- const spinner = ora().start();
27
- args[ 0 ].spinner = spinner;
28
- let time = process.hrtime();
29
- return command( ...args ).then(
30
- ( message ) => {
31
- time = process.hrtime( time );
32
- spinner.succeed(
33
- `${ message || spinner.text } (in ${ time[ 0 ] }s ${ (
34
- time[ 1 ] / 1e6
35
- ).toFixed( 0 ) }ms)`
36
- );
37
- process.exit( 0 );
38
- },
39
- ( error ) => {
40
- if ( error instanceof env.ValidationError ) {
41
- // Error is a validation error. That means the user did something wrong.
42
- spinner.fail( error.message );
43
- process.exit( 1 );
44
- } else if (
45
- error &&
46
- typeof error === 'object' &&
47
- 'exitCode' in error &&
48
- 'err' in error &&
49
- 'out' in error
50
- ) {
51
- // Error is a docker-compose error. That means something docker-related failed.
52
- // https://github.com/PDMLab/docker-compose/blob/HEAD/src/index.ts
53
- spinner.fail( 'Error while running docker-compose command.' );
54
- if ( error.out ) {
55
- process.stdout.write( error.out );
56
- }
57
- if ( error.err ) {
58
- process.stderr.write( error.err );
59
- }
60
- process.exit( error.exitCode );
61
- } else if ( error ) {
62
- // Error is an unknown error. That means there was a bug in our code.
63
- spinner.fail(
64
- typeof error === 'string' ? error : error.message
25
+ const withSpinner =
26
+ ( command ) =>
27
+ ( ...args ) => {
28
+ const spinner = ora().start();
29
+ args[ 0 ].spinner = spinner;
30
+ let time = process.hrtime();
31
+ return command( ...args ).then(
32
+ ( message ) => {
33
+ time = process.hrtime( time );
34
+ spinner.succeed(
35
+ `${ message || spinner.text } (in ${ time[ 0 ] }s ${ (
36
+ time[ 1 ] / 1e6
37
+ ).toFixed( 0 ) }ms)`
65
38
  );
66
- // Disable reason: Using console.error() means we get a stack trace.
67
- console.error( error );
68
- process.exit( 1 );
69
- } else {
70
- spinner.fail( 'An unknown error occured.' );
71
- process.exit( 1 );
39
+ process.exit( 0 );
40
+ },
41
+ ( error ) => {
42
+ if ( error instanceof env.ValidationError ) {
43
+ // Error is a validation error. That means the user did something wrong.
44
+ spinner.fail( error.message );
45
+ process.exit( 1 );
46
+ } else if (
47
+ error &&
48
+ typeof error === 'object' &&
49
+ 'exitCode' in error &&
50
+ 'err' in error &&
51
+ 'out' in error
52
+ ) {
53
+ // Error is a docker-compose error. That means something docker-related failed.
54
+ // https://github.com/PDMLab/docker-compose/blob/HEAD/src/index.ts
55
+ spinner.fail(
56
+ 'Error while running docker-compose command.'
57
+ );
58
+ if ( error.out ) {
59
+ process.stdout.write( error.out );
60
+ }
61
+ if ( error.err ) {
62
+ process.stderr.write( error.err );
63
+ }
64
+ process.exit( error.exitCode );
65
+ } else if ( error ) {
66
+ // Error is an unknown error. That means there was a bug in our code.
67
+ spinner.fail(
68
+ typeof error === 'string' ? error : error.message
69
+ );
70
+ // Disable reason: Using console.error() means we get a stack trace.
71
+ console.error( error );
72
+ process.exit( 1 );
73
+ } else {
74
+ spinner.fail( 'An unknown error occured.' );
75
+ process.exit( 1 );
76
+ }
72
77
  }
73
- }
74
- );
75
- };
78
+ );
79
+ };
76
80
 
77
81
  module.exports = function cli() {
78
82
  // Do nothing if Docker is unavailable.
@@ -92,6 +96,10 @@ module.exports = function cli() {
92
96
  default: false,
93
97
  } );
94
98
 
99
+ // Make sure any unknown arguments are passed to the command as arguments.
100
+ // This allows options to be passed to "run" without being quoted.
101
+ yargs.parserConfiguration( { 'unknown-options-as-args': true } );
102
+
95
103
  yargs.command(
96
104
  'start',
97
105
  wpGreen(
@@ -171,7 +179,7 @@ module.exports = function cli() {
171
179
  describe: 'The container to run the command on.',
172
180
  } );
173
181
  args.positional( 'command', {
174
- type: 'string',
182
+ type: 'array',
175
183
  describe: 'The command to run.',
176
184
  } );
177
185
  },
@@ -189,6 +197,7 @@ module.exports = function cli() {
189
197
  '$0 run tests-cli bash',
190
198
  'Open a bash session in the WordPress tests instance.'
191
199
  );
200
+
192
201
  yargs.command(
193
202
  'destroy',
194
203
  wpRed(
@@ -9,7 +9,7 @@ const { spawn } = require( 'child_process' );
9
9
  const initConfig = require( '../init-config' );
10
10
 
11
11
  /**
12
- * @typedef {import('../config').Config} Config
12
+ * @typedef {import('../config').WPConfig} WPConfig
13
13
  */
14
14
 
15
15
  /**
@@ -42,11 +42,11 @@ module.exports = async function run( { container, command, spinner, debug } ) {
42
42
  /**
43
43
  * Runs an arbitrary command on the given Docker container.
44
44
  *
45
- * @param {Object} options
46
- * @param {string} options.container The Docker container to run the command on.
47
- * @param {string} options.command The command to run.
48
- * @param {Config} options.config The wp-env configuration.
49
- * @param {Object} options.spinner A CLI spinner which indicates progress.
45
+ * @param {Object} options
46
+ * @param {string} options.container The Docker container to run the command on.
47
+ * @param {string} options.command The command to run.
48
+ * @param {WPConfig} options.config The wp-env configuration.
49
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
50
50
  */
51
51
  function spawnCommandDirectly( { container, command, config, spinner } ) {
52
52
  const composeCommand = [
@@ -21,16 +21,18 @@ const retry = require( '../retry' );
21
21
  const stop = require( './stop' );
22
22
  const initConfig = require( '../init-config' );
23
23
  const downloadSources = require( '../download-sources' );
24
+ const downloadWPPHPUnit = require( '../download-wp-phpunit' );
24
25
  const {
25
26
  checkDatabaseConnection,
26
27
  configureWordPress,
27
28
  setupWordPressDirectories,
29
+ readWordPressVersion,
28
30
  } = require( '../wordpress' );
29
31
  const { didCacheChange, setCache } = require( '../cache' );
30
32
  const md5 = require( '../md5' );
31
33
 
32
34
  /**
33
- * @typedef {import('../config').Config} Config
35
+ * @typedef {import('../config').WPConfig} WPConfig
34
36
  */
35
37
  const CONFIG_CACHE_KEY = 'config_checksum';
36
38
 
@@ -127,7 +129,25 @@ module.exports = async function start( { spinner, debug, update, xdebug } ) {
127
129
  ] );
128
130
 
129
131
  if ( shouldConfigureWp ) {
132
+ spinner.text = 'Setting up WordPress directories';
133
+
130
134
  await setupWordPressDirectories( config );
135
+
136
+ // Use the WordPress versions to download the PHPUnit suite.
137
+ const wpVersions = await Promise.all( [
138
+ readWordPressVersion(
139
+ config.env.development.coreSource,
140
+ spinner,
141
+ debug
142
+ ),
143
+ readWordPressVersion( config.env.tests.coreSource, spinner, debug ),
144
+ ] );
145
+ await downloadWPPHPUnit(
146
+ config,
147
+ { development: wpVersions[ 0 ], tests: wpVersions[ 1 ] },
148
+ spinner,
149
+ debug
150
+ );
131
151
  }
132
152
 
133
153
  spinner.text = 'Starting WordPress.';
@@ -173,7 +193,7 @@ module.exports = async function start( { spinner, debug, update, xdebug } ) {
173
193
  }
174
194
 
175
195
  const siteUrl = config.env.development.config.WP_SITEURL;
176
- const e2eSiteUrl = config.env.tests.config.WP_TESTS_DOMAIN;
196
+ const e2eSiteUrl = `http://${ config.env.tests.config.WP_TESTS_DOMAIN }:${ config.env.tests.port }/`;
177
197
 
178
198
  const { out: mySQLAddress } = await dockerCompose.port(
179
199
  'mysql',
@@ -83,7 +83,7 @@ module.exports = async function readConfig( configPath ) {
83
83
  WP_PHP_BINARY: 'php',
84
84
  WP_TESTS_EMAIL: 'admin@example.org',
85
85
  WP_TESTS_TITLE: 'Test Blog',
86
- WP_TESTS_DOMAIN: 'http://localhost',
86
+ WP_TESTS_DOMAIN: 'localhost',
87
87
  WP_SITEURL: 'http://localhost',
88
88
  WP_HOME: 'http://localhost',
89
89
  },
@@ -297,7 +297,6 @@ function withOverrides( config ) {
297
297
  };
298
298
 
299
299
  // Update wp config options to include the correct port number in the URL.
300
- updateEnvUrl( 'WP_TESTS_DOMAIN' );
301
300
  updateEnvUrl( 'WP_SITEURL' );
302
301
  updateEnvUrl( 'WP_HOME' );
303
302
 
@@ -133,7 +133,7 @@ function parseSourceString( sourceString, { workDirectoryPath } ) {
133
133
  return {
134
134
  type: 'git',
135
135
  url: sshUrl.href.split( '#' )[ 0 ],
136
- ref: sshUrl.hash.slice( 1 ) || 'master',
136
+ ref: sshUrl.hash.slice( 1 ) || undefined,
137
137
  path: workingPath,
138
138
  clonePath: workingPath,
139
139
  basename,
@@ -144,11 +144,12 @@ function parseSourceString( sourceString, { workDirectoryPath } ) {
144
144
  const gitHubFields = sourceString.match(
145
145
  /^([^\/]+)\/([^#\/]+)(\/([^#]+))?(?:#(.+))?$/
146
146
  );
147
+
147
148
  if ( gitHubFields ) {
148
149
  return {
149
150
  type: 'git',
150
151
  url: `https://github.com/${ gitHubFields[ 1 ] }/${ gitHubFields[ 2 ] }.git`,
151
- ref: gitHubFields[ 5 ] || 'master',
152
+ ref: gitHubFields[ 5 ],
152
153
  path: path.resolve(
153
154
  workDirectoryPath,
154
155
  gitHubFields[ 2 ],
@@ -17,7 +17,7 @@ Object {
17
17
  "WP_HOME": "http://localhost:2000/",
18
18
  "WP_PHP_BINARY": "php",
19
19
  "WP_SITEURL": "http://localhost:2000/",
20
- "WP_TESTS_DOMAIN": "http://localhost:2000/",
20
+ "WP_TESTS_DOMAIN": "localhost",
21
21
  "WP_TESTS_EMAIL": "admin@example.org",
22
22
  "WP_TESTS_TITLE": "Test Blog",
23
23
  },
@@ -40,7 +40,7 @@ Object {
40
40
  "WP_HOME": "http://localhost:1000/",
41
41
  "WP_PHP_BINARY": "php",
42
42
  "WP_SITEURL": "http://localhost:1000/",
43
- "WP_TESTS_DOMAIN": "http://localhost:1000/",
43
+ "WP_TESTS_DOMAIN": "localhost",
44
44
  "WP_TESTS_EMAIL": "admin@example.org",
45
45
  "WP_TESTS_TITLE": "Test Blog",
46
46
  },
@@ -64,7 +64,7 @@ Object {
64
64
  "WP_HOME": "http://localhost:8889/",
65
65
  "WP_PHP_BINARY": "php",
66
66
  "WP_SITEURL": "http://localhost:8889/",
67
- "WP_TESTS_DOMAIN": "http://localhost:8889/",
67
+ "WP_TESTS_DOMAIN": "localhost",
68
68
  "WP_TESTS_EMAIL": "admin@example.org",
69
69
  "WP_TESTS_TITLE": "Test Blog",
70
70
  }
@@ -78,7 +78,7 @@ Object {
78
78
  "WP_HOME": "http://localhost:8888/",
79
79
  "WP_PHP_BINARY": "php",
80
80
  "WP_SITEURL": "http://localhost:8888/",
81
- "WP_TESTS_DOMAIN": "http://localhost:8888/",
81
+ "WP_TESTS_DOMAIN": "localhost",
82
82
  "WP_TESTS_EMAIL": "admin@example.org",
83
83
  "WP_TESTS_TITLE": "Test Blog",
84
84
  }
@@ -265,17 +265,17 @@ describe( 'readConfig', () => {
265
265
  pluginSources: [
266
266
  {
267
267
  type: 'local',
268
- path: expect.stringMatching( /^(\/||\\).*relative$/ ),
268
+ path: expect.stringMatching( /^(\/|\\).*relative$/ ),
269
269
  basename: 'relative',
270
270
  },
271
271
  {
272
272
  type: 'local',
273
- path: expect.stringMatching( /^(\/||\\).*parent$/ ),
273
+ path: expect.stringMatching( /^(\/|\\).*parent$/ ),
274
274
  basename: 'parent',
275
275
  },
276
276
  {
277
277
  type: 'local',
278
- path: expect.stringMatching( /^(\/||\\).*home$/ ),
278
+ path: expect.stringMatching( /^(\/|\\).*home$/ ),
279
279
  basename: 'home',
280
280
  },
281
281
  ],
@@ -284,17 +284,17 @@ describe( 'readConfig', () => {
284
284
  pluginSources: [
285
285
  {
286
286
  type: 'local',
287
- path: expect.stringMatching( /^(\/||\\).*relative$/ ),
287
+ path: expect.stringMatching( /^(\/|\\).*relative$/ ),
288
288
  basename: 'relative',
289
289
  },
290
290
  {
291
291
  type: 'local',
292
- path: expect.stringMatching( /^(\/||\\).*parent$/ ),
292
+ path: expect.stringMatching( /^(\/|\\).*parent$/ ),
293
293
  basename: 'parent',
294
294
  },
295
295
  {
296
296
  type: 'local',
297
- path: expect.stringMatching( /^(\/||\\).*home$/ ),
297
+ path: expect.stringMatching( /^(\/|\\).*home$/ ),
298
298
  basename: 'home',
299
299
  },
300
300
  ],
@@ -324,28 +324,28 @@ describe( 'readConfig', () => {
324
324
  expect( config.env.development.pluginSources ).toEqual( [
325
325
  {
326
326
  type: 'local',
327
- path: expect.stringMatching( /^(\/||\\).*test1a$/ ),
327
+ path: expect.stringMatching( /^(\/|\\).*test1a$/ ),
328
328
  basename: 'test1a',
329
329
  },
330
330
  ] );
331
331
  expect( config.env.development.themeSources ).toEqual( [
332
332
  {
333
333
  type: 'local',
334
- path: expect.stringMatching( /^(\/||\\).*test2a$/ ),
334
+ path: expect.stringMatching( /^(\/|\\).*test2a$/ ),
335
335
  basename: 'test2a',
336
336
  },
337
337
  ] );
338
338
  expect( config.env.tests.pluginSources ).toEqual( [
339
339
  {
340
340
  type: 'local',
341
- path: expect.stringMatching( /^(\/||\\).*test1b$/ ),
341
+ path: expect.stringMatching( /^(\/|\\).*test1b$/ ),
342
342
  basename: 'test1b',
343
343
  },
344
344
  ] );
345
345
  expect( config.env.tests.themeSources ).toEqual( [
346
346
  {
347
347
  type: 'local',
348
- path: expect.stringMatching( /^(\/||\\).*test2b$/ ),
348
+ path: expect.stringMatching( /^(\/|\\).*test2b$/ ),
349
349
  basename: 'test2b',
350
350
  },
351
351
  ] );
@@ -359,18 +359,18 @@ describe( 'readConfig', () => {
359
359
  expect( config.env.development ).toMatchObject( {
360
360
  coreSource: {
361
361
  type: 'local',
362
- path: expect.stringMatching( /^(\/||\\).*relative$/ ),
362
+ path: expect.stringMatching( /^(\/|\\).*relative$/ ),
363
363
  testsPath: expect.stringMatching(
364
- /^(\/||\\).*tests-relative$/
364
+ /^(\/|\\).*tests-relative$/
365
365
  ),
366
366
  },
367
367
  } );
368
368
  expect( config.env.tests ).toMatchObject( {
369
369
  coreSource: {
370
370
  type: 'local',
371
- path: expect.stringMatching( /^(\/||\\).*relative$/ ),
371
+ path: expect.stringMatching( /^(\/|\\).*relative$/ ),
372
372
  testsPath: expect.stringMatching(
373
- /^(\/||\\).*tests-relative$/
373
+ /^(\/|\\).*tests-relative$/
374
374
  ),
375
375
  },
376
376
  } );
@@ -395,31 +395,30 @@ describe( 'readConfig', () => {
395
395
  {
396
396
  type: 'git',
397
397
  url: 'https://github.com/WordPress/gutenberg.git',
398
- ref: 'master',
399
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
398
+ ref: undefined,
399
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
400
400
  basename: 'gutenberg',
401
401
  },
402
402
  {
403
403
  type: 'git',
404
404
  url: 'https://github.com/WordPress/gutenberg.git',
405
405
  ref: 'trunk',
406
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
406
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
407
407
  basename: 'gutenberg',
408
408
  },
409
409
  {
410
410
  type: 'git',
411
411
  url: 'https://github.com/WordPress/gutenberg.git',
412
412
  ref: '5.0',
413
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
413
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
414
414
  basename: 'gutenberg',
415
415
  },
416
416
  {
417
417
  type: 'git',
418
- url:
419
- 'https://github.com/WordPress/theme-experiments.git',
418
+ url: 'https://github.com/WordPress/theme-experiments.git',
420
419
  ref: 'tt1-blocks@0.4.3',
421
420
  path: expect.stringMatching(
422
- /^(\/||\\).*theme-experiments(\/||\\)tt1-blocks$/
421
+ /^(\/|\\).*theme-experiments(\/|\\)tt1-blocks$/
423
422
  ),
424
423
  basename: 'tt1-blocks',
425
424
  },
@@ -447,33 +446,29 @@ describe( 'readConfig', () => {
447
446
  pluginSources: [
448
447
  {
449
448
  type: 'zip',
450
- url:
451
- 'https://downloads.wordpress.org/plugin/gutenberg.zip',
452
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
449
+ url: 'https://downloads.wordpress.org/plugin/gutenberg.zip',
450
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
453
451
  basename: 'gutenberg',
454
452
  },
455
453
  {
456
454
  type: 'zip',
457
- url:
458
- 'https://downloads.wordpress.org/plugin/gutenberg.8.1.0.zip',
459
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
455
+ url: 'https://downloads.wordpress.org/plugin/gutenberg.8.1.0.zip',
456
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
460
457
  basename: 'gutenberg',
461
458
  },
462
459
  {
463
460
  type: 'zip',
464
- url:
465
- 'https://downloads.wordpress.org/theme/twentytwenty.zip',
461
+ url: 'https://downloads.wordpress.org/theme/twentytwenty.zip',
466
462
  path: expect.stringMatching(
467
- /^(\/||\\).*twentytwenty$/
463
+ /^(\/|\\).*twentytwenty$/
468
464
  ),
469
465
  basename: 'twentytwenty',
470
466
  },
471
467
  {
472
468
  type: 'zip',
473
- url:
474
- 'https://downloads.wordpress.org/theme/twentytwenty.1.3.zip',
469
+ url: 'https://downloads.wordpress.org/theme/twentytwenty.1.3.zip',
475
470
  path: expect.stringMatching(
476
- /^(\/||\\).*twentytwenty$/
471
+ /^(\/|\\).*twentytwenty$/
477
472
  ),
478
473
  basename: 'twentytwenty',
479
474
  },
@@ -502,35 +497,31 @@ describe( 'readConfig', () => {
502
497
  pluginSources: [
503
498
  {
504
499
  type: 'zip',
505
- url:
506
- 'https://www.example.com/test/path/to/gutenberg.zip',
507
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
500
+ url: 'https://www.example.com/test/path/to/gutenberg.zip',
501
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
508
502
  basename: 'gutenberg',
509
503
  },
510
504
  {
511
505
  type: 'zip',
512
- url:
513
- 'https://www.example.com/test/path/to/gutenberg.8.1.0.zip',
506
+ url: 'https://www.example.com/test/path/to/gutenberg.8.1.0.zip',
514
507
  path: expect.stringMatching(
515
- /^(\/||\\).*gutenberg.8.1.0$/
508
+ /^(\/|\\).*gutenberg.8.1.0$/
516
509
  ),
517
510
  basename: 'gutenberg.8.1.0',
518
511
  },
519
512
  {
520
513
  type: 'zip',
521
- url:
522
- 'https://www.example.com/test/path/to/twentytwenty.zip',
514
+ url: 'https://www.example.com/test/path/to/twentytwenty.zip',
523
515
  path: expect.stringMatching(
524
- /^(\/||\\).*twentytwenty$/
516
+ /^(\/|\\).*twentytwenty$/
525
517
  ),
526
518
  basename: 'twentytwenty',
527
519
  },
528
520
  {
529
521
  type: 'zip',
530
- url:
531
- 'https://www.example.com/test/path/to/twentytwenty.1.3.zip',
522
+ url: 'https://www.example.com/test/path/to/twentytwenty.1.3.zip',
532
523
  path: expect.stringMatching(
533
- /^(\/||\\).*twentytwenty.1.3$/
524
+ /^(\/|\\).*twentytwenty.1.3$/
534
525
  ),
535
526
  basename: 'twentytwenty.1.3',
536
527
  },
@@ -538,7 +529,7 @@ describe( 'readConfig', () => {
538
529
  type: 'zip',
539
530
  url: 'https://example.com/twentytwenty.1.3.zip',
540
531
  path: expect.stringMatching(
541
- /^(\/||\\).*twentytwenty.1.3$/
532
+ /^(\/|\\).*twentytwenty.1.3$/
542
533
  ),
543
534
  basename: 'twentytwenty.1.3',
544
535
  },
@@ -580,12 +571,12 @@ describe( 'readConfig', () => {
580
571
  const matchObj = {
581
572
  test: {
582
573
  type: 'local',
583
- path: expect.stringMatching( /^(\/||\\).*relative$/ ),
574
+ path: expect.stringMatching( /^(\/|\\).*relative$/ ),
584
575
  basename: 'relative',
585
576
  },
586
577
  test2: {
587
578
  type: 'git',
588
- path: expect.stringMatching( /^(\/||\\).*gutenberg$/ ),
579
+ path: expect.stringMatching( /^(\/|\\).*gutenberg$/ ),
589
580
  basename: 'gutenberg',
590
581
  },
591
582
  };
@@ -813,7 +804,7 @@ describe( 'readConfig', () => {
813
804
  development: {
814
805
  port: 1000,
815
806
  config: {
816
- WP_TESTS_DOMAIN: 'http://localhost:1000/',
807
+ WP_TESTS_DOMAIN: 'localhost',
817
808
  WP_SITEURL: 'http://localhost:1000/',
818
809
  WP_HOME: 'http://localhost:1000/',
819
810
  },
@@ -821,7 +812,7 @@ describe( 'readConfig', () => {
821
812
  tests: {
822
813
  port: 2000,
823
814
  config: {
824
- WP_TESTS_DOMAIN: 'http://localhost:2000/',
815
+ WP_TESTS_DOMAIN: 'localhost',
825
816
  WP_SITEURL: 'http://localhost:2000/',
826
817
  WP_HOME: 'http://localhost:2000/',
827
818
  },
@@ -849,7 +840,7 @@ describe( 'readConfig', () => {
849
840
  development: {
850
841
  port: 1000,
851
842
  config: {
852
- WP_TESTS_DOMAIN: 'http://localhost:1000/',
843
+ WP_TESTS_DOMAIN: 'localhost',
853
844
  WP_SITEURL: 'http://localhost:1000/',
854
845
  WP_HOME: 'http://localhost:3000/',
855
846
  },
@@ -857,7 +848,7 @@ describe( 'readConfig', () => {
857
848
  tests: {
858
849
  port: 2000,
859
850
  config: {
860
- WP_TESTS_DOMAIN: 'http://localhost:2000/',
851
+ WP_TESTS_DOMAIN: 'localhost',
861
852
  WP_SITEURL: 'http://localhost:2000/',
862
853
  WP_HOME: 'http://localhost:3000/',
863
854
  },
@@ -1112,7 +1103,7 @@ describe( 'readConfig', () => {
1112
1103
  WP_PHP_BINARY: 'php',
1113
1104
  WP_TESTS_EMAIL: 'admin@example.org',
1114
1105
  WP_TESTS_TITLE: 'Test Blog',
1115
- WP_TESTS_DOMAIN: 'http://localhost:8889/',
1106
+ WP_TESTS_DOMAIN: 'localhost',
1116
1107
  WP_SITEURL: 'http://localhost:8889/',
1117
1108
  WP_HOME: 'http://localhost:8889/',
1118
1109
  } );
@@ -1126,7 +1117,7 @@ describe( 'readConfig', () => {
1126
1117
  WP_PHP_BINARY: 'php',
1127
1118
  WP_TESTS_EMAIL: 'admin@example.org',
1128
1119
  WP_TESTS_TITLE: 'Test Blog',
1129
- WP_TESTS_DOMAIN: 'http://localhost:8888/',
1120
+ WP_TESTS_DOMAIN: 'localhost',
1130
1121
  WP_SITEURL: 'http://localhost:8888/',
1131
1122
  WP_HOME: 'http://localhost:8888/',
1132
1123
  } );
@@ -16,7 +16,7 @@ const extractZip = util.promisify( require( 'extract-zip' ) );
16
16
  const rimraf = util.promisify( require( 'rimraf' ) );
17
17
 
18
18
  /**
19
- * @typedef {import('./config').Config} Config
19
+ * @typedef {import('./config').WPConfig} WPConfig
20
20
  * @typedef {import('./config').WPSource} WPSource
21
21
  */
22
22
 
@@ -24,8 +24,8 @@ const rimraf = util.promisify( require( 'rimraf' ) );
24
24
  * Download each source for each environment. If the same source is used in
25
25
  * multiple environments, it will only be downloaded once.
26
26
  *
27
- * @param {Config} config The wp-env configuration object.
28
- * @param {Object} spinner The spinner object to show progress.
27
+ * @param {WPConfig} config The wp-env configuration object.
28
+ * @param {Object} spinner The spinner object to show progress.
29
29
  * @return {Promise} Returns a promise which resolves when the downloads finish.
30
30
  */
31
31
  module.exports = function downloadSources( config, spinner ) {
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+ /**
3
+ * External dependencies
4
+ */
5
+ const SimpleGit = require( 'simple-git' );
6
+ const fs = require( 'fs' );
7
+ const path = require( 'path' );
8
+
9
+ /**
10
+ * @typedef {import('./config').WPConfig} WPConfig
11
+ */
12
+
13
+ /**
14
+ * Downloads the WordPress PHPUnit files for each environment into the appropriate directories.
15
+ *
16
+ * @param {WPConfig} config The wp-env config object.
17
+ * @param {Object} wpVersions The WordPress versions for each environment.
18
+ * @param {Object} spinner The spinner object to show progress.
19
+ * @param {boolean} debug Indicates whether or not debug mode is active.
20
+ * @return {Promise} Returns a promise which resolves when the downloads finish.
21
+ */
22
+ module.exports = function downloadWPPHPUnit(
23
+ config,
24
+ wpVersions,
25
+ spinner,
26
+ debug
27
+ ) {
28
+ const progresses = {};
29
+ const getProgressSetter = ( id ) => ( progress ) => {
30
+ progresses[ id ] = progress;
31
+ spinner.text =
32
+ 'Downloading WordPress PHPUnit Suite.\n' +
33
+ Object.entries( progresses )
34
+ .map(
35
+ ( [ key, value ] ) =>
36
+ ` - ${ key }: ${ ( value * 100 ).toFixed( 0 ) }/100%`
37
+ )
38
+ .join( '\n' );
39
+ };
40
+
41
+ const promises = [];
42
+ for ( const env in config.env ) {
43
+ const wpVersion = wpVersions[ env ] ? wpVersions[ env ] : null;
44
+ const directory = path.join(
45
+ config.workDirectoryPath,
46
+ env === 'development'
47
+ ? 'WordPress-PHPUnit'
48
+ : 'tests-WordPress-PHPUnit'
49
+ );
50
+ promises.push(
51
+ downloadTestSuite( directory, wpVersion, {
52
+ onProgress: getProgressSetter,
53
+ spinner,
54
+ debug,
55
+ } )
56
+ );
57
+ }
58
+
59
+ return Promise.all( promises );
60
+ };
61
+
62
+ /**
63
+ * Downloads the PHPUnit tests for a given WordPress version into the appropriate directory.
64
+ *
65
+ * @param {string} directory The directory to place the PHPUnit tests in.
66
+ * @param {string} wpVersion The version of WordPress to install PHPUnit tests for. Trunk when empty.
67
+ * @param {Object} options
68
+ * @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
69
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
70
+ * @param {boolean} options.debug True if debug mode is enabled.
71
+ */
72
+ async function downloadTestSuite(
73
+ directory,
74
+ wpVersion,
75
+ { onProgress, spinner, debug }
76
+ ) {
77
+ const log = debug
78
+ ? ( message ) => {
79
+ spinner.info( `SimpleGit: ${ message }` );
80
+ spinner.start();
81
+ }
82
+ : () => {};
83
+ onProgress( 0 );
84
+
85
+ const progressHandler = ( { progress } ) => {
86
+ onProgress( progress / 100 );
87
+ };
88
+
89
+ // Make sure that the version is in X.X.X format. This is required
90
+ // because WordPress/wordpress-develop uses X.X.X tags but
91
+ // WordPress uses X.X for non-patch releases.
92
+ if ( wpVersion && wpVersion.match( /^[0-9]+.[0-9]+$/ ) ) {
93
+ wpVersion += '.0';
94
+ }
95
+
96
+ log( 'Cloning or getting the PHPUnit suite from GitHub.' );
97
+ const git = SimpleGit( { progress: progressHandler } );
98
+
99
+ const isRepo =
100
+ fs.existsSync( directory ) &&
101
+ ( await git.cwd( directory ).checkIsRepo( 'root' ) );
102
+
103
+ if ( isRepo ) {
104
+ log( 'Repo already exists, using it.' );
105
+ } else {
106
+ await git.clone(
107
+ 'https://github.com/WordPress/wordpress-develop.git',
108
+ directory,
109
+ {
110
+ '--depth': '1',
111
+ '--no-checkout': null,
112
+ }
113
+ );
114
+ await git.cwd( directory );
115
+
116
+ // We use a sparse checkout to minimize the amount of data we need to download.
117
+ log( 'Enabling sparse checkout.' );
118
+ await git.raw( 'sparse-checkout', 'set', '--cone', 'tests/phpunit' );
119
+ }
120
+
121
+ // Figure out the ref that we need to checkout to get the correct version of the PHPUnit library.
122
+ // Alpha, Beta, and RC versions are bleeding edge and should pull from trunk.
123
+ let ref;
124
+ const fetchRaw = [];
125
+ if ( ! wpVersion || wpVersion.match( /-(?:alpha|beta|rc)/ ) ) {
126
+ ref = 'trunk';
127
+ fetchRaw.push( 'fetch', 'origin', ref, '--depth', '1' );
128
+ } else {
129
+ ref = `tags/${ wpVersion }`;
130
+ fetchRaw.push( 'fetch', 'origin', 'tag', wpVersion, '--depth', '1' );
131
+ }
132
+
133
+ log( `Fetching ${ ref }.` );
134
+ await git.raw( fetchRaw );
135
+
136
+ log( `Checking out ${ ref }.` );
137
+ await git.checkout( ref );
138
+
139
+ onProgress( 1 );
140
+ }
package/lib/wordpress.js CHANGED
@@ -14,6 +14,7 @@ const copyDir = util.promisify( require( 'copy-dir' ) );
14
14
  /**
15
15
  * @typedef {import('./config').WPConfig} WPConfig
16
16
  * @typedef {import('./config').WPServiceConfig} WPServiceConfig
17
+ * @typedef {import('./config').WPSource} WPSource
17
18
  * @typedef {'development'|'tests'} WPEnvironment
18
19
  * @typedef {'development'|'tests'|'all'} WPEnvironmentSelection
19
20
  */
@@ -64,6 +65,11 @@ async function configureWordPress( environment, config, spinner ) {
64
65
  for ( let [ key, value ] of Object.entries(
65
66
  config.env[ environment ].config
66
67
  ) ) {
68
+ // Allow the configuration to skip a default constant by specifying it as null.
69
+ if ( null === value ) {
70
+ continue;
71
+ }
72
+
67
73
  // Add quotes around string values to work with multi-word strings better.
68
74
  value = typeof value === 'string' ? `"${ value }"` : value;
69
75
  setupCommands.push(
@@ -96,25 +102,15 @@ async function configureWordPress( environment, config, spinner ) {
96
102
  }
97
103
  );
98
104
 
99
- /**
100
- * Since wp-phpunit loads wp-settings.php at the end of its wp-config.php
101
- * file, we need to avoid loading it too early in our own wp-config.php. If
102
- * we load it too early, then some things (like MULTISITE) will be defined
103
- * before wp-phpunit has a chance to configure them. To avoid this, create a
104
- * copy of wp-config.php for phpunit which doesn't require wp-settings.php.
105
- *
106
- * Note that This needs to be executed using `exec` on the wordpress service
107
- * so that file permissions work properly.
108
- *
109
- * This will be removed in the future. @see https://github.com/WordPress/gutenberg/issues/23171
110
- *
111
- */
105
+ // WordPress' PHPUnit suite expects a `wp-tests-config.php` in
106
+ // the directory that the test suite is contained within.
107
+ // Make sure ABSPATH points to the WordPress install.
112
108
  await dockerCompose.exec(
113
109
  environment === 'development' ? 'wordpress' : 'tests-wordpress',
114
110
  [
115
111
  'sh',
116
112
  '-c',
117
- 'sed "/^require.*wp-settings.php/d" /var/www/html/wp-config.php > /var/www/html/phpunit-wp-config.php && chmod 777 /var/www/html/phpunit-wp-config.php',
113
+ `sed -e "/^require.*wp-settings.php/d" -e "s/define( 'ABSPATH', __DIR__ . '\\/' );/define( 'ABSPATH', '\\/var\\/www\\/html\\/' );\\n\\tdefine( 'WP_DEFAULT_THEME', 'default' );/" /var/www/html/wp-config.php > /wordpress-phpunit/wp-tests-config.php`,
118
114
  ],
119
115
  {
120
116
  config: config.dockerComposeConfigPath,
@@ -241,10 +237,49 @@ async function copyCoreFiles( fromPath, toPath ) {
241
237
  } );
242
238
  }
243
239
 
240
+ /**
241
+ * Scans through a WordPress source to find the version of WordPress it contains.
242
+ *
243
+ * @param {WPSource} coreSource The WordPress source.
244
+ * @param {Object} spinner A CLI spinner which indicates progress.
245
+ * @param {boolean} debug Indicates whether or not the CLI is in debug mode.
246
+ * @return {string} The version of WordPress the source is for.
247
+ */
248
+ async function readWordPressVersion( coreSource, spinner, debug ) {
249
+ // No source means they're using the bleeding edge.
250
+ if ( coreSource === null ) {
251
+ return null;
252
+ }
253
+
254
+ const versionFilePath = path.join(
255
+ coreSource.path,
256
+ 'wp-includes',
257
+ 'version.php'
258
+ );
259
+ const versionFile = await fs.readFile( versionFilePath, {
260
+ encoding: 'utf-8',
261
+ } );
262
+ const versionMatch = versionFile.match(
263
+ /\$wp_version = '([A-Za-z\-0-9.]+)'/
264
+ );
265
+ if ( ! versionMatch ) {
266
+ throw new Error( `Failed to find version in ${ versionFilePath }` );
267
+ }
268
+
269
+ if ( debug ) {
270
+ spinner.info(
271
+ `Found WordPress ${ versionMatch[ 1 ] } in ${ versionFilePath }.`
272
+ );
273
+ }
274
+
275
+ return versionMatch[ 1 ];
276
+ }
277
+
244
278
  module.exports = {
245
279
  hasSameCoreSource,
246
280
  checkDatabaseConnection,
247
281
  configureWordPress,
248
282
  resetDatabase,
249
283
  setupWordPressDirectories,
284
+ readWordPressVersion,
250
285
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/env",
3
- "version": "4.7.0",
3
+ "version": "5.0.0",
4
4
  "description": "A zero-config, self contained local WordPress environment for development and testing.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -36,7 +36,7 @@
36
36
  "copy-dir": "^1.3.0",
37
37
  "docker-compose": "^0.22.2",
38
38
  "extract-zip": "^1.6.7",
39
- "got": "^10.7.0",
39
+ "got": "^11.8.5",
40
40
  "inquirer": "^7.1.0",
41
41
  "js-yaml": "^3.13.1",
42
42
  "ora": "^4.0.2",
@@ -51,5 +51,5 @@
51
51
  "scripts": {
52
52
  "test": "echo \"Error: run tests from root\" && exit 1"
53
53
  },
54
- "gitHead": "198fa129cf1af8dc615918987ea6795cd40ab7df"
54
+ "gitHead": "0315dbc240cb2aa146d7c1bafd251f004b88300e"
55
55
  }