Skip to content

Commit

Permalink
Add .wp-env.json support to wp-env
Browse files Browse the repository at this point in the history
  • Loading branch information
noisysocks committed Feb 3, 2020
1 parent 7c32ac9 commit 81da692
Show file tree
Hide file tree
Showing 16 changed files with 972 additions and 424 deletions.
4 changes: 4 additions & 0 deletions .wp-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"core": "WordPress/WordPress",
"plugins": [ "." ]
}
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions packages/env/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## Master

### Breaking Changes

- `wp-env start` no longer accepts a WordPress branch or tag reference as its argument. Instead, create a `.wp-env.json` file and specify a `"core"` field.

### New Feature

- A `.wp-env.json` configuration file can now be used to specify the WordPress installation, plugins, and themes to use in the local development environment.

### Bug Fixes

- When running scripts using `wp-env run`, the output will not be formatted if not written to terminal display, resolving an issue where piped or redirected output could be unintentionally padded with newlines.
86 changes: 71 additions & 15 deletions packages/env/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ $ wp-env start
### `wp-env start [ref]`

```sh
wp-env start [ref]
wp-env start

Starts WordPress for development on port 8888 (​http://localhost:8888​)
(override with WP_ENV_PORT) and tests on port 8889 (​http://localhost:8889​)
(override with WP_ENV_TESTS_PORT). If the current working directory is a plugin
and/or has e2e-tests with plugins and/or mu-plugins, they will be mounted
appropriately.
(override with WP_ENV_TESTS_PORT). The current working directory must be a
WordPress installation, a plugin, a theme, or contain a .wp-env.json file.


Positionals:
ref A `https://github.com/WordPress/WordPress` git repo branch or commit for
Expand All @@ -171,28 +171,84 @@ Positionals:
[string] [choices: "all", "development", "tests"] [default: "tests"]
```
## Running with multiple plugins and/or themes
## .wp-env.json
You can customize the WordPress installation, plugins and themes that the development environment will use by specifying a `.wp-env.json` file in the directory that you run `wp-env` from.
`.wp-env.json` supports three fields:
| Field | Type | Default | Description |
| -- | -- | -- | -- |
| `"core"` | `string|null` | `null` | The WordPress installation to use. If `null` is specified, `wp-env` will use the latest production release of WordPress. |
| `"plugins"` | `string[]` | `[]` | A list of plugins to install and activate in the environment. |
| `"themes"` | `string[]` | `[]` | A list of themes to install in the environment. The first theme in the list will be activated. |
Several types of strings can be passed into these fields:
`wp-env` also supports a configuration file. At the moment, this is only used for loading extra themes and plugins that you may be developing together with your main one. The script will attach the specified theme and plugin directories as volumes on the docker containers so that changes you make to them exist in the WordPress instance.
| Type | Format | Example(s) |
| -- | -- | -- |
| Relative path | `.<path>|~<path>` | `"./a/directory"`, `"../a/directory"`, `"~/a/directory"` |
| Absolute path | `/<path>|<letter>:\<path>` | `"/a/directory"`, `"C:\\a\\directory"` |
| GitHub repository | `<owner>/<repo>[#<ref>]` | `"WordPress/WordPress"`, `"WordPress/gutenberg#master"` |
### Example:
Remote sources will be downloaded into a temporary directory located in `~/.wp-env`.
### Examples
#### Latest production WordPress + current directory as a plugin
This is useful for plugin development.
`wp-env.json`
```json
{
"themes": [
"../path/to/theme/dir"
],
"core": null,
"plugins": [
"."
]
}
```
#### Latest development WordPress + current directory as a plugin
This is useful for plugin development when upstream Core changes need to be tested.
```json
{
"core": "WordPress/WordPress#master",
"plugins": [
"."
]
}
```
#### Local `wordpress-develop` + current directory as a plugin
This is useful for working on plugins and WordPress Core at the same time.
```json
{
"core": "../wordpress-develop/build",
"plugins": [
"../path/to/plugin/dir"
"."
]
}
```
### Caveats:
#### A complete testing environment
The file should be located in the same directory from which you run `wp-env` commands for a project. So if you are running `wp-env` in the root directory of a plugin, `wp-env.json` should also be located there.
This is useful for integration testing: that is, testing how old versions of WordPress and different combinations of plugins and themes impact each other.
Each item in the `themes` or `plugins` array should be an absolute or relative path to the root of a different theme or plugin directory. Relative paths will be resolved from the current working directory, which means they will be resolved from the location of the `wp-env.json` file.
```json
{
"core": "WordPress/WordPress#5.2.0",
"plugins": [
"WordPress/wp-lazy-loading",
"WordPress/classic-editor",
],
"themes": [
"WordPress/theme-experiments"
]
}
```
<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>
90 changes: 90 additions & 0 deletions packages/env/lib/build-docker-compose-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
'use strict';
/**
* External dependencies
*/
const fs = require( 'fs' );
const path = require( 'path' );

/**
* Creates a docker-compose config object which, when serialized into a
* docker-compose.yml file, tells docker-compose how to run the environment.
*
* @param {Config} config A wp-env config object.
* @return {Object} A docker-compose config object, ready to serialize into YAML.
*/
module.exports = function buildDockerComposeConfig( config ) {
const pluginMounts = config.pluginSources.flatMap( ( source ) => [
`${ source.path }:/var/www/html/wp-content/plugins/${ source.basename }`,

// If this is is the Gutenberg plugin, then mount its E2E test plugins.
// TODO: Implement an API that lets Gutenberg mount test plugins without this workaround.
...( fs.existsSync( path.resolve( source.path, 'gutenberg.php' ) ) && [
`${ source.path }/packages/e2e-tests/plugins:/var/www/html/wp-content/plugins/gutenberg-test-plugins`,
`${ source.path }/packages/e2e-tests/mu-plugins:/var/www/html/wp-content/mu-plugins`,
] ),
] );

const themeMounts = config.themeSources.map(
( source ) => `${ source.path }:/var/www/html/wp-content/themes/${ source.basename }`
);

const developmentMounts = [
`${ config.coreSource ? config.coreSource.path : 'wordpress' }:/var/www/html`,
...pluginMounts,
...themeMounts,
];

const testsMounts = [
`${ config.coreSource ? config.coreSource.testsPath : 'tests-wordpress' }:/var/www/html`,
...pluginMounts,
...themeMounts,
];

return {
version: '3.7',
services: {
mysql: {
image: 'mariadb',
environment: {
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes',
},
},
wordpress: {
depends_on: [ 'mysql' ],
image: 'wordpress',
ports: [ '${WP_ENV_PORT:-8888}:80' ],
environment: {
WORDPRESS_DEBUG: '1',
},
volumes: developmentMounts,
},
'tests-wordpress': {
depends_on: [ 'mysql' ],
image: 'wordpress',
ports: [ '${WP_ENV_TESTS_PORT:-8889}:80' ],
environment: {
WORDPRESS_DEBUG: '1',
},
volumes: testsMounts,
},
cli: {
depends_on: [ 'wordpress' ],
image: 'wordpress:cli',
volumes: developmentMounts,
},
'tests-cli': {
depends_on: [ 'wordpress' ],
image: 'wordpress:cli',
volumes: testsMounts,
},
composer: {
image: 'composer',
volumes: [ `${ config.configDirectoryPath }:/app` ],
},
},
volumes: {
...( ! config.coreSource && { wordpress: {} } ),
...( ! config.coreSource && { 'tests-wordpress': {} } ),
},
};
};
33 changes: 12 additions & 21 deletions packages/env/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ const withSpinner = ( command ) => ( ...args ) => {
( message ) => {
time = process.hrtime( time );
spinner.succeed(
`${ message || spinner.text } (in ${ time[ 0 ] }s ${ ( time[ 1 ] / 1e6 ).toFixed(
0
) }ms)`
`${ message || spinner.text } (in ${ time[ 0 ] }s ${ ( time[ 1 ] / 1e6 ).toFixed( 0 ) }ms)`
);
},
( err ) => {
spinner.fail( err.message || err.err );
// eslint-disable-next-line no-console
console.error( `\n\n${ err.out || err.err }\n\n` );
process.exit( err.exitCode || 1 );
( error ) => {
spinner.fail( error.message || error.err );
if ( ! ( error instanceof env.ValidationError ) ) {
// eslint-disable-next-line no-console
console.error( '\n\n', error, '\n\n' );
}
process.exit( error.exitCode || 1 );
}
);
};
Expand All @@ -46,31 +46,22 @@ module.exports = function cli() {
yargs.usage( wpPrimary( '$0 <command>' ) );

yargs.command(
'start [ref]',
'start',
wpGreen(
chalk`Starts WordPress for development on port {bold.underline ${ terminalLink(
'8888',
'http://localhost:8888'
) }} (override with WP_ENV_PORT) and tests on port {bold.underline ${ terminalLink(
'8889',
'http://localhost:8889'
) }} (override with WP_ENV_TESTS_PORT). If the current working directory is a plugin and/or has e2e-tests with plugins and/or mu-plugins, they will be mounted appropriately.`
) }} (override with WP_ENV_TESTS_PORT). The current working directory must be a WordPress installation, a plugin, a theme, or contain a .wp-env.json file.`
),
( args ) => {
args.positional( 'ref', {
type: 'string',
describe:
'A `https://github.com/WordPress/WordPress` git repo branch or commit for choosing a specific version.',
default: 'master',
} );
},
() => {},
withSpinner( env.start )
);
yargs.command(
'stop',
wpRed(
'Stops running WordPress for development and tests and frees the ports.'
),
wpRed( 'Stops running WordPress for development and tests and frees the ports.' ),
() => {},
withSpinner( env.stop )
);
Expand Down
Loading

0 comments on commit 81da692

Please sign in to comment.