Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b2ee325
Env: Add a MariaDB version validator
desrosj Sep 29, 2026
74e817f
Env: Parse the mariadbVersion option and WP_ENV_MARIADB_VERSION
desrosj Sep 29, 2026
2c66eb3
Env: Use the configured MariaDB version for the database image and he…
desrosj Sep 29, 2026
3c46564
Env: Document the mariadbVersion option and add it to the schema
desrosj Sep 29, 2026
ef273b3
Env: Detect healthcheck.sh in pinned MariaDB images instead of matchi…
desrosj Sep 29, 2026
964b1e2
Env: Link the MariaDB version changelog entry to its PR
desrosj Sep 29, 2026
ad38c10
Merge branch 'trunk' into add/database-version-control-to-wp-env
desrosj Sep 29, 2026
5cc17af
Merge branch 'trunk' into add/database-version-control-to-wp-env
desrosj Sep 29, 2026
706b900
Merge branch 'trunk' into add/database-version-control-to-wp-env
desrosj Oct 1, 2026
30874d3
Env: Fix the health check for older MariaDB images.
desrosj Oct 1, 2026
23f53b6
Env: Explain when a database was last used by a newer MariaDB.
desrosj Oct 2, 2026
80a1c59
Env: Use one MariaDB health check for every version.
desrosj Oct 2, 2026
7cc2a91
Env: Define the MariaDB image tags and default in one place.
desrosj Oct 2, 2026
91d3614
Env: Validate PHP and MariaDB versions with one anchored pattern.
desrosj Oct 2, 2026
e535c7c
Env: Test what the MariaDB health check does, not its text.
desrosj Oct 2, 2026
427f8ec
Env: Correct which MariaDB versions need emulation on ARM.
desrosj Oct 2, 2026
25a976c
Env: Name images that cannot be pulled or found locally.
desrosj Oct 2, 2026
1a602e5
Merge branch 'trunk' into add/database-version-control-to-wp-env
desrosj Oct 5, 2026
cbd1928
Env: Remove a health check test that can no longer fail.
desrosj Oct 5, 2026
8f7e27f
Env: Check the database versions in parallel.
desrosj Oct 5, 2026
17b285a
Env: Say what `wp-env cleanup` removes when suggesting it.
desrosj Oct 5, 2026
c687c83
Env: Only report a MariaDB downgrade when a database failed to start.
desrosj Oct 5, 2026
f400648
Env: Only run healthcheck.sh when the MariaDB image has it.
desrosj Oct 5, 2026
794ca55
Env: Skip the MariaDB health check shell tests on Windows.
desrosj Oct 5, 2026
478674e
Merge branch 'trunk' into add/database-version-control-to-wp-env
desrosj Oct 5, 2026
f6b0a70
Merge branch 'add/database-version-control-to-wp-env' of https://gith…
desrosj Oct 5, 2026
099afff
Env: Let `wp db` commands connect to MariaDB versions before 11.4.
desrosj Oct 5, 2026
bcbad4f
Merge branch 'trunk' into add/database-version-control-to-wp-env
desrosj Oct 6, 2026
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
8 changes: 8 additions & 0 deletions packages/env/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@

## Unreleased

### New Features

- Add a `mariadbVersion` option and `WP_ENV_MARIADB_VERSION` environment variable to choose the MariaDB version used by the Docker runtime, including versions older than 10.4 ([#83751](https://github.com/WordPress/gutenberg/pull/83751)).
- Explain why `wp-env start` fails when a database was last used by a newer MariaDB version, which MariaDB cannot downgrade from ([#83751](https://github.com/WordPress/gutenberg/pull/83751)).
- Stop `wp-env start` with an error naming the image when an image cannot be pulled and is not available locally, such as a `mariadbVersion` that does not exist, instead of reporting that cached images will be used ([#83751](https://github.com/WordPress/gutenberg/pull/83751)).
- Make `wp db` commands, and so `wp-env reset`, work with a `mariadbVersion` older than 11.4. The MariaDB client in the CLI image requires TLS, which those servers do not offer, so the CLI image now runs the client without verifying the server certificate, as WP-CLI does from db-command 3.0 ([#83751](https://github.com/WordPress/gutenberg/pull/83751)).

### Bug Fixes

- Reject a `phpVersion` or `WP_ENV_PHP_VERSION` that is not only a version number, such as `8.2-apache` or `abc8`, instead of failing later because the Docker image does not exist ([#83751](https://github.com/WordPress/gutenberg/pull/83751)).
- Pass `-T` to `docker compose exec` when stdin is not a terminal, so commands run from a Git hook, which has a TTY on stdout but not on stdin, no longer fail with "cannot attach stdin to a TTY-enabled container" ([#78374](https://github.com/WordPress/gutenberg/pull/78374)).

### Internal
Expand Down
17 changes: 17 additions & 0 deletions packages/env/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ $ wp-env start --runtime=playground
| MySQL database | Yes | No (SQLite) |
| Multisite | Yes | Yes |
| Custom PHP version | Yes | Yes |
| Custom MariaDB version | Yes | No (SQLite) |
| Plugin/theme mounting | Yes | Yes |
| `wp-env run` command | Yes | No |

Expand Down Expand Up @@ -601,6 +602,7 @@ To enable editor autocomplete and validation, add a `$schema` key:
|----------------------|----------------|----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| `"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, `lts` 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` | The port number to use for the installation. |
Expand Down Expand Up @@ -827,6 +829,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. The Playground runtime uses SQLite and ignores this option.

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

MariaDB cannot start on a database last used by a newer version. When that happens, `wp-env start` stops with an error that names both versions. To switch to a lower version, run `wp-env cleanup` first. It removes the environment's Docker containers, volumes, and local files, not only the databases, so everything is recreated on the next start.

**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.

### Multisite support

You can tell `wp-env` if the site should be multisite enabled.
Expand Down
6 changes: 5 additions & 1 deletion packages/env/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const {
getRuntime,
UnsupportedCommandError,
EnvironmentNotInitializedError,
DatabaseDowngradeError,
MissingImageError,
} = require( './runtime' );

// Spinner.
Expand Down Expand Up @@ -39,7 +41,9 @@ const withSpinner =
( error ) => {
if (
error instanceof UnsupportedCommandError ||
error instanceof EnvironmentNotInitializedError
error instanceof EnvironmentNotInitializedError ||
error instanceof DatabaseDowngradeError ||
error instanceof MissingImageError
) {
// Error is a known user-facing error.
spinner.fail( error.message );
Expand Down
21 changes: 21 additions & 0 deletions packages/env/lib/config/db-env.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,29 @@ const development = {
WORDPRESS_DB_NAME: 'wordpress',
};

/*
* MariaDB image used by the database services. Besides a version number, the
* image accepts these tags, and the default follows the latest LTS release.
*/
const MARIADB_IMAGE_TAGS = [ 'lts', 'latest' ];
const DEFAULT_MARIADB_VERSION = 'lts';

/**
* Gets the MariaDB image for an environment's configured version.
*
* @param {string|null|undefined} mariadbVersion The configured MariaDB version, or null for the default.
*
* @return {string} The image name, such as `mariadb:lts` or `mariadb:10.11`.
*/
function getMariaDBImage( mariadbVersion ) {
return `mariadb:${ mariadbVersion ?? DEFAULT_MARIADB_VERSION }`;
}

module.exports = {
credentials,
tests,
development,
MARIADB_IMAGE_TAGS,
DEFAULT_MARIADB_VERSION,
getMariaDBImage,
};
17 changes: 16 additions & 1 deletion packages/env/lib/config/get-config-from-environment-vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ const {
parseSourceString,
includeTestsPath,
} = require( './parse-source-string' );
const { checkPort, checkVersion, checkString } = require( './validate-config' );
const {
checkPort,
checkVersion,
checkMariaDBVersion,
checkString,
} = require( './validate-config' );

/**
* @typedef {import('./parse-source-string').WPSource} WPSource
Expand All @@ -20,6 +25,7 @@ const { checkPort, checkVersion, checkString } = require( './validate-config' );
* @property {?number} phpmyadminPort An override for the development environment's phpMyAdmin port.
* @property {?WPSource} coreSource An override for all environment's coreSource.
* @property {?string} phpVersion An override for all environment's PHP version.
* @property {?string} mariadbVersion An override for all environment's MariaDB version.
* @property {?Object.<string, string>} lifecycleScripts An override for various lifecycle scripts.
*/

Expand Down Expand Up @@ -65,6 +71,15 @@ module.exports = function getConfigFromEnvironmentVars( cacheDirectoryPath ) {
environmentConfig.phpVersion = process.env.WP_ENV_PHP_VERSION;
}

if ( process.env.WP_ENV_MARIADB_VERSION ) {
checkMariaDBVersion(
'environment variable',
'WP_ENV_MARIADB_VERSION',
process.env.WP_ENV_MARIADB_VERSION
);
environmentConfig.mariadbVersion = process.env.WP_ENV_MARIADB_VERSION;
}

return environmentConfig;
};

Expand Down
22 changes: 22 additions & 0 deletions packages/env/lib/config/parse-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const {
checkStringArray,
checkObjectWithValues,
checkVersion,
checkMariaDBVersion,
checkValidURL,
} = require( './validate-config' );
const getConfigFromEnvironmentVars = require( './get-config-from-environment-vars' );
Expand Down Expand Up @@ -51,6 +52,7 @@ const mergeConfigs = require( './merge-configs' );
* @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|null} phpVersion Version of PHP to use in the environments, of the format 0.0.
* @property {string|null} 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 @@ -79,6 +81,7 @@ const mergeConfigs = require( './merge-configs' );
const DEFAULT_ENVIRONMENT_CONFIG = {
core: null,
phpVersion: null,
mariadbVersion: null,
plugins: [],
themes: [],
port: 8888,
Expand Down Expand Up @@ -327,6 +330,13 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) {
overrideConfig.env.tests.phpVersion = overrides.phpVersion;
}

if ( overrides.mariadbVersion ) {
overrideConfig.mariadbVersion = overrides.mariadbVersion;
overrideConfig.env.development.mariadbVersion =
overrides.mariadbVersion;
overrideConfig.env.tests.mariadbVersion = overrides.mariadbVersion;
}

if ( overrides.multisite ) {
overrideConfig.multisite = overrides.multisite;
overrideConfig.env.development.multisite = overrides.multisite;
Expand Down Expand Up @@ -532,6 +542,18 @@ async function parseEnvironmentConfig(
parsedConfig.phpVersion = config.phpVersion;
}

if ( config.mariadbVersion !== undefined ) {
// Support null as a valid input.
if ( config.mariadbVersion !== null ) {
checkMariaDBVersion(
configFile,
`${ environmentPrefix }mariadbVersion`,
config.mariadbVersion
);
}
parsedConfig.mariadbVersion = config.mariadbVersion;
}

if ( config.core !== undefined ) {
parsedConfig.coreSource = includeTestsPath(
await parseCoreSource( config.core, options ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ exports[`Config Integration > should load local and override configuration files
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": 23306,
"phpVersion": null,
Expand Down Expand Up @@ -62,6 +63,7 @@ exports[`Config Integration > should load local and override configuration files
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": 23307,
"phpVersion": null,
Expand Down Expand Up @@ -115,6 +117,7 @@ exports[`Config Integration > should load local configuration file 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": 13306,
"phpVersion": null,
Expand Down Expand Up @@ -147,6 +150,7 @@ exports[`Config Integration > should load local configuration file 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": 23307,
"phpVersion": null,
Expand Down Expand Up @@ -200,6 +204,7 @@ exports[`Config Integration > should use default configuration 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": null,
"phpVersion": null,
Expand Down Expand Up @@ -232,6 +237,7 @@ exports[`Config Integration > should use default configuration 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": null,
"phpVersion": null,
Expand Down Expand Up @@ -285,6 +291,7 @@ exports[`Config Integration > should use environment variables over local and ov
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": 23306,
"phpVersion": null,
Expand Down Expand Up @@ -318,6 +325,7 @@ exports[`Config Integration > should use environment variables over local and ov
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"mariadbVersion": null,
"multisite": false,
"mysqlPort": 23307,
"phpVersion": null,
Expand Down
104 changes: 104 additions & 0 deletions packages/env/lib/config/test/parse-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const DEFAULT_CONFIG = {
phpmyadminPort: null,
multisite: false,
phpVersion: null,
mariadbVersion: null,
coreSource: {
type: 'git',
url: 'https://github.com/WordPress/WordPress.git',
Expand Down Expand Up @@ -104,6 +105,7 @@ describe( 'parseConfig', () => {
delete process.env.WP_ENV_TESTS_PORT;
delete process.env.WP_ENV_CORE;
delete process.env.WP_ENV_PHP_VERSION;
delete process.env.WP_ENV_MARIADB_VERSION;
delete process.env.WP_ENV_LIFECYCLE_SCRIPT_AFTER_START;
} );

Expand Down Expand Up @@ -612,4 +614,106 @@ describe( 'parseConfig', () => {
)
);
} );

it( 'should parse mariadbVersion at the root and per environment', async () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return {
mariadbVersion: '10.11',
env: {
tests: {
mariadbVersion: 'latest',
},
},
};
}

if ( configFile === '/test/gutenberg/.wp-env.override.json' ) {
return {};
}

throw new Error( 'Invalid File: ' + configFile );
} );

const parsed = await parseConfig( '/test/gutenberg', '/cache' );

expect( parsed.mariadbVersion ).toBe( '10.11' );
expect( parsed.env.tests.mariadbVersion ).toBe( 'latest' );
} );

it( 'should accept a null mariadbVersion', async () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return { mariadbVersion: null };
}

if ( configFile === '/test/gutenberg/.wp-env.override.json' ) {
return {};
}

throw new Error( 'Invalid File: ' + configFile );
} );

const parsed = await parseConfig( '/test/gutenberg', '/cache' );

expect( parsed.mariadbVersion ).toBeNull();
} );

it( 'should throw for an invalid mariadbVersion', async () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return { env: { tests: { mariadbVersion: 'LTS' } } };
}

if ( configFile === '/test/gutenberg/.wp-env.override.json' ) {
return {};
}

throw new Error( 'Invalid File: ' + configFile );
} );

await expect(
parseConfig( '/test/gutenberg', '/cache' )
).rejects.toEqual(
new ValidationError(
'Invalid /test/gutenberg/.wp-env.json: "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 () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return {
mariadbVersion: '10.11',
env: { tests: { mariadbVersion: 'latest' } },
};
}

if ( configFile === '/test/gutenberg/.wp-env.override.json' ) {
return {};
}

throw new Error( 'Invalid File: ' + configFile );
} );
process.env.WP_ENV_MARIADB_VERSION = '10.3';

const parsed = await parseConfig( '/test/gutenberg', '/cache' );

expect( parsed.mariadbVersion ).toBe( '10.3' );
expect( parsed.env.development.mariadbVersion ).toBe( '10.3' );
expect( parsed.env.tests.mariadbVersion ).toBe( '10.3' );
} );

it( 'should throw for an invalid WP_ENV_MARIADB_VERSION', async () => {
process.env.WP_ENV_MARIADB_VERSION = 'LTS';

await expect(
parseConfig( '/test/gutenberg', '/cache' )
).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".'
)
);
} );
} );
Loading
Loading