diff --git a/docker-compose.yml b/docker-compose.yml index 6cd25afb638ea..8b90b678a00a2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,7 +79,7 @@ services: - mysql:/var/lib/mysql # For compatibility with PHP versions that don't support the caching_sha2_password auth plugin used in MySQL 8.0. - command: --default-authentication-plugin=mysql_native_password + command: ${LOCAL_DB_AUTH_OPTION-} healthcheck: test: [ "CMD-SHELL", "if [ \"$LOCAL_DB_TYPE\" = \"mariadb\" ]; then mariadb-admin ping -h localhost; else mysqladmin ping -h localhost; fi" ] diff --git a/tools/local-env/mysql-old-php.conf b/tools/local-env/mysql-old-php.conf new file mode 100644 index 0000000000000..ae1cb9b72a7f5 --- /dev/null +++ b/tools/local-env/mysql-old-php.conf @@ -0,0 +1,20 @@ +## +# The local Docker environment will try to use the database software's default authentication plugin whenever possible. +# +# One exception to this is using PHP 7.2 & 7.3 in combination with MySQL >= 8.0. These versions of PHP lack support for +# MySQL's caching_sha2_password plugin, which was made the new default in MySQL 8.0. +# +# Until MySQL 8.4, this could easily be changed using the --default-authentication-plugin with the old value of +# mysql_native_password. +# +# In MySQL 8.4, the --default-authentication-plugin option was removed in favor of --authentication-policy and +# mysql_native_password was disabled by default. +# +# When mounted to the database container in the local Docker environment, this file turns the old authentication plugin +# back on so that PHP 7.2 & 7.3 can be used in combination with MySQL 8.4. +# +# MySQL 9.0 will remove mysql_native_password. +## + +[mysqld] +mysql-native-password=ON diff --git a/tools/local-env/old-php-mysql-84.override.yml b/tools/local-env/old-php-mysql-84.override.yml new file mode 100644 index 0000000000000..3eca65f3c1c0e --- /dev/null +++ b/tools/local-env/old-php-mysql-84.override.yml @@ -0,0 +1,5 @@ +services: + + mysql: + volumes: + - ./tools/local-env/mysql-old-php.conf:/etc/mysql/conf.d/config-file.cnf diff --git a/tools/local-env/scripts/docker.js b/tools/local-env/scripts/docker.js index b33fc2b3ed0e3..078ce89f916a6 100644 --- a/tools/local-env/scripts/docker.js +++ b/tools/local-env/scripts/docker.js @@ -1,8 +1,11 @@ const dotenv = require( 'dotenv' ); const dotenvExpand = require( 'dotenv-expand' ); const { execSync } = require( 'child_process' ); +const local_env_utils = require( './utils' ); dotenvExpand.expand( dotenv.config() ); +const composeFiles = local_env_utils.get_compose_files(); + // Execute any docker compose command passed to this script. -execSync( 'docker compose ' + process.argv.slice( 2 ).join( ' ' ), { stdio: 'inherit' } ); +execSync( 'docker compose ' + composeFiles + ' ' + process.argv.slice( 2 ).join( ' ' ), { stdio: 'inherit' } ); diff --git a/tools/local-env/scripts/install.js b/tools/local-env/scripts/install.js index 7bc2915fd44b7..519fc37a0d258 100644 --- a/tools/local-env/scripts/install.js +++ b/tools/local-env/scripts/install.js @@ -3,9 +3,14 @@ const dotenvExpand = require( 'dotenv-expand' ); const wait_on = require( 'wait-on' ); const { execSync } = require( 'child_process' ); const { renameSync, readFileSync, writeFileSync } = require( 'fs' ); +const { utils } = require( './utils.js' ); +const local_env_utils = require( './utils' ); dotenvExpand.expand( dotenv.config() ); +// Determine if a non-default database authentication plugin needs to be used. +local_env_utils.determine_auth_option(); + // Create wp-config.php. wp_cli( 'config create --dbname=wordpress_develop --dbuser=root --dbpass=password --dbhost=mysql --path=/var/www/src --force' ); @@ -48,7 +53,9 @@ wait_on( { resources: [ `tcp:localhost:${process.env.LOCAL_PORT}`] } ) * @param {string} cmd The WP-CLI command to run. */ function wp_cli( cmd ) { - execSync( `docker compose run --rm cli ${cmd}`, { stdio: 'inherit' } ); + const composeFiles = local_env_utils.get_compose_files(); + + execSync( `docker compose ${composeFiles} run --rm cli ${cmd}`, { stdio: 'inherit' } ); } /** @@ -56,7 +63,8 @@ function wp_cli( cmd ) { */ function install_wp_importer() { const testPluginDirectory = 'tests/phpunit/data/plugins/wordpress-importer'; + const composeFiles = local_env_utils.get_compose_files(); - execSync( `docker compose exec -T php rm -rf ${testPluginDirectory}`, { stdio: 'inherit' } ); - execSync( `docker compose exec -T php git clone https://github.com/WordPress/wordpress-importer.git ${testPluginDirectory} --depth=1`, { stdio: 'inherit' } ); + execSync( `docker compose ${composeFiles} exec -T php rm -rf ${testPluginDirectory}`, { stdio: 'inherit' } ); + execSync( `docker compose ${composeFiles} exec -T php git clone https://github.com/WordPress/wordpress-importer.git ${testPluginDirectory} --depth=1`, { stdio: 'inherit' } ); } diff --git a/tools/local-env/scripts/start.js b/tools/local-env/scripts/start.js index 92fa3601499c8..ef7fb7b7d4360 100644 --- a/tools/local-env/scripts/start.js +++ b/tools/local-env/scripts/start.js @@ -1,6 +1,7 @@ const dotenv = require( 'dotenv' ); const dotenvExpand = require( 'dotenv-expand' ); const { execSync } = require( 'child_process' ); +const local_env_utils = require( './utils' ); const { constants, copyFile } = require( 'node:fs' ); // Copy the default .env file when one is not present. @@ -10,6 +11,11 @@ copyFile( '.env.example', '.env', constants.COPYFILE_EXCL, (e) => { dotenvExpand.expand( dotenv.config() ); +const composeFiles = local_env_utils.get_compose_files(); + +// Determine if a non-default database authentication plugin needs to be used. +local_env_utils.determine_auth_option(); + // Check if the Docker service is running. try { execSync( 'docker info' ); @@ -25,7 +31,7 @@ try { const containers = ( process.env.LOCAL_PHP_MEMCACHED === 'true' ) ? 'wordpress-develop memcached' : 'wordpress-develop'; -execSync( `docker compose up -d ${containers}`, { stdio: 'inherit' } ); +execSync( `docker compose ${composeFiles} up -d ${containers}`, { stdio: 'inherit' } ); // If Docker Toolbox is being used, we need to manually forward LOCAL_PORT to the Docker VM. if ( process.env.DOCKER_TOOLBOX_INSTALL_PATH ) { diff --git a/tools/local-env/scripts/utils.js b/tools/local-env/scripts/utils.js new file mode 100644 index 0000000000000..88243b3413268 --- /dev/null +++ b/tools/local-env/scripts/utils.js @@ -0,0 +1,53 @@ +const local_env_utils = { + + /** + * Determines which Docker compose files are required to properly configure the local environment given the + * specified PHP version, database type, and database version. + * + * By default, only the standard docker-compose.yml file will be used. + * + * When PHP 7.2 or 7.3 is used in combination with MySQL 8.4, an override file will also be returned to ensure + * that the mysql_native_password plugin authentication plugin is on and available for use. + */ + get_compose_files: function() { + var composeFiles = '-f docker-compose.yml'; + + if ( process.env.LOCAL_DB_TYPE !== 'mysql' ) { + return composeFiles; + } + + if ( process.env.LOCAL_PHP !== '7.2-fpm' && process.env.LOCAL_PHP !== '7.3-fpm' ) { + return composeFiles; + } + + // PHP 7.2/7.3 in combination with MySQL 8.4 requires additional configuration to function properly. + if ( process.env.LOCAL_DB_VERSION === '8.4' ) { + composeFiles = composeFiles + ' -f tools/local-env/old-php-mysql-84.override.yml'; + } + + return composeFiles; + }, + + /** + * Determines the option to pass for proper authentication plugin configuration given the specified PHP version, + * database type, and database version. + */ + determine_auth_option: function() { + if ( process.env.LOCAL_DB_TYPE !== 'mysql' ) { + return; + } + + if ( process.env.LOCAL_PHP !== '7.2-fpm' && process.env.LOCAL_PHP !== '7.3-fpm' ) { + return; + } + + // MySQL 8.4 removed --default-authentication-plugin in favor of --authentication-policy. + if ( process.env.LOCAL_DB_VERSION === '8.4' ) { + process.env.LOCAL_DB_AUTH_OPTION = '--authentication-policy=mysql_native_password'; + } else { + process.env.LOCAL_DB_AUTH_OPTION = '--default-authentication-plugin=mysql_native_password'; + } + } +}; + +module.exports = local_env_utils;