diff --git a/.travis.yml b/.travis.yml index 99f72bbbd5f4e5..66adf18ee3e9c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ branches: env: global: - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true - - WP_DEVELOP_DIR: ./wordpress - LOCAL_SCRIPT_DEBUG: false - INSTALL_COMPOSER: false - INSTALL_WORDPRESS: true @@ -46,39 +45,7 @@ install: - npm run build - | if [[ "$INSTALL_WORDPRESS" = "true" ]]; then - # Download and unpack WordPress. - curl -sL https://wordpress.org/nightly-builds/wordpress-latest.zip -o /tmp/wordpress-latest.zip - unzip -q /tmp/wordpress-latest.zip -d /tmp - mkdir -p wordpress/src - mv /tmp/wordpress/* wordpress/src - - # Create the upload directory with permissions that Travis can handle. - mkdir -p wordpress/src/wp-content/uploads - chmod 767 wordpress/src/wp-content/uploads - - # Grab the tools we need for WordPress' local-env. - curl -sL https://github.com/WordPress/wordpress-develop/archive/master.zip -o /tmp/wordpress-develop.zip - unzip -q /tmp/wordpress-develop.zip -d /tmp - mv \ - /tmp/wordpress-develop-master/tools \ - /tmp/wordpress-develop-master/tests \ - /tmp/wordpress-develop-master/.env \ - /tmp/wordpress-develop-master/docker-compose.yml \ - /tmp/wordpress-develop-master/wp-cli.yml \ - /tmp/wordpress-develop-master/*config-sample.php \ - /tmp/wordpress-develop-master/package.json wordpress - - # Install WordPress. - cd wordpress - npm install dotenv wait-on - npm run env:start - sleep 10 - npm run env:install - cd .. - - # Connect Gutenberg to WordPress. - npm run env connect - npm run env cli plugin activate gutenberg + npm run env install fi - | if [[ "$INSTALL_COMPOSER" = "true" ]]; then diff --git a/package-lock.json b/package-lock.json index d7586bbb615730..9fef52585124ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5318,11 +5318,11 @@ "@wordpress/eslint-plugin": "file:packages/eslint-plugin", "@wordpress/jest-preset-default": "file:packages/jest-preset-default", "@wordpress/npm-package-json-lint-config": "file:packages/npm-package-json-lint-config", + "appdata-path": "^1.0.0", "babel-jest": "^24.7.1", "babel-loader": "^8.0.5", "chalk": "^2.4.1", "check-node-version": "^3.1.1", - "command-exists": "1.2.8", "cross-spawn": "^5.1.0", "decompress-zip": "0.2.2", "eslint": "^6.1.0", @@ -5792,6 +5792,12 @@ "normalize-path": "^2.1.1" } }, + "appdata-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/appdata-path/-/appdata-path-1.0.0.tgz", + "integrity": "sha512-ZbH3ezXfnT/YE3NdqduIt4lBV+H0ybvA2Qx3K76gIjQvh8gROpDFdDLpx6B1QJtW7zxisCbpTlCLhKqoR8cDBw==", + "dev": true + }, "append-transform": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 73710a869261e3..f962738f25d83d 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -37,11 +37,11 @@ "@wordpress/eslint-plugin": "file:../eslint-plugin", "@wordpress/jest-preset-default": "file:../jest-preset-default", "@wordpress/npm-package-json-lint-config": "file:../npm-package-json-lint-config", + "appdata-path": "^1.0.0", "babel-jest": "^24.7.1", "babel-loader": "^8.0.5", "chalk": "^2.4.1", "check-node-version": "^3.1.1", - "command-exists": "1.2.8", "cross-spawn": "^5.1.0", "decompress-zip": "0.2.2", "eslint": "^6.1.0", diff --git a/packages/scripts/scripts/env.js b/packages/scripts/scripts/env.js index 000a4fca2e270f..0cb7ecb7ae6dc2 100644 --- a/packages/scripts/scripts/env.js +++ b/packages/scripts/scripts/env.js @@ -6,15 +6,17 @@ const chalk = require( 'chalk' ); /** * Node dependencies. */ -const { env, exit, stdout, cwd } = require( 'process' ); +const { env, exit, stdout } = require( 'process' ); const { normalize } = require( 'path' ); const { existsSync } = require( 'fs' ); +const { userInfo } = require( 'os' ); /** * Internal dependencies */ const { getArgsFromCLI, + getManagedWordPressPath, spawnScript, } = require( '../utils' ); @@ -23,22 +25,18 @@ const args = getArgsFromCLI(); if ( ! args.length ) { const scripts = { install: "If you don't have a check out of the WordPress repository that you want to work with, this will automatically download, configure, and connect to WordPress.", - connect: 'If you have a WordPress respository already, define the ' + chalk.magenta( 'WP_DEVELOP_DIR' ) + ' environment variable with the path to your repository, then run this command to add this plugin to it.', + connect: chalk`If you have a WordPress respository already, define the {magenta WP_DEVELOP_DIR} environment variable with the path to your repository, then run this command to add this plugin to it.`, start: "This will start a container that you've already installed and connected to.", stop: "And this will stop it when you're done!", - update: 'If you used ' + chalk.blue( 'npm run env install' ) + ' to setup WordPress, run this command to update it.', + update: chalk`If you used {blue npm run env install} to setup WordPress, run this command to update it.`, reinstall: 'Resets the database and re-configures WordPress again.', cli: 'Run WP-CLI commands against the WordPress install.', 'lint-php': 'Run PHPCS linting on the plugin.', 'test-php': "Run the plugin's PHPUnit tests.", - 'docker-run': 'For more advanced debugging, you may sometimes need to run commands in the Docker containers. This is the equivalent of running ' + chalk.blue( 'docker-compose run' ) + '.', + 'docker-run': chalk`For more advanced debugging, you may sometimes need to run commands in the Docker containers. This is the equivalent of running {blue docker-compose run}.`, }; - stdout.write( chalk.white( 'Welcome to the WordPress Local Environment! There are several commands available to help you get up and running. Each of these commands should be run after ' ) ); - stdout.write( chalk.blue( 'npm run env' ) ); - stdout.write( chalk.white( '. For example, ' ) ); - stdout.write( chalk.blue( 'npm run env install' ) ); - stdout.write( chalk.white( '.\n\n' ) ); + stdout.write( chalk`{white Welcome to the WordPress Local Environment! There are several commands available to help you get up and running. Each of these commands should be run after {blue npm run env}. For example, {blue npm run env install}.}\n\n` ); Object.keys( scripts ).forEach( ( script ) => { stdout.write( chalk.green( script ) + '\n ' + chalk.white( scripts[ script ] ) + '\n\n' ); @@ -46,15 +44,25 @@ if ( ! args.length ) { exit( 0 ); } +const user = userInfo(); + +if ( ! env.PHP_FPM_UID && user.uid > 0 ) { + env.PHP_FPM_UID = user.uid; +} + +if ( ! env.PHP_FPM_GID && user.gid > 0 ) { + env.PHP_FPM_GID = user.gid; +} + const command = args.shift(); if ( ! env.WP_DEVELOP_DIR && command !== 'install' ) { - if ( existsSync( normalize( cwd() + '/wordpress/wp-config-sample.php' ) ) ) { - env.WP_DEVELOP_DIR = normalize( cwd() + '/wordpress' ); + if ( existsSync( normalize( getManagedWordPressPath() + '/wp-config.php' ) ) ) { + env.WP_DEVELOP_DIR = getManagedWordPressPath(); env.MANAGED_WP = true; } else { - stdout.write( chalk.white( 'Please ensure the WP_DEVELOP_DIR environment variable is set to your WordPress Development directory before running this script.\n\n' ) ); - stdout.write( chalk.white( "If you don't have a WordPress Development directory to use, run `npm run env install` to automatically configure one!\n" ) ); + stdout.write( chalk`{white Please ensure the {magenta WP_DEVELOP_DIR} environment variable is set to your WordPress Development directory before running this script.}\n\n` ); + stdout.write( chalk`{white If you don't have a WordPress Development directory to use, run {blue npm run env install} to automatically configure one!}\n` ); exit( 1 ); } } diff --git a/packages/scripts/scripts/env/connect.js b/packages/scripts/scripts/env/connect.js index a18bdf5c323740..86b56f04f53b28 100644 --- a/packages/scripts/scripts/env/connect.js +++ b/packages/scripts/scripts/env/connect.js @@ -16,6 +16,7 @@ const { execSync } = require( 'child_process' ); */ const { fromConfigRoot, + hasArgInCLI, mergeYAMLConfigs, } = require( '../../utils' ); @@ -71,7 +72,9 @@ const mergedCompose = mergeYAMLConfigs( compose, pluginCompose, pluginMountDir ) writeFileSync( composeFile, yaml.safeDump( mergedCompose, { lineWidth: -1 } ) ); -stdout.write( 'Restarting the WordPress environment...\n' ); +if ( ! hasArgInCLI( '--no-restart' ) ) { + stdout.write( 'Restarting the WordPress environment...\n' ); -execSync( 'npm run env:stop', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); -execSync( 'npm run env:start', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); + execSync( 'npm run env:stop', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); + execSync( 'npm run env:start', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); +} diff --git a/packages/scripts/scripts/env/install.js b/packages/scripts/scripts/env/install.js index 7eee086a05d84e..035d378f8e1333 100644 --- a/packages/scripts/scripts/env/install.js +++ b/packages/scripts/scripts/env/install.js @@ -1,13 +1,12 @@ /** * External dependencies */ -const { sync: commandExistsSync } = require( 'command-exists' ); +const chalk = require( 'chalk' ); /** - * Node dependencies. + * Node dependencies */ -const { execSync } = require( 'child_process' ); -const { env, exit, cwd, stdout } = require( 'process' ); +const { env, exit, stdout } = require( 'process' ); const { normalize } = require( 'path' ); const { existsSync } = require( 'fs' ); @@ -16,29 +15,24 @@ const { existsSync } = require( 'fs' ); */ const { buildWordPress, - downloadWordPressZip, + getManagedWordPressPath, + hasArgInCLI, + installManagedWordPress, } = require( '../../utils' ); -const { hasArgInCLI } = require( '../../utils' ); -env.WP_DEVELOP_DIR = normalize( cwd() + '/wordpress' ); +env.WP_DEVELOP_DIR = getManagedWordPressPath(); if ( hasArgInCLI( '--fast' ) ) { buildWordPress( true, true ); return; } -if ( existsSync( normalize( cwd() + '/wordpress/wp-config-sample.php' ) ) ) { - stdout.write( 'It looks like WordPress is already installed, please delete the `wordpress` directory for a fresh install, or run `npm run env start` to start the existing environment.\n' ); +if ( existsSync( normalize( env.WP_DEVELOP_DIR + '/wp-config.php' ) ) ) { + stdout.write( chalk`{white It looks like WordPress is already installed, please run {blue npm run env clean} for a fresh install, or run {blue npm run env start} to start the existing environment.}\n` ); exit( 1 ); } -if ( commandExistsSync( 'git' ) ) { - execSync( 'git clone --depth=1 git://develop.git.wordpress.org/ wordpress', { stdio: 'inherit' } ); - buildWordPress( true, false ); -} else { - stdout.write( "Git isn't available. Switching to downloading a zip version.\n" ); - downloadWordPressZip() - .then( () => { - buildWordPress( true, false ); - } ); -} +installManagedWordPress() + .then( () => { + buildWordPress( true, false ); + } ); diff --git a/packages/scripts/scripts/env/start.js b/packages/scripts/scripts/env/start.js index b563b897ba0c81..e5e16a67675ac8 100644 --- a/packages/scripts/scripts/env/start.js +++ b/packages/scripts/scripts/env/start.js @@ -1,24 +1,20 @@ -/** - * External dependencies - */ -const { sync: commandExistsSync } = require( 'command-exists' ); /** - * Node dependencies. + * Node dependencies */ const { execSync } = require( 'child_process' ); const { env, stdout } = require( 'process' ); const { normalize } = require( 'path' ); const { statSync } = require( 'fs' ); +/** + * Internal dependencies + */ +const { getManagedWordPressPath } = require( '../../utils' ); + if ( env.MANAGED_WP ) { // We're running in our managed WordPress environment, so check if we need to update. - let stat; - if ( false && commandExistsSync( 'git' ) ) { - stat = statSync( normalize( env.WP_DEVELOP_DIR + '/.git' ) ); - } else { - stat = statSync( normalize( env.WP_DEVELOP_DIR + '/wp-config-sample.php' ) ); - } + const stat = statSync( normalize( getManagedWordPressPath() + '/src/wp-config-sample.php' ) ); const lastUpdated = new Date( stat.mtimeMs ); if ( Date.now() - lastUpdated.getTime() > 7 * 24 * 60 * 60 * 1000 ) { diff --git a/packages/scripts/scripts/env/update.js b/packages/scripts/scripts/env/update.js index f912992f0b115f..2ef3d31a07b92b 100644 --- a/packages/scripts/scripts/env/update.js +++ b/packages/scripts/scripts/env/update.js @@ -1,13 +1,7 @@ -/** - * External dependencies - */ -const { sync: commandExistsSync } = require( 'command-exists' ); - /** * Node dependencies. */ -const { execSync } = require( 'child_process' ); -const { env, cwd, stdout } = require( 'process' ); +const { env, cwd } = require( 'process' ); const { normalize } = require( 'path' ); /** @@ -15,18 +9,12 @@ const { normalize } = require( 'path' ); */ const { buildWordPress, - downloadWordPressZip, + installManagedWordPress, } = require( '../../utils' ); env.WP_DEVELOP_DIR = normalize( cwd() + '/wordpress' ); -if ( commandExistsSync( 'git' ) ) { - execSync( 'git pull', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); - buildWordPress( false, false ); -} else { - stdout.write( "Git isn't available. Switching to downloading a zip version.\n" ); - downloadWordPressZip() - .then( () => { - buildWordPress( false, false ); - } ); -} +installManagedWordPress() + .then( () => { + buildWordPress( false, false ); + } ); diff --git a/packages/scripts/utils/env.js b/packages/scripts/utils/env.js index 7b2f6d46d6ec8a..39856c0290feec 100644 --- a/packages/scripts/utils/env.js +++ b/packages/scripts/utils/env.js @@ -6,6 +6,7 @@ const request = require( 'request' ); const DecompressZip = require( 'decompress-zip' ); const chalk = require( 'chalk' ); const { sprintf } = require( 'sprintf-js' ); +const getAppDataPath = require( 'appdata-path' ); /** * Node dependencies. @@ -13,7 +14,7 @@ const { sprintf } = require( 'sprintf-js' ); const { execSync } = require( 'child_process' ); const { env, exit, stdout } = require( 'process' ); const { normalize } = require( 'path' ); -const { createWriteStream } = require( 'fs' ); +const { createWriteStream, mkdirSync } = require( 'fs' ); const { tmpdir } = require( 'os' ); /** @@ -59,12 +60,20 @@ function mergeYAMLConfigs( originalConfig, newConfig, baseDir ) { } /** - * Downloads and extracts WordPress from the GitHub repo zip file. - * - * @return {Promise} A promise that resolves when WordPress has been downloaded and extracted. + * Installs the latest version of the WordPress nightly build in the managed WordPress directory. */ -function downloadWordPressZip() { - return new Promise( ( resolve ) => { +async function installManagedWordPress() { + mkdirSync( getManagedWordPressPath(), { recursive: true } ); + let envVars = ''; + if ( env.PHP_FPM_UID ) { + envVars += `--env PHP_FPM_UID=${ env.PHP_FPM_UID }`; + } + if ( env.PHP_FPM_GID ) { + envVars += `--env PHP_FPM_GID=${ env.PHP_FPM_GID }`; + } + execSync( `docker run -it --rm ${ envVars } --volume "` + getManagedWordPressPath() + ':/var/www" docker.pkg.github.com/wordpress/wpdev-docker-images/cli:latest-16 core download --path=/var/www/src --version=nightly --force', { stdio: 'inherit' } ); + + await new Promise( ( resolve ) => { const tmpZip = normalize( tmpdir() + '/wordpress-develop.zip' ); const tmpZipWriter = createWriteStream( tmpZip ); @@ -83,9 +92,39 @@ function downloadWordPressZip() { stdout.write( 'Extracting...\n' ); unzipper.extract( { - path: env.WP_DEVELOP_DIR, + path: getManagedWordPressPath(), strip: 1, - filter: ( file ) => file.type !== 'Directory', + filter: ( file ) => { + if ( file.type === 'Directory' ) { + return false; + } + + const allowedFolders = [ + 'tools', + 'tests', + ]; + const allowedFiles = [ + '.env', + 'docker-compose.yml', + 'package.json', + 'wp-cli.yml', + 'wp-tests-config-sample.php', + ]; + + const path = file.path.replace( /[^\/]+\//, '' ); + + if ( allowedFiles.includes( path ) ) { + return true; + } + + return allowedFolders.reduce( ( allowCopy, folder ) => { + if ( allowCopy ) { + return allowCopy; + } + + return path.startsWith( folder + '/' ); + }, false ); + }, } ); } ); @@ -108,24 +147,22 @@ function downloadWordPressZip() { * @param {boolean} newInstall Flag whether to treat this as a new WordPress install or not. * @param {boolean} fastInstall When set, assumes NPM dependencies are already downloaded, and build commands have been run. */ -function buildWordPress( newInstall, fastInstall ) { +async function buildWordPress( newInstall, fastInstall ) { + // Mount the plugin into the WordPress install. + execSync( 'npm run env connect -- --no-restart', { stdio: 'inherit' } ); + if ( ! fastInstall ) { - execSync( 'npm install', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); + execSync( 'npm install dotenv wait-on', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); execSync( 'npm run env:start', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); - if ( env.LOCAL_DIR === 'build' ) { - execSync( 'npm run build', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); - } else { - execSync( 'npm run build:dev', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); - } + await new Promise( ( resolve ) => { + setTimeout( resolve, 10000 ); + } ); } if ( newInstall ) { execSync( 'npm run env:install', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); } - // Mount the plugin into the WordPress install. - execSync( 'npm run env connect', { stdio: 'inherit' } ); - if ( newInstall ) { execSync( `npm run env cli plugin activate ${ env.npm_package_wp_env_plugin_dir }`, { stdio: 'inherit' } ); @@ -158,8 +195,18 @@ function buildWordPress( newInstall, fastInstall ) { } } +/** + * Returns the path to the managed WordPress install. + * + * @return {string} The path to WordPress. + */ +function getManagedWordPressPath() { + return normalize( getAppDataPath() + '/wordpress-local-env' ); +} + module.exports = { buildWordPress, - downloadWordPressZip, + getManagedWordPressPath, + installManagedWordPress, mergeYAMLConfigs, }; diff --git a/packages/scripts/utils/index.js b/packages/scripts/utils/index.js index 3d5e3bd7ac4386..8ea33574c55ace 100644 --- a/packages/scripts/utils/index.js +++ b/packages/scripts/utils/index.js @@ -17,6 +17,8 @@ const { const { buildWordPress, downloadWordPressZip, + getManagedWordPressPath, + installManagedWordPress, mergeYAMLConfigs, } = require( './env' ); const { @@ -37,6 +39,7 @@ module.exports = { getArgFromCLI, getArgsFromCLI, getFileArgsFromCLI, + getManagedWordPressPath, getWebpackArgs, hasBabelConfig, hasArgInCLI, @@ -44,6 +47,7 @@ module.exports = { hasJestConfig, hasPackageProp, hasProjectFile, + installManagedWordPress, downloadWordPressZip, mergeYAMLConfigs, spawnScript,