Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/env/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### New Features

- Add a `mariadbVersion` option and `WP_ENV_MARIADB_VERSION` environment variable to choose the MariaDB version used by the Docker runtime ([#83751](https://github.com/WordPress/gutenberg/pull/83751)).

## 4.0.3 (2021-04-29)

### Bug Fix
Expand Down
18 changes: 18 additions & 0 deletions packages/env/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ You can customize the WordPress installation, plugins and themes that the develo
| -------------- | -------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `"core"` | `string\|null` | `null` | The WordPress installation to use. If `null` is specified, `wp-env` will use the latest production release of WordPress. |
| `"phpVersion"` | `string\|null` | `null` | The PHP version to use. If `null` is specified, `wp-env` will use the default version used with production release of WordPress. |
| `"mariadbVersion"` | `string\|null` | `null` | The MariaDB version to use: `"lts"`, `"latest"`, or a version such as `"10.11"`. If `null` is specified, `latest` is used. |
| `"plugins"` | `string[]` | `[]` | A list of plugins to install and activate in the environment. |
| `"themes"` | `string[]` | `[]` | A list of themes to install in the environment. |
| `"port"` | `integer` | `8888` (`8889` for the tests instance) | The primary port number to use for the installation. You'll access the instance through the port: 'http://localhost:8888'. |
Expand Down Expand Up @@ -575,4 +576,21 @@ You can tell `wp-env` to use a specific PHP version for compatibility and testin
}
```

#### Specific MariaDB Version

You can tell `wp-env` which MariaDB version the database should run, for compatibility and testing. Use `"lts"`, `"latest"`, or a version such as `"10.11"` or `"11.4.2"`. This can also be set via the environment variable `WP_ENV_MARIADB_VERSION`, which applies to every environment.

```json
{
"mariadbVersion": "10.11",
"plugins": [ "." ]
}
```

MariaDB cannot start on a database written by a newer version. When switching to a lower version, run `wp-env destroy` first. It removes the environment's Docker containers, volumes, networks, and local files, not only the databases, so everything is recreated on the next start.

**Note:** With a `mariadbVersion` older than 11.4, `wp db` commands in the `cli` containers fail, and `wp-env clean` leaves the database as it is: the MariaDB client in the CLI image requires TLS when `phpVersion` is unset or 8.1 or newer, and MariaDB servers before 11.4 do not offer it. WordPress itself is not affected. To start over with an empty database, run `wp-env destroy`.

**Note:** MariaDB 5.5 images are not published for ARM processors. Apple silicon devices can still run version 5.5 under emulation by setting `DOCKER_DEFAULT_PLATFORM=linux/amd64` before running `wp-env start`. Be aware that every container in the environment runs under emulation, not only the database, so the whole environment runs more slowly.

<br/><br/><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>
8 changes: 6 additions & 2 deletions packages/env/lib/build-docker-compose-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ module.exports = function buildDockerComposeConfig( config ) {
version: '3.7',
services: {
mysql: {
image: 'mariadb',
image: config.env.development.mariadbVersion
? `mariadb:${ config.env.development.mariadbVersion }`
: 'mariadb',
ports: [ '3306' ],
environment: {
MYSQL_ROOT_PASSWORD:
Expand All @@ -184,7 +186,9 @@ module.exports = function buildDockerComposeConfig( config ) {
volumes: [ 'mysql:/var/lib/mysql' ],
},
'tests-mysql': {
image: 'mariadb',
image: config.env.tests.mariadbVersion
? `mariadb:${ config.env.tests.mariadbVersion }`
: 'mariadb',
ports: [ '3306' ],
environment: {
MYSQL_ROOT_PASSWORD:
Expand Down
20 changes: 19 additions & 1 deletion packages/env/lib/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ const os = require( 'os' );
* Internal dependencies
*/
const detectDirectoryType = require( './detect-directory-type' );
const { validateConfig, ValidationError } = require( './validate-config' );
const {
validateConfig,
checkMariaDBVersion,
ValidationError,
} = require( './validate-config' );
const readRawConfigFile = require( './read-raw-config-file' );
const parseConfig = require( './parse-config' );
const md5 = require( '../md5' );
Expand Down Expand Up @@ -39,6 +43,7 @@ const md5 = require( '../md5' );
* @property {Object} config Mapping of wp-config.php constants to their desired values.
* @property {Object.<string, WPSource>} mappings Mapping of WordPress directories to local directories which should be mounted.
* @property {string} phpVersion Version of PHP to use in the environments, of the format 0.0.
* @property {string} mariadbVersion Version of MariaDB to use in the environments: "lts", "latest", or of the format 0.0. Null uses the default.
*/

/**
Expand Down Expand Up @@ -71,6 +76,7 @@ module.exports = async function readConfig( configPath ) {
const defaultConfiguration = {
core: null,
phpVersion: null,
mariadbVersion: null,
plugins: [],
themes: [],
port: 8888,
Expand Down Expand Up @@ -262,6 +268,18 @@ function withOverrides( config ) {
config.env.tests.phpVersion =
process.env.WP_ENV_PHP_VERSION || config.env.tests.phpVersion;

// Override MariaDB version with environment variable.
if ( process.env.WP_ENV_MARIADB_VERSION ) {
checkMariaDBVersion(
'environment variable',
'WP_ENV_MARIADB_VERSION',
process.env.WP_ENV_MARIADB_VERSION
);
config.env.development.mariadbVersion =
process.env.WP_ENV_MARIADB_VERSION;
config.env.tests.mariadbVersion = process.env.WP_ENV_MARIADB_VERSION;
}

const updateEnvUrl = ( configKey ) => {
[ 'development', 'tests' ].forEach( ( envKey ) => {
try {
Expand Down
1 change: 1 addition & 0 deletions packages/env/lib/config/parse-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports = function parseConfig( config, options ) {
return {
port: config.port,
phpVersion: config.phpVersion,
mariadbVersion: config.mariadbVersion,
coreSource: includeTestsPath(
parseSourceString( config.core, options ),
options
Expand Down
2 changes: 2 additions & 0 deletions packages/env/lib/config/test/__snapshots__/config.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Object {
},
"coreSource": null,
"mappings": Object {},
"mariadbVersion": null,
"phpVersion": null,
"pluginSources": Array [],
"port": 2000,
Expand All @@ -46,6 +47,7 @@ Object {
},
"coreSource": null,
"mappings": Object {},
"mariadbVersion": null,
"phpVersion": null,
"pluginSources": Array [],
"port": 1000,
Expand Down
71 changes: 71 additions & 0 deletions packages/env/lib/config/test/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,77 @@ describe( 'readConfig', () => {
} );
} );

describe( 'mariadbVersion parsing', () => {
afterEach( () => {
delete process.env.WP_ENV_MARIADB_VERSION;
} );

it( 'should default to null', async () => {
readFile.mockImplementation( () =>
Promise.resolve( JSON.stringify( {} ) )
);
const config = await readConfig( '.wp-env.json' );
expect( config.env.development.mariadbVersion ).toBeNull();
expect( config.env.tests.mariadbVersion ).toBeNull();
} );

it( 'should parse mariadbVersion at the root and per environment', async () => {
readFile.mockImplementation( () =>
Promise.resolve(
JSON.stringify( {
mariadbVersion: '10.11',
env: { tests: { mariadbVersion: 'latest' } },
} )
)
);
const config = await readConfig( '.wp-env.json' );
expect( config.env.development.mariadbVersion ).toBe( '10.11' );
expect( config.env.tests.mariadbVersion ).toBe( 'latest' );
} );

it( 'should throw a validation error for an invalid mariadbVersion', async () => {
readFile.mockImplementation( () =>
Promise.resolve(
JSON.stringify( {
env: { tests: { mariadbVersion: 'LTS' } },
} )
)
);
await expect( readConfig( '.wp-env.json' ) ).rejects.toEqual(
new ValidationError(
'Invalid .wp-env.json: "env.tests.mariadbVersion" must be "lts", "latest", or a version such as "10.11" or "11.4.2".'
)
);
} );

it( 'should override mariadbVersion in every environment with WP_ENV_MARIADB_VERSION', async () => {
readFile.mockImplementation( () =>
Promise.resolve(
JSON.stringify( {
mariadbVersion: '10.11',
env: { tests: { mariadbVersion: 'latest' } },
} )
)
);
process.env.WP_ENV_MARIADB_VERSION = '10.3';
const config = await readConfig( '.wp-env.json' );
expect( config.env.development.mariadbVersion ).toBe( '10.3' );
expect( config.env.tests.mariadbVersion ).toBe( '10.3' );
} );

it( 'should throw a validation error for an invalid WP_ENV_MARIADB_VERSION', async () => {
readFile.mockImplementation( () =>
Promise.resolve( JSON.stringify( {} ) )
);
process.env.WP_ENV_MARIADB_VERSION = 'LTS';
await expect( readConfig( '.wp-env.json' ) ).rejects.toEqual(
new ValidationError(
'Invalid environment variable: "WP_ENV_MARIADB_VERSION" must be "lts", "latest", or a version such as "10.11" or "11.4.2".'
)
);
} );
} );

describe( 'port number parsing', () => {
it( 'should throw a validaton error if the ports are not numbers', async () => {
expect.assertions( 10 );
Expand Down
38 changes: 38 additions & 0 deletions packages/env/lib/config/validate-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,48 @@ function validateConfig( config, envLocation ) {
);
}

if (
config.mariadbVersion !== undefined &&
config.mariadbVersion !== null
) {
checkMariaDBVersion(
'.wp-env.json',
`${ envPrefix }mariadbVersion`,
config.mariadbVersion
);
}

return config;
}

/**
* Validates a MariaDB version and throws if it isn't valid. Accepts the
* "lts" and "latest" image tags or a numeric version such as "10.11".
*
* @param {string} source Where the value came from, for the error message.
* @param {string} configKey The configuration key we're validating.
* @param {string} version The version that we're checking.
*/
function checkMariaDBVersion( source, configKey, version ) {
if ( typeof version !== 'string' ) {
throw new ValidationError(
`Invalid ${ source }: "${ configKey }" must be a string.`
);
}

if ( version === 'lts' || version === 'latest' ) {
return;
}

if ( ! /^[0-9]+(?:\.[0-9]+)*$/.test( version ) ) {
throw new ValidationError(
`Invalid ${ source }: "${ configKey }" must be "lts", "latest", or a version such as "10.11" or "11.4.2".`
);
}
}

module.exports = {
validateConfig,
checkMariaDBVersion,
ValidationError,
};
39 changes: 39 additions & 0 deletions packages/env/test/build-docker-compose-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,43 @@ describe( 'buildDockerComposeConfig', () => {
expect( dockerConfig.volumes.wordpress ).toBe( undefined );
expect( dockerConfig.volumes[ 'tests-wordpress' ] ).toBe( undefined );
} );

describe( 'mariadbVersion', () => {
it( 'uses the floating mariadb image by default', () => {
const config = buildDockerComposeConfig( {
workDirectoryPath: '/path',
env: { development: CONFIG, tests: CONFIG },
} );

expect( config.services.mysql.image ).toBe( 'mariadb' );
expect( config.services[ 'tests-mysql' ].image ).toBe( 'mariadb' );
} );

it( 'treats null the same as unset', () => {
const config = buildDockerComposeConfig( {
workDirectoryPath: '/path',
env: {
development: { ...CONFIG, mariadbVersion: null },
tests: { ...CONFIG, mariadbVersion: null },
},
} );

expect( config.services.mysql.image ).toBe( 'mariadb' );
} );

it( 'uses each environment’s own version', () => {
const config = buildDockerComposeConfig( {
workDirectoryPath: '/path',
env: {
development: { ...CONFIG, mariadbVersion: '10.6.4' },
tests: { ...CONFIG, mariadbVersion: 'latest' },
},
} );

expect( config.services.mysql.image ).toBe( 'mariadb:10.6.4' );
expect( config.services[ 'tests-mysql' ].image ).toBe(
'mariadb:latest'
);
} );
} );
} );
Loading