Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Env: add initial object cache support #55909

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 23 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
1 change: 1 addition & 0 deletions .wp-env.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"core": "WordPress/WordPress",
"plugins": [ "." ],
"themes": [ "./test/emptytheme" ],
"objectCache": "memcached",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for dogfooding, to remove before merge

"env": {
"tests": {
"mappings": {
Expand Down
21 changes: 11 additions & 10 deletions packages/env/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,16 +479,17 @@ You can customize the WordPress installation, plugins and themes that the develo

`.wp-env.json` supports fields for options applicable to both the tests and development instances.

| 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. |
| `"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. |
| `"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'. |
| `"testsPort"` | `integer` | `8889` | The port number for the test site. You'll access the instance through the port: 'http://localhost:8889'. |
| `"config"` | `Object` | See below. | Mapping of wp-config.php constants to their desired values. |
| `"mappings"` | `Object` | `"{}"` | Mapping of WordPress directories to local directories to be mounted in the WordPress instance. |
| 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. |
| `"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. |
| `"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'. |
| `"testsPort"` | `integer` | `8889` | The port number for the test site. You'll access the instance through the port: 'http://localhost:8889'. |
| `"config"` | `Object` | See below. | Mapping of wp-config.php constants to their desired values. |
| `"mappings"` | `Object` | `"{}"` | Mapping of WordPress directories to local directories to be mounted in the WordPress instance. |
| `"objectCache"` | `string` | `null` | Object cache to set up. Currently only supports `"memcached"` |

_Note: the port number environment variables (`WP_ENV_PORT` and `WP_ENV_TESTS_PORT`) take precedent over the .wp-env.json values._

Expand Down
46 changes: 45 additions & 1 deletion packages/env/lib/build-docker-compose-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ module.exports = function buildDockerComposeConfig( config ) {
const developmentPorts = `\${WP_ENV_PORT:-${ config.env.development.port }}:80`;
const testsPorts = `\${WP_ENV_TESTS_PORT:-${ config.env.tests.port }}:80`;

return {
const dockerComposeConfig = {
version: '3.7',
services: {
mysql: {
Expand Down Expand Up @@ -271,4 +271,48 @@ module.exports = function buildDockerComposeConfig( config ) {
'tests-user-home': {},
},
};

if ( config.env.development.objectCache ) {
dockerComposeConfig.services.wordpress.depends_on.push(
'object-cache'
);
dockerComposeConfig.services[ 'object-cache' ] = {
depends_on: [],
build: {
context: '.',
dockerfile: 'ObjectCache.Dockerfile',
args: imageBuildArgs,
},
volumes: developmentMounts,
user: hostUser.fullUser,
environment: {
...dbEnv.credentials,
...dbEnv.development,
},
extra_hosts: [ 'host.docker.internal:host-gateway' ],
};
}

if ( config.env.tests.objectCache ) {
dockerComposeConfig.services[ 'tests-wordpress' ].depends_on.push(
'tests-object-cache'
);
dockerComposeConfig.services[ 'tests-object-cache' ] = {
depends_on: [],
build: {
context: '.',
dockerfile: 'Tests-ObjectCache.Dockerfile',
args: imageBuildArgs,
},
volumes: testsMounts,
user: hostUser.fullUser,
environment: {
...dbEnv.credentials,
...dbEnv.tests,
},
extra_hosts: [ 'host.docker.internal:host-gateway' ],
};
}

return dockerComposeConfig;
};
35 changes: 34 additions & 1 deletion packages/env/lib/commands/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,45 @@ module.exports = async function start( {
spinner,
debug
);

if ( 'memcached' === config.env.development.objectCache ) {
// Set up object cache drop-in if configured.
const memcachedFile = path.resolve(
__dirname,
'../object-cache/memcached.php'
);

fs.copyFile(
memcachedFile,
path.join(
config.env.development.coreSource.path,
'wp-content',
'object-cache.php'
)
);

fs.copyFile(
memcachedFile,
path.join(
config.env.tests.coreSource.path,
'wp-content',
'object-cache.php'
)
);
}
}

spinner.text = 'Starting WordPress.';

await dockerCompose.upMany(
[ 'wordpress', 'tests-wordpress', 'cli', 'tests-cli' ],
[
'wordpress',
'tests-wordpress',
'cli',
'tests-cli',
'object-cache',
'tests-object-cache',
],
{
...dockerComposeConfig,
commandOptions: shouldConfigureWp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const { checkPort, checkVersion, checkString } = require( './validate-config' );
* @property {?number} testsPort An override for the testing environment's port.
* @property {?WPSource} coreSource An override for all environment's coreSource.
* @property {?string} phpVersion An override for all environment's PHP version.
* @property {?string} objectCache An override for all environment's object cache configuration.
* @property {?Object.<string, string>} lifecycleScripts An override for various lifecycle scripts.
*/

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 @@ -18,6 +18,7 @@ const {
checkStringArray,
checkObjectWithValues,
checkVersion,
checkOneOfStrings,
checkValidURL,
} = require( './validate-config' );
const getConfigFromEnvironmentVars = require( './get-config-from-environment-vars' );
Expand Down Expand Up @@ -53,6 +54,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} objectCache Type of object cache to set up. Supports "memcached" or none (null).
*/

/**
Expand Down Expand Up @@ -85,6 +87,7 @@ const DEFAULT_ENVIRONMENT_CONFIG = {
themes: [],
port: 8888,
testsPort: 8889,
objectCache: null,
mappings: {},
config: {
FS_METHOD: 'direct',
Expand Down Expand Up @@ -293,6 +296,12 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) {
overrideConfig.env.tests.phpVersion = overrides.phpVersion;
}

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

return overrideConfig;
}

Expand Down Expand Up @@ -455,6 +464,19 @@ async function parseEnvironmentConfig(
);
}

if ( config.objectCache !== undefined ) {
// Support null as a valid input.
if ( config.objectCache !== null ) {
checkOneOfStrings(
configFile,
`${ environmentPrefix }objectCache`,
config.objectCache,
[ 'memcached' ]
);
}
parsedConfig.objectCache = config.objectCache;
}

if ( config.plugins !== undefined ) {
checkStringArray(
configFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ exports[`Config Integration should load local and override configuration files 1
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 999,
Expand Down Expand Up @@ -57,6 +58,7 @@ exports[`Config Integration should load local and override configuration files 1
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 456,
Expand Down Expand Up @@ -102,6 +104,7 @@ exports[`Config Integration should load local configuration file 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 123,
Expand Down Expand Up @@ -130,6 +133,7 @@ exports[`Config Integration should load local configuration file 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 8889,
Expand Down Expand Up @@ -175,6 +179,7 @@ exports[`Config Integration should use default configuration 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 8888,
Expand Down Expand Up @@ -203,6 +208,7 @@ exports[`Config Integration should use default configuration 1`] = `
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 8889,
Expand Down Expand Up @@ -248,6 +254,7 @@ exports[`Config Integration should use environment variables over local and over
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 12345,
Expand Down Expand Up @@ -277,6 +284,7 @@ exports[`Config Integration should use environment variables over local and over
"url": "https://github.com/WordPress/WordPress.git",
},
"mappings": {},
"objectCache": null,
"phpVersion": null,
"pluginSources": [],
"port": 61234,
Expand Down
28 changes: 28 additions & 0 deletions packages/env/lib/config/test/parse-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const DEFAULT_CONFIG = {
WP_SITEURL: 'http://localhost',
WP_HOME: 'http://localhost',
},
objectCache: null,
mappings: {},
lifecycleScripts: {
afterStart: null,
Expand Down Expand Up @@ -389,5 +390,32 @@ describe( 'parseConfig', () => {
);
}
} );

it( 'throws for invalid object-cache config option', async () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return {
objectCache: 'doesnotexist',
};
}

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

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

expect.assertions( 1 );
try {
await parseConfig( '/test/gutenberg', '/cache' );
} catch ( error ) {
expect( error ).toEqual(
new ValidationError(
`Invalid /test/gutenberg/.wp-env.json: "objectCache" must be one of: "memcached".`
)
);
}
} );
} );
/* eslint-enable jest/no-conditional-expect */
27 changes: 27 additions & 0 deletions packages/env/lib/config/validate-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,32 @@ function checkString( configFile, configKey, value ) {
}
}

/**
* Validates the string is one of the supported options.
*
* @param {string} configFile The config file we're validating.
* @param {string} configKey The configuration key we're validating.
* @param {string} value The value to check.
* @param {string[]} options The supported options.
*/
function checkOneOfStrings( configFile, configKey, value, options ) {
if ( typeof value !== 'string' ) {
throw new ValidationError(
`Invalid ${ configFile }: "${ configKey }" must be a string.`
);
}

const validOptions = options
.map( ( option ) => `"${ option }"` )
.join( ',' );

if ( ! options.includes( value ) ) {
throw new ValidationError(
`Invalid ${ configFile }: "${ configKey }" must be one of: ${ validOptions }.`
);
}
}

/**
* Validates the port and throws if it isn't valid.
*
Expand Down Expand Up @@ -173,6 +199,7 @@ function checkValidURL( configFile, configKey, url ) {
module.exports = {
ValidationError,
checkString,
checkOneOfStrings,
checkPort,
checkStringArray,
checkObjectWithValues,
Expand Down
Loading
Loading