Skip to content

Commit

Permalink
wp-env: Add phpMyAdmin support (WordPress#67588)
Browse files Browse the repository at this point in the history
* wp-env: Add phpMyAdmin support

Defines two new docker-compose services: `phpmyadmin` and
`tests-phpmyadmin`. These are off by default. They can be individually
turned on by:

- Specifying a port in any enviroment's config via key `phpmyadminPort`
  (see bottom of commit message for example).
- By setting environment variable `WP_ENV_PHPMYADMIN_PORT` and/or
  `WP_ENV_TESTS_PHPMYADMIN_PORT`.

* Opt into the phpMyAdmin service in the Gutenberg environment

* wp-env: start: refactor computation of command output

- Refactor repeating logic into getPublicDockerPort
- Remove trailing newlines from dockerCompose output
- Refactor evaluation of spinner.prefixText so as to clearly reveal
  newlines.

{
  env: {
    development: {
      ...
      phpmyadminPort: 9000
    },
    tests: {
      ...
    }
  }
}

---------

Co-authored-by: Riad Benguella <[email protected]>
  • Loading branch information
2 people authored and yogeshbhutkar committed Dec 18, 2024
1 parent c5434f9 commit 722ba4f
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 26 deletions.
3 changes: 3 additions & 0 deletions .wp-env.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"plugins": [ "." ],
"themes": [ "./test/emptytheme" ],
"env": {
"development": {
"phpmyadminPort": 9000
},
"tests": {
"mappings": {
"wp-content/plugins/gutenberg": ".",
Expand Down
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

### Enhancements

- Add phpMyAdmin as an optional service. Enabled via the new `phpmyadminPort` environment config, as well as env vars `WP_ENV_PHPMYADMIN_PORT` and `WP_ENV_TESTS_PHPMYADMIN_PORT`.

## 10.13.0 (2024-11-27)

## 10.12.0 (2024-11-16)
Expand Down
2 changes: 1 addition & 1 deletion packages/env/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ containers.
Positionals:
container The Docker service to run the command on.
[string] [required] [choices: "mysql", "tests-mysql", "wordpress",
"tests-wordpress", "cli", "tests-cli", "composer", "phpunit"]
"tests-wordpress", "cli", "tests-cli", "composer", "phpmyadmin"]
command The command to run. [required]
Options:
Expand Down
27 changes: 27 additions & 0 deletions packages/env/lib/build-docker-compose-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ module.exports = function buildDockerComposeConfig( config ) {
config.env.tests.mysqlPort ?? ''
}}:3306`;

const developmentPhpmyadminPorts = `\${WP_ENV_PHPMYADMIN_PORT:-${
config.env.development.phpmyadminPort ?? ''
}}:80`;
const testsPhpmyadminPorts = `\${WP_ENV_TESTS_PHPMYADMIN_PORT:-${
config.env.tests.phpmyadminPort ?? ''
}}:80`;

return {
services: {
mysql: {
Expand Down Expand Up @@ -266,6 +273,26 @@ module.exports = function buildDockerComposeConfig( config ) {
},
extra_hosts: [ 'host.docker.internal:host-gateway' ],
},
phpmyadmin: {
image: 'phpmyadmin',
ports: [ developmentPhpmyadminPorts ],
environment: {
PMA_PORT: 3306,
PMA_HOST: 'mysql',
PMA_USER: 'root',
PMA_PASSWORD: 'password',
},
},
'tests-phpmyadmin': {
image: 'phpmyadmin',
ports: [ testsPhpmyadminPorts ],
environment: {
PMA_PORT: 3306,
PMA_HOST: 'tests-mysql',
PMA_USER: 'root',
PMA_PASSWORD: 'password',
},
},
},
volumes: {
...( ! config.env.development.coreSource && { wordpress: {} } ),
Expand Down
76 changes: 60 additions & 16 deletions packages/env/lib/commands/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,24 @@ module.exports = async function start( {
}
);

if ( config.env.development.phpmyadminPort ) {
await dockerCompose.upOne( 'phpmyadmin', {
...dockerComposeConfig,
commandOptions: shouldConfigureWp
? [ '--build', '--force-recreate' ]
: [],
} );
}

if ( config.env.tests.phpmyadminPort ) {
await dockerCompose.upOne( 'tests-phpmyadmin', {
...dockerComposeConfig,
commandOptions: shouldConfigureWp
? [ '--build', '--force-recreate' ]
: [],
} );
}

// Make sure we've consumed the custom CLI dockerfile.
if ( shouldConfigureWp ) {
await dockerCompose.buildOne( [ 'cli' ], { ...dockerComposeConfig } );
Expand Down Expand Up @@ -225,35 +243,61 @@ module.exports = async function start( {
const siteUrl = config.env.development.config.WP_SITEURL;
const testsSiteUrl = config.env.tests.config.WP_SITEURL;

const { out: mySQLAddress } = await dockerCompose.port(
const mySQLPort = await getPublicDockerPort(
'mysql',
3306,
dockerComposeConfig
);
const mySQLPort = mySQLAddress.split( ':' ).pop();

const { out: testsMySQLAddress } = await dockerCompose.port(
const testsMySQLPort = await getPublicDockerPort(
'tests-mysql',
3306,
dockerComposeConfig
);
const testsMySQLPort = testsMySQLAddress.split( ':' ).pop();

spinner.prefixText = 'WordPress development site started'
.concat( siteUrl ? ` at ${ siteUrl }` : '.' )
.concat( '\n' )
.concat( 'WordPress test site started' )
.concat( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' )
.concat( '\n' )
.concat( `MySQL is listening on port ${ mySQLPort }` )
.concat(
`MySQL for automated testing is listening on port ${ testsMySQLPort }`
)
.concat( '\n' );

const phpmyadminPort = config.env.development.phpmyadminPort
? await getPublicDockerPort( 'phpmyadmin', 80, dockerComposeConfig )
: null;

const testsPhpmyadminPort = config.env.tests.phpmyadminPort
? await getPublicDockerPort(
'tests-phpmyadmin',
80,
dockerComposeConfig
)
: null;

spinner.prefixText = [
'WordPress development site started' +
( siteUrl ? ` at ${ siteUrl }` : '.' ),
'WordPress test site started' +
( testsSiteUrl ? ` at ${ testsSiteUrl }` : '.' ),
`MySQL is listening on port ${ mySQLPort }`,
`MySQL for automated testing is listening on port ${ testsMySQLPort }`,
phpmyadminPort &&
`phpMyAdmin started at http://localhost:${ phpmyadminPort }`,
testsPhpmyadminPort &&
`phpMyAdmin for automated testing started at http://localhost:${ testsPhpmyadminPort }`,
]
.filter( Boolean )
.join( '\n' );
spinner.prefixText += '\n\n';
spinner.text = 'Done!';
};

async function getPublicDockerPort(
service,
containerPort,
dockerComposeConfig
) {
const { out: address } = await dockerCompose.port(
service,
containerPort,
dockerComposeConfig
);
return address.split( ':' ).pop().trim();
}

/**
* Checks for legacy installs and provides
* the user the option to delete them.
Expand Down
7 changes: 7 additions & 0 deletions packages/env/lib/config/get-config-from-environment-vars.js
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} mysqlPort An override for the development environment's MySQL port.
* @property {?number} testsPort An override for the testing environment's port.
* @property {?number} testsMysqlPort An override for the testing environment's MySQL port.
* @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 {?Object.<string, string>} lifecycleScripts An override for various lifecycle scripts.
Expand All @@ -40,6 +41,12 @@ module.exports = function getConfigFromEnvironmentVars( cacheDirectoryPath ) {
testsMysqlPort: getPortFromEnvironmentVariable(
'WP_ENV_TESTS_MYSQL_PORT'
),
phpmyadminPort: getPortFromEnvironmentVariable(
'WP_ENV_PHPMYADMIN_PORT'
),
testsPhpmyadminPort: getPortFromEnvironmentVariable(
'WP_ENV_TESTS_PHPMYADMIN_PORT'
),
lifecycleScripts: getLifecycleScriptOverrides(),
};

Expand Down
27 changes: 19 additions & 8 deletions packages/env/lib/config/parse-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ const mergeConfigs = require( './merge-configs' );
* The environment-specific configuration options. (development/tests/etc)
*
* @typedef WPEnvironmentConfig
* @property {WPSource} coreSource The WordPress installation to load in the environment.
* @property {WPSource[]} pluginSources Plugins to load in the environment.
* @property {WPSource[]} themeSources Themes to load in the environment.
* @property {number} port The port to use.
* @property {number} mysqlPort The port to use for MySQL. Random if empty.
* @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 {WPSource} coreSource The WordPress installation to load in the environment.
* @property {WPSource[]} pluginSources Plugins to load in the environment.
* @property {WPSource[]} themeSources Themes to load in the environment.
* @property {number} port The port to use.
* @property {number} mysqlPort The port to use for MySQL. Random if empty.
* @property {number} phpmyadminPort The port to use for phpMyAdmin. If empty, disabled phpMyAdmin.
* @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.
*/

/**
Expand Down Expand Up @@ -87,6 +88,7 @@ const DEFAULT_ENVIRONMENT_CONFIG = {
port: 8888,
testsPort: 8889,
mysqlPort: null,
phpmyadminPort: null,
mappings: {},
config: {
FS_METHOD: 'direct',
Expand Down Expand Up @@ -282,6 +284,11 @@ function getEnvironmentVarOverrides( cacheDirectoryPath ) {
overrideConfig.env.development.mysqlPort = overrides.mysqlPort;
}

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

if ( overrides.testsPort ) {
overrideConfig.testsPort = overrides.testsPort;
overrideConfig.env.tests.port = overrides.testsPort;
Expand Down Expand Up @@ -455,6 +462,10 @@ async function parseEnvironmentConfig(
parsedConfig.mysqlPort = config.mysqlPort;
}

if ( config.phpmyadminPort !== undefined ) {
parsedConfig.phpmyadminPort = config.phpmyadminPort;
}

if ( config.phpVersion !== undefined ) {
// Support null as a valid input.
if ( config.phpVersion !== null ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ exports[`Config Integration should load local and override configuration files 1
"mappings": {},
"mysqlPort": 23306,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 999,
"themeSources": [],
Expand Down Expand Up @@ -60,6 +61,7 @@ exports[`Config Integration should load local and override configuration files 1
"mappings": {},
"mysqlPort": 23307,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 456,
"themeSources": [],
Expand Down Expand Up @@ -106,6 +108,7 @@ exports[`Config Integration should load local configuration file 1`] = `
"mappings": {},
"mysqlPort": 13306,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 123,
"themeSources": [],
Expand Down Expand Up @@ -135,6 +138,7 @@ exports[`Config Integration should load local configuration file 1`] = `
"mappings": {},
"mysqlPort": 23307,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 8889,
"themeSources": [],
Expand Down Expand Up @@ -181,6 +185,7 @@ exports[`Config Integration should use default configuration 1`] = `
"mappings": {},
"mysqlPort": null,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 8888,
"themeSources": [],
Expand Down Expand Up @@ -210,6 +215,7 @@ exports[`Config Integration should use default configuration 1`] = `
"mappings": {},
"mysqlPort": null,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 8889,
"themeSources": [],
Expand Down Expand Up @@ -256,6 +262,7 @@ exports[`Config Integration should use environment variables over local and over
"mappings": {},
"mysqlPort": 23306,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 12345,
"testsPort": 61234,
Expand Down Expand Up @@ -286,6 +293,7 @@ exports[`Config Integration should use environment variables over local and over
"mappings": {},
"mysqlPort": 23307,
"phpVersion": null,
"phpmyadminPort": null,
"pluginSources": [],
"port": 61234,
"testsPort": 61234,
Expand Down
54 changes: 54 additions & 0 deletions packages/env/lib/config/test/parse-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const DEFAULT_CONFIG = {
port: 8888,
testsPort: 8889,
mysqlPort: null,
phpmyadminPort: null,
phpVersion: null,
coreSource: {
type: 'git',
Expand Down Expand Up @@ -400,4 +401,57 @@ describe( 'parseConfig', () => {
)
);
} );

it( 'should parse phpmyadmin configuration for a given environment', async () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return {
core: 'WordPress/WordPress#Test',
phpVersion: '1.0',
lifecycleScripts: {
afterStart: 'test',
},
env: {
development: {
phpmyadminPort: 9001,
},
},
};
}
} );

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

const expected = {
development: {
...DEFAULT_CONFIG.env.development,
phpmyadminPort: 9001,
},
tests: DEFAULT_CONFIG.env.tests,
};
expect( parsed.env ).toEqual( expected );
} );

it( 'should ignore root-level configuration for phpmyadmin', async () => {
readRawConfigFile.mockImplementation( async ( configFile ) => {
if ( configFile === '/test/gutenberg/.wp-env.json' ) {
return {
core: 'WordPress/WordPress#Test',
phpVersion: '1.0',
lifecycleScripts: {
afterStart: 'test',
},
phpmyadminPort: 9001,
};
}
} );

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

const expected = {
development: DEFAULT_CONFIG.env.development,
tests: DEFAULT_CONFIG.env.tests,
};
expect( parsed.env ).toEqual( expected );
} );
} );
1 change: 1 addition & 0 deletions packages/env/lib/validate-run-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const RUN_CONTAINERS = [
'tests-wordpress',
'cli',
'tests-cli',
'phpmyadmin',
];

/**
Expand Down
Loading

0 comments on commit 722ba4f

Please sign in to comment.