diff --git a/.gitignore b/.gitignore index 5e48a472bc5cbc..96f49190bf8b53 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ gutenberg.zip *.log phpcs.xml yarn.lock -docker-compose.override.yml /wordpress playground/dist diff --git a/.travis.yml b/.travis.yml index 3e16c463eb6ed5..2fc9a43a3a61ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,16 +16,79 @@ cache: - $HOME/.jest-cache - $HOME/.npm - $HOME/.nvm/.cache - - $HOME/.phpbrew branches: only: - master +env: + global: + - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true + - WP_DEVELOP_DIR: ./wordpress + - LOCAL_SCRIPT_DEBUG: false + - INSTALL_COMPOSER: false + - INSTALL_WORDPRESS: true + before_install: - nvm install - -env: PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true + - | + if [[ "$INSTALL_WORDPRESS" = "true" ]]; then + # Upgrade docker-compose. + sudo rm /usr/local/bin/docker-compose + curl -sL https://github.com/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > docker-compose + chmod +x docker-compose + sudo mv docker-compose /usr/local/bin + fi + +install: + # Build Gutenberg. + - npm ci + - 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 + fi + - | + if [[ "$INSTALL_COMPOSER" = "true" ]]; then + npm run env docker-run -- php composer install + fi + - | + if [[ "$E2E_ROLE" = "author" ]]; then + npm run env cli -- user create author author@example.com --role=author --user_pass=authpass + npm run env cli -- post update 1 --post_author=2 + fi jobs: include: @@ -52,125 +115,86 @@ jobs: - npm run check-licenses - name: JavaScript unit tests + env: INSTALL_WORDPRESS=false install: - npm ci - script: # It's not necessary to run the full build, since Jest can interpret # source files with `babel-jest`. Some packages have their own custom # build tasks, however. These must be run. - npx lerna run build + script: - npm run test-unit -- --ci --maxWorkers=2 --cacheDirectory="$HOME/.jest-cache" - name: JavaScript native mobile tests install: - npm ci - script: # It's not necessary to run the full build, since Jest can interpret # source files with `babel-jest`. Some packages have their own custom # build tasks, however. These must be run. - npx lerna run build + script: - npm run test-unit:native -- --ci --maxWorkers=2 --cacheDirectory="$HOME/.jest-cache" - - name: PHP unit tests (Docker) - env: WP_VERSION=latest DOCKER=true + - name: PHP unit tests + env: INSTALL_COMPOSER=true script: - - ./bin/run-wp-unit-tests.sh + - npm run test-php && npm run test-unit-php-multisite - name: PHP unit tests (PHP 5.6) - language: php - php: 5.6 - env: WP_VERSION=latest + env: INSTALL_COMPOSER=true LOCAL_PHP=5.6-fpm script: - - ./bin/run-wp-unit-tests.sh - if: branch = master and type != "pull_request" - - - name: PHP unit tests (PHP 5.3) - env: WP_VERSION=latest SWITCH_TO_PHP=5.3 - script: - - ./bin/run-wp-unit-tests.sh - if: branch = master and type != "pull_request" - - - name: PHP unit tests (PHP 5.2) - env: WP_VERSION=latest SWITCH_TO_PHP=5.2 - script: - - ./bin/run-wp-unit-tests.sh + - npm run test-php && npm run test-unit-php-multisite - name: E2E tests (Admin) (1/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 0' < ~/.jest-e2e-tests ) - name: E2E tests (Admin) (2/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 1' < ~/.jest-e2e-tests ) - name: E2E tests (Admin) (3/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 2' < ~/.jest-e2e-tests ) - name: E2E tests (Admin) (4/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 3' < ~/.jest-e2e-tests ) - name: E2E tests (Author) (1/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false E2E_ROLE=author PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: E2E_ROLE=author FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 0' < ~/.jest-e2e-tests ) - name: E2E tests (Author) (2/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false E2E_ROLE=author PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: E2E_ROLE=author FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 1' < ~/.jest-e2e-tests ) - name: E2E tests (Author) (3/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false E2E_ROLE=author PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: E2E_ROLE=author FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 2' < ~/.jest-e2e-tests ) - name: E2E tests (Author) (4/4) - env: WP_VERSION=latest SCRIPT_DEBUG=false E2E_ROLE=author PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= - install: - - ./bin/setup-travis-e2e-tests.sh + env: E2E_ROLE=author FORCE_REDUCED_MOTION=true PUPPETEER_SKIP_CHROMIUM_DOWNLOAD= script: - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --listTests > ~/.jest-e2e-tests - $( npm bin )/wp-scripts test-e2e --config=./packages/e2e-tests/jest.config.js --cacheDirectory="$HOME/.jest-cache" --runTestsByPath $( awk 'NR % 4 == 3' < ~/.jest-e2e-tests ) allow_failures: - name: JavaScript native mobile tests - - name: PHP unit tests (PHP 5.3) - env: WP_VERSION=latest SWITCH_TO_PHP=5.3 - script: - - ./bin/run-wp-unit-tests.sh - if: branch = master and type != "pull_request" - - - name: PHP unit tests (PHP 5.2) - env: WP_VERSION=latest SWITCH_TO_PHP=5.2 - script: - - ./bin/run-wp-unit-tests.sh before_deploy: - npm install diff --git a/bin/bootstrap-env.sh b/bin/bootstrap-env.sh deleted file mode 100755 index 3055a49b5138ec..00000000000000 --- a/bin/bootstrap-env.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -WP_VERSION=${WP_VERSION-latest} -WP_DEBUG=${WP_DEBUG-true} -SCRIPT_DEBUG=${SCRIPT_DEBUG-true} -DOCKER=${DOCKER-false} -DOCKER_ENV=${DOCKER_ENV-ci} -DOCKER_COMPOSE_FILE_OPTIONS="-f docker-compose.yml" - -if [ "$DOCKER_ENV" == "localwpdev" ]; then - DOCKER_COMPOSE_FILE_OPTIONS="${DOCKER_COMPOSE_FILE_OPTIONS} -f docker-compose-localdev.yml" -fi diff --git a/bin/docker-compose.override.yml.template b/bin/docker-compose.override.yml.template new file mode 100644 index 00000000000000..465211fe7a4a63 --- /dev/null +++ b/bin/docker-compose.override.yml.template @@ -0,0 +1,17 @@ +services: + wordpress-develop: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% + - %PLUGIN_MOUNT_DIR%/packages/e2e-tests/plugins:/var/www/${LOCAL_DIR-src}/wp-content/plugins/gutenberg-test-plugins + - %PLUGIN_MOUNT_DIR%/packages/e2e-tests/mu-plugins:/var/www/${LOCAL_DIR-src}/wp-content/mu-plugins + php: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% + - %PLUGIN_MOUNT_DIR%/packages/e2e-tests/plugins:/var/www/${LOCAL_DIR-src}/wp-content/plugins/gutenberg-test-plugins + - %PLUGIN_MOUNT_DIR%/packages/e2e-tests/mu-plugins:/var/www/${LOCAL_DIR-src}/wp-content/mu-plugins + cli: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% + phpunit: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% diff --git a/bin/includes.sh b/bin/includes.sh deleted file mode 100755 index d0028a1c665751..00000000000000 --- a/bin/includes.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/bash - -## -# Ask a Yes/No question, and way for a reply. -# -# This is a general-purpose function to ask Yes/No questions in Bash, either with or without a default -# answer. It keeps repeating the question until it gets a valid answer. -# -# @param {string} prompt The question to ask the user. -# @param {string} [default] Optional. "Y" or "N", for the default option to use if none is entered. -# @param {int} [timeout] Optional. The number of seconds to wait before using the default option. -# -# @returns {bool} true if the user replies Yes, false if the user replies No. -## -ask() { - # Source: https://djm.me/ask - local timeout endtime timediff prompt default reply - - while true; do - - timeout="${3:-}" - - if [ "${2:-}" = "Y" ]; then - prompt="Y/n" - default=Y - elif [ "${2:-}" = "N" ]; then - prompt="y/N" - default=N - else - prompt="y/n" - default= - timeout= - fi - - if [ -z "$timeout" ]; then - # Ask the question (not using "read -p" as it uses stderr not stdout) - echo -en "$1 [$prompt] " - - # Read the answer (use /dev/tty in case stdin is redirected from somewhere else) - read reply /dev/null 2>&1 -} diff --git a/bin/install-docker.sh b/bin/install-docker.sh deleted file mode 100755 index f485753b9cc4c6..00000000000000 --- a/bin/install-docker.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Exit if any command fails. -set -e - -. "$(dirname "$0")/bootstrap-env.sh" - -# Include useful functions. -. "$(dirname "$0")/includes.sh" - -# Check that Docker is installed. -if ! command_exists "docker"; then - echo -e $(error_message "Docker doesn't seem to be installed. Please head on over to the Docker site to download it: $(action_format "https://www.docker.com/products/docker-desktop")") - exit 1 -fi - -# Check that Docker is running. -if ! docker info >/dev/null 2>&1; then - echo -e $(error_message "Docker isn't running. Please check that you've started your Docker app, and see it in your system tray.") - exit 1 -fi - -# Stop existing containers. -echo -e $(status_message "Stopping Docker containers...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS down --remove-orphans >/dev/null 2>&1 - -# Download image updates. -echo -e $(status_message "Downloading Docker image updates...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS pull - -# Launch the containers. -echo -e $(status_message "Starting Docker containers...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS up -d >/dev/null diff --git a/bin/install-node-nvm.sh b/bin/install-node-nvm.sh deleted file mode 100755 index d9cd1a6faf5102..00000000000000 --- a/bin/install-node-nvm.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash -NVM_VERSION=`curl -Ls -w %{url_effective} -o /dev/null https://github.com/creationix/nvm/releases/latest | rev | cut -d '/' -f 1 | rev` - -# Exit if any command fails -set -e - -# Include useful functions -. "$(dirname "$0")/includes.sh" - -# Load NVM -if [ -n "$NVM_DIR" ]; then - # The --no-use option ensures loading NVM doesn't switch the current version. - if [ -f "$NVM_DIR/nvm.sh" ]; then - . "$NVM_DIR/nvm.sh" --no-use - elif command_exists "brew" && [ -f "$(brew --prefix nvm)/nvm.sh" ]; then - # use homebrew if that's how nvm was installed - . "$(brew --prefix nvm)/nvm.sh" --no-use - fi -fi - -# Change to the expected directory -cd "$(dirname "$0")/.." - -# Check if nvm is installed -if [ "$TRAVIS" != "true" ] && ! command_exists "nvm"; then - if ask "$(error_message "NVM isn't installed, would you like to download and install it automatically?")" Y; then - # The .bash_profile file needs to exist for NVM to install - if [ ! -e ~/.bash_profile ]; then - touch ~/.bash_profile - fi - - echo -en $(status_message "Installing NVM..." ) - download "https://raw.githubusercontent.com/creationix/nvm/$NVM_VERSION/install.sh" | bash >/dev/null 2>&1 - echo ' done!' - - echo -e $(warning_message "NVM was updated, please run this command to reload it:" ) - echo -e $(warning_message "$(action_format ". \$HOME/.nvm/nvm.sh")" ) - echo -e $(warning_message "After that, re-run the setup script to continue." ) - else - echo -e $(error_message "") - echo -e $(error_message "Please install NVM manually, then re-run the setup script to continue.") - echo -e $(error_message "NVM installation instructions can be found here: $(action_format "https://github.com/creationix/nvm")") - fi - - exit 1 -fi - -# Check if the current nvm version is up to date. -if [ "$TRAVIS" != "true" ] && [ $NVM_VERSION != "v$(nvm --version)" ]; then - echo -en $(status_message "Updating NVM..." ) - download "https://raw.githubusercontent.com/creationix/nvm/$NVM_VERSION/install.sh" | bash >/dev/null 2>&1 - echo ' done!' - - echo -e $(warning_message "NVM was updated, please run this command to reload it:" ) - echo -e $(warning_message "$(action_format ". \$HOME/.nvm/nvm.sh")" ) - echo -e $(warning_message "After that, re-run the setup script to continue." ) - exit 1 -fi - -# Check if the current node version is up to date. -if [ "$TRAVIS" != "true" ] && [ "$(nvm current)" != "$(nvm version-remote --lts)" ]; then - echo -e $(warning_message "Node version does not match the latest long term support version. Please run this command to install and use it:" ) - echo -e $(warning_message "$(action_format "nvm install")" ) - echo -e $(warning_message "After that, re-run the setup script to continue." ) - exit 1 -fi - -# Install/update packages -echo -e $(status_message "Installing and updating NPM packages..." ) -npm install - -# There was a bug in NPM that caused changes in package-lock.json. Handle that. -if [ "$TRAVIS" != "true" ] && ! git diff --no-ext-diff --exit-code package-lock.json >/dev/null; then - if ask "$(warning_message "Your package-lock.json changed, which may mean there's an issue with your NPM cache. Would you like to try and automatically clean it up?" )" N 10; then - rm -rf node_modules/ - npm cache clean --force >/dev/null 2>&1 - git checkout package-lock.json - - echo -e $(status_message "Reinstalling NPM packages..." ) - npm install - - # Check that it's cleaned up now. - if git diff --no-ext-diff --exit-code package-lock.json >/dev/null; then - echo -e $(warning_message "Confirmed that the NPM cache is cleaned up." ) - else - echo -e $(error_message "We were unable to clean the NPM cache, please manually review the changes to package-lock.json. Continuing with the setup process..." ) - fi - else - echo -e $(warning_message "Please manually review the changes to package-lock.json. Continuing with the setup process..." ) - fi -fi diff --git a/bin/install-php-phpunit.sh b/bin/install-php-phpunit.sh deleted file mode 100755 index 09b9137b1fc711..00000000000000 --- a/bin/install-php-phpunit.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash - -# Uses phpbrew to install older php versions on modern(ish) distros. -# Installs the correct version of phpunit for the requested php -# version. ~/.phpbrew is expected to be cached so we only have -# to build php the first time. - -# we have to save and restore the original working directory, because -# phpbrew can mess up if we don't run it from the home directory -ORIG_DIR=`pwd`; -THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -PHP52_PATH=$HOME/.phpbrew/php/php-5.2.17 - -# install phpunit - -mkdir -p $HOME/phpunit-bin - -if [[ ${SWITCH_TO_PHP:0:3} == "5.2" ]]; then - # use the phpunit in the PHP5.2 installation - ln -s ${PHP52_PATH}/lib/php/phpunit/phpunit.php $HOME/phpunit-bin/phpunit -elif [[ ${TRAVIS_PHP_VERSION:0:2} == "5." ]] || [[ ${SWITCH_TO_PHP:0:2} == "5." ]]; then - wget -O $HOME/phpunit-bin/phpunit https://phar.phpunit.de/phpunit-4.8.phar - chmod +x $HOME/phpunit-bin/phpunit -else - composer global require "phpunit/phpunit=6.*" -fi - -export PATH=$HOME/phpunit-bin/:$PATH - -if [[ ${SWITCH_TO_PHP:0:3} == "5.2" ]] || [[ ${SWITCH_TO_PHP:0:3} == "5.3" ]]; then - PHPBREW_BUILT_CHECK=$HOME/.phpbrew/bashrc - - # directory to install phpbrew into - mkdir -p $HOME/php-utils-bin - - # install phpbrew - curl -L -o $HOME/php-utils-bin/phpbrew https://github.com/phpbrew/phpbrew/raw/f6a422e1ba49293ee73bc4c317795c021bc57020/phpbrew - chmod +x $HOME/php-utils-bin/phpbrew - - # needs to be on the path for switching php versions to work - export PATH=$HOME/php-utils-bin:$PATH - - # php and phpunit3.6 installs should be cached, only build if they're not there. - if [ ! -f $PHPBREW_BUILT_CHECK ]; then - - # init with known --old to get 5.2 and 5.3 - $HOME/php-utils-bin/phpbrew init - $HOME/php-utils-bin/phpbrew known --old - - # fetch the build tarballs manually - mkdir -p $HOME/.phpbrew/distfiles - curl -L -o $HOME/.phpbrew/distfiles/php-5.2.17.tar.bz2 https://museum.php.net/php5/php-5.2.17.tar.bz2 - curl -L -o $HOME/.phpbrew/distfiles/php-5.3.29.tar.bz2 https://museum.php.net/php5/php-5.3.29.tar.bz2 - - # build PHP5.2 - echo 'Installing PHP 5.2...' - $HOME/php-utils-bin/phpbrew install --patch ${THIS_DIR}/patches/node.patch --patch ${THIS_DIR}/patches/openssl.patch 5.2.17 +default +mysql +pdo \ - +gettext +phar +openssl -- --with-openssl-dir=/usr/include/openssl --enable-spl --with-mysql --with-mysqli=/usr/bin/mysql_config --with-pdo-mysql=/usr - - # build PHP5.3 - echo 'Installing PHP 5.3...' - $HOME/php-utils-bin/phpbrew install --patch ${THIS_DIR}/patches/node.patch --patch ${THIS_DIR}/patches/openssl.patch 5.3.29 +default +mysql +pdo \ - +gettext +phar +openssl -- --with-openssl-dir=/usr/include/openssl --enable-spl --with-mysql --with-mysqli=/usr/bin/mysql_config --with-pdo-mysql=/usr - - # install PHPUnit 3.6. The only install method available is from source, using git branches old - # enough that they don't rely on any PHP5.3+ features. This clones each needed dependency - # and then we add the paths to the include_path by setting up an extra .ini file - cd ${PHP52_PATH}/lib/php - - # dependencies - git clone --depth=1 --branch=1.1 git://github.com/sebastianbergmann/dbunit.git - git clone --depth=1 --branch=1.1 git://github.com/sebastianbergmann/php-code-coverage.git - git clone --depth=1 --branch=1.3.2 git://github.com/sebastianbergmann/php-file-iterator.git - git clone --depth=1 --branch=1.1.1 git://github.com/sebastianbergmann/php-invoker.git - git clone --depth=1 --branch=1.1.2 git://github.com/sebastianbergmann/php-text-template.git - git clone --depth=1 --branch=1.0.3 git://github.com/sebastianbergmann/php-timer.git - git clone --depth=1 --branch=1.1.4 git://github.com/sebastianbergmann/php-token-stream.git - git clone --depth=1 --branch=1.1 git://github.com/sebastianbergmann/phpunit-mock-objects.git - git clone --depth=1 --branch=1.1 git://github.com/sebastianbergmann/phpunit-selenium.git - git clone --depth=1 --branch=1.0.0 git://github.com/sebastianbergmann/phpunit-story.git - - # and the version of phpunit that we expect to run with php 5.2 - git clone --depth=1 --branch=3.6 git://github.com/sebastianbergmann/phpunit.git - - # fix up the version number of phpunit - sed -i 's/@package_version@/3.6-git/g' phpunit/PHPUnit/Runner/Version.php - - # now set up an ini file that adds all of the above to include_path for the PHP5.2 install - mkdir -p ${PHP52_PATH}/var/db - echo "include_path=.:${PHP52_PATH}/lib/php:${PHP52_PATH}/lib/php/dbunit:${PHP52_PATH}/lib/php/php-code-coverage:${PHP52_PATH}/lib/php/php-file-iterator:${PHP52_PATH}/lib/php/php-invoker:${PHP52_PATH}/lib/php/php-text-template:${PHP52_PATH}/lib/php/php-timer:${PHP52_PATH}/lib/php/php-token-stream:${PHP52_PATH}/lib/php/phpunit-mock-objects:${PHP52_PATH}/lib/php/phpunit-selenium:${PHP52_PATH}/lib/php/phpunit-story:${PHP52_PATH}/lib/php/phpunit" > ${PHP52_PATH}/var/db/path.ini - - # one more PHPUnit dependency that we need to install using pear under PHP5.2 - cd $HOME - export PHPBREW_RC_ENABLE=1 - source $HOME/.phpbrew/bashrc - phpbrew use 5.2.17 - - # manually go back to the system php, we can't use `phpbrew switch-off` - # because we're running a version of php that phpbrew doesn't work with at this point - unset PHPBREW_PHP - unset PHPBREW_PATH - __phpbrew_set_path - __phpbrew_reinit - eval `$BIN env` - - # clean up build directory - rm -rf $HOME/.phpbrew/build/* - fi - - # all needed php versions and phpunit versions are installed, either from the above - # install script, or from travis cache, so switch to using them - cd $HOME - export PHPBREW_RC_ENABLE=1 - source $HOME/.phpbrew/bashrc - - if [[ ${SWITCH_TO_PHP:0:3} == "5.2" ]]; then - phpbrew use 5.2.17 - else - phpbrew use 5.3.29 - fi -fi - -cd $ORIG_DIR diff --git a/bin/install-wordpress.sh b/bin/install-wordpress.sh deleted file mode 100755 index 551e8bd0dc77e1..00000000000000 --- a/bin/install-wordpress.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# Exit if any command fails. -set -e - -# Gutenberg script includes. -. "$(dirname "$0")/includes.sh" - -# Set up environment variables -. "$(dirname "$0")/bootstrap-env.sh" - -# These are the containers and values for the development site. -CLI='cli' -CONTAINER='wordpress' -SITE_TITLE='Gutenberg Dev' - -# If we're installing/re-installing the test site, change the containers used. -if [ "$1" == '--e2e_tests' ]; then - CLI="${CLI}_e2e_tests" - CONTAINER='wordpress_e2e_tests' - SITE_TITLE='Gutenberg Testing' - - if ! docker ps | grep -q $CONTAINER; then - echo -e $(error_message "WordPress e2e tests run in their own Docker container, but that container wasn't found.") - echo "Please restart your Docker containers by running 'docker-compose $DOCKER_COMPOSE_FILE_OPTIONS down && docker-compose $DOCKER_COMPOSE_FILE_OPTIONS up -d' or" - echo "by running './bin/setup-local-env.sh' again." - echo "" - exit 1 - fi -fi - -# Get the host port for the WordPress container. -HOST_PORT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS port $CONTAINER 80 | awk -F : '{printf $2}') - -# Wait until the Docker containers are running and the WordPress site is -# responding to requests. -echo -en $(status_message "Attempting to connect to WordPress...") -until $(curl -L http://localhost:$HOST_PORT -so - 2>&1 | grep -q "WordPress"); do - echo -n '.' - sleep 5 -done -echo '' - -# If this is the test site, we reset the database so no posts/comments/etc. -# dirty up the tests. -if [ "$1" == '--e2e_tests' ]; then - echo -e $(status_message "Resetting test database...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI db reset --yes --quiet -fi - -# Install WordPress. -echo -e $(status_message "Installing WordPress...") -# The `-u 33` flag tells Docker to run the command as a particular user and -# prevents permissions errors. See: https://github.com/WordPress/gutenberg/pull/8427#issuecomment-410232369 -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI core install --title="$SITE_TITLE" --admin_user=admin --admin_password=password --admin_email=test@test.com --skip-email --url=http://localhost:$HOST_PORT --quiet - -if [ "$E2E_ROLE" = "author" ]; then - echo -e $(status_message "Creating an additional author user for testing...") - # Create an additional author user for testing. - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI user create author author@example.com --role=author --user_pass=authpass --quiet - # Assign the existing Hello World post to the author. - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI post update 1 --post_author=2 --quiet -fi - -# Make sure the uploads and upgrade folders exist and we have permissions to add files. -echo -e $(status_message "Ensuring that files can be uploaded...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER mkdir -p /var/www/html/wp-content/uploads /var/www/html/wp-content/upgrade -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER chmod 767 /var/www/html/wp-content/plugins /var/www/html/wp-config.php /var/www/html/wp-settings.php /var/www/html/wp-content/uploads /var/www/html/wp-content/upgrade - -CURRENT_WP_VERSION=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm $CLI core version) -echo -e $(status_message "Current WordPress version: $CURRENT_WP_VERSION...") - -if [ "$WP_VERSION" == "latest" ]; then - # Check for WordPress updates, to make sure we're running the very latest version. - echo -e $(status_message "Updating WordPress to the latest version...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI core update --quiet - echo -e $(status_message "Updating The WordPress Database...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI core update-db --quiet -fi - -# If the 'wordpress' volume wasn't during the down/up earlier, but the post port has changed, we need to update it. -echo -e $(status_message "Checking the site's url...") -CURRENT_URL=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm $CLI option get siteurl) -if [ "$CURRENT_URL" != "http://localhost:$HOST_PORT" ]; then - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI option update home "http://localhost:$HOST_PORT" --quiet - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI option update siteurl "http://localhost:$HOST_PORT" --quiet -fi - -# Activate Gutenberg. -echo -e $(status_message "Activating Gutenberg...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI plugin activate gutenberg --quiet - -# Install a dummy favicon to avoid 404 errors. -echo -e $(status_message "Installing a dummy favicon...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm $CONTAINER touch /var/www/html/favicon.ico - -# Configure site constants. -echo -e $(status_message "Configuring site constants...") -WP_DEBUG_CURRENT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json WP_DEBUG) -if [ $WP_DEBUG != $WP_DEBUG_CURRENT ]; then - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI config set WP_DEBUG $WP_DEBUG --raw --type=constant --quiet - WP_DEBUG_RESULT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json WP_DEBUG) - echo -e $(status_message "WP_DEBUG: $WP_DEBUG_RESULT...") -fi -SCRIPT_DEBUG_CURRENT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json SCRIPT_DEBUG) -if [ $SCRIPT_DEBUG != $SCRIPT_DEBUG_CURRENT ]; then - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm -u 33 $CLI config set SCRIPT_DEBUG $SCRIPT_DEBUG --raw --type=constant --quiet - SCRIPT_DEBUG_RESULT=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm -u 33 $CLI config get --type=constant --format=json SCRIPT_DEBUG) - echo -e $(status_message "SCRIPT_DEBUG: $SCRIPT_DEBUG_RESULT...") -fi diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh deleted file mode 100755 index 17dc681629034a..00000000000000 --- a/bin/install-wp-tests.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env bash - -# Include useful functions -. "$(dirname "$0")/includes.sh" - -if [ $# -lt 3 ]; then - echo "usage: $0 [db-host] [wp-version] [skip-database-creation]" - exit 1 -fi - -DB_NAME=$1 -DB_USER=$2 -DB_PASS=$3 -DB_HOST=${4-localhost} -WP_VERSION=${5-latest} -SKIP_DB_CREATE=${6-false} - -WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} -WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} - -if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then - WP_TESTS_TAG="tags/$WP_VERSION" -elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then - WP_TESTS_TAG="trunk" -else - # http serves a single offer, whereas https serves multiple. we only want one - download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json - grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json - LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') - if [[ -z "$LATEST_VERSION" ]]; then - echo "Latest WordPress version could not be found" - exit 1 - fi - WP_TESTS_TAG="tags/$LATEST_VERSION" -fi - -set -ex - -install_wp() { - - if [ -d $WP_CORE_DIR ]; then - return; - fi - - mkdir -p $WP_CORE_DIR - - if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then - mkdir -p /tmp/wordpress-nightly - download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip - unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/ - mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR - else - if [ $WP_VERSION == 'latest' ]; then - local ARCHIVE_NAME='latest' - else - local ARCHIVE_NAME="wordpress-$WP_VERSION" - fi - download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz - tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR - fi - - download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php -} - -install_test_suite() { - # portable in-place argument for both GNU sed and Mac OSX sed - if [[ $(uname -s) == 'Darwin' ]]; then - local ioption='-i .bak' - else - local ioption='-i' - fi - - # set up testing suite if it doesn't yet exist - if [ ! -d $WP_TESTS_DIR ]; then - # set up testing suite - mkdir -p $WP_TESTS_DIR - svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes - svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data - fi - - if [ ! -f wp-tests-config.php ]; then - download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php - # remove all forward slashes in the end - WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::") - sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php - fi - -} - -install_db() { - - if [ ${SKIP_DB_CREATE} = "true" ]; then - return 0 - fi - - # parse DB_HOST for port or socket references - local PARTS=(${DB_HOST//\:/ }) - local DB_HOSTNAME=${PARTS[0]}; - local DB_SOCK_OR_PORT=${PARTS[1]}; - local EXTRA="" - - if ! [ -z $DB_HOSTNAME ] ; then - if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then - EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" - elif ! [ -z $DB_SOCK_OR_PORT ] ; then - EXTRA=" --socket=$DB_SOCK_OR_PORT" - elif ! [ -z $DB_HOSTNAME ] ; then - EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" - fi - fi - - # create database - mysql --user="$DB_USER" --password="$DB_PASS"$EXTRA --execute "CREATE DATABASE IF NOT EXISTS $DB_NAME;" -} - -# Wait for MySQL availability before proceeding with installation -echo -en $(status_message "Attempting to connect to MySQL...") -while ! mysqladmin ping -h"$DB_HOST" --silent; do - echo -n '.' - sleep 2 -done - -install_wp -install_test_suite -install_db diff --git a/bin/patches/README.md b/bin/patches/README.md deleted file mode 100644 index 8ea482c4e6e632..00000000000000 --- a/bin/patches/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains patches required to build -older versions of PHP on trusty. \ No newline at end of file diff --git a/bin/patches/node.patch b/bin/patches/node.patch deleted file mode 100644 index e5dbab7972b6b2..00000000000000 --- a/bin/patches/node.patch +++ /dev/null @@ -1,51 +0,0 @@ ---- ext/dom/node.c 2012-08-06 17:49:48.826716692 +0800 -+++ ext/dom/node.c 2012-08-06 17:52:47.633484660 +0800 -@@ -1895,9 +1895,17 @@ static void dom_canonicalization(INTERNA - RETVAL_FALSE; - } else { - if (mode == 0) { -+#ifdef LIBXML2_NEW_BUFFER -+ ret = xmlOutputBufferGetSize(buf); -+#else - ret = buf->buffer->use; -+#endif - if (ret > 0) { -+#ifdef LIBXML2_NEW_BUFFER -+ RETVAL_STRINGL((char *) xmlOutputBufferGetContent(buf), ret, 1); -+#else - RETVAL_STRINGL((char *) buf->buffer->content, ret, 1); -+#endif - } else { - RETVAL_EMPTY_STRING(); - } ---- ext/dom/documenttype.c 2012-08-06 18:02:16.019640870 +0800 -+++ ext/dom/documenttype.c 2012-08-06 18:06:16.612228905 +0800 -@@ -205,7 +205,13 @@ int dom_documenttype_internal_subset_rea - if (buff != NULL) { - xmlNodeDumpOutput (buff, NULL, (xmlNodePtr) intsubset, 0, 0, NULL); - xmlOutputBufferFlush(buff); -+ -+#ifdef LIBXML2_NEW_BUFFER -+ ZVAL_STRINGL(*retval, xmlOutputBufferGetContent(buff), -+ xmlOutputBufferGetSize(buff), 1); -+#else - ZVAL_STRINGL(*retval, buff->buffer->content, buff->buffer->use, 1); -+#endif - (void)xmlOutputBufferClose(buff); - return SUCCESS; - } ---- ext/simplexml/simplexml.c 2012-08-06 18:10:44.621017026 +0800 -+++ ext/simplexml/simplexml.c 2012-08-06 18:12:48.016270419 +0800 -@@ -1417,7 +1417,12 @@ SXE_METHOD(asXML) - - xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, ((xmlDocPtr) sxe->document->ptr)->encoding); - xmlOutputBufferFlush(outbuf); -+#ifdef LIBXML2_NEW_BUFFER -+ RETVAL_STRINGL((char *)xmlOutputBufferGetContent(outbuf), -+ xmlOutputBufferGetSize(outbuf), 1); -+#else - RETVAL_STRINGL((char *)outbuf->buffer->content, outbuf->buffer->use, 1); -+#endif - xmlOutputBufferClose(outbuf); - } - } else { diff --git a/bin/patches/openssl.patch b/bin/patches/openssl.patch deleted file mode 100644 index 3b0e010b1fd1f2..00000000000000 --- a/bin/patches/openssl.patch +++ /dev/null @@ -1,52 +0,0 @@ ---- ext/openssl/xp_ssl.c -+++ ext/openssl/xp_ssl.c -@@ -328,10 +328,12 @@ static inline int php_openssl_setup_cryp - sslsock->is_client = 1; - method = SSLv23_client_method(); - break; -+#ifndef OPENSSL_NO_SSL2 - case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: - sslsock->is_client = 1; - method = SSLv2_client_method(); - break; -+#endif - case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: - sslsock->is_client = 1; - method = SSLv3_client_method(); -@@ -348,10 +350,12 @@ static inline int php_openssl_setup_cryp - sslsock->is_client = 0; - method = SSLv3_server_method(); - break; -+#ifndef OPENSSL_NO_SSL2 - case STREAM_CRYPTO_METHOD_SSLv2_SERVER: - sslsock->is_client = 0; - method = SSLv2_server_method(); - break; -+#endif - case STREAM_CRYPTO_METHOD_TLS_SERVER: - sslsock->is_client = 0; - method = TLSv1_server_method(); -@@ -629,9 +633,11 @@ static inline int php_openssl_tcp_sockop - case STREAM_CRYPTO_METHOD_SSLv23_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_SSLv23_SERVER; - break; -+#ifndef OPENSSL_NO_SSL2 - case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_SSLv2_SERVER; - break; -+#endif - case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_SSLv3_SERVER; - break; -@@ -911,9 +917,11 @@ php_stream *php_openssl_ssl_socket_facto - if (strncmp(proto, "ssl", protolen) == 0) { - sslsock->enable_on_connect = 1; - sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT; -+#ifndef OPENSSL_NO_SSL2 - } else if (strncmp(proto, "sslv2", protolen) == 0) { - sslsock->enable_on_connect = 1; - sslsock->method = STREAM_CRYPTO_METHOD_SSLv2_CLIENT; -+#endif - } else if (strncmp(proto, "sslv3", protolen) == 0) { - sslsock->enable_on_connect = 1; - sslsock->method = STREAM_CRYPTO_METHOD_SSLv3_CLIENT; diff --git a/bin/reset-local-e2e-tests.sh b/bin/reset-local-e2e-tests.sh deleted file mode 100755 index fb1e080f9da04d..00000000000000 --- a/bin/reset-local-e2e-tests.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# Exit if any command fails. -set -e - -# Set up WordPress site used for end-to-end (e2e) tests. -. "$(dirname "$0")/install-wordpress.sh" --e2e_tests diff --git a/bin/run-wp-unit-tests.sh b/bin/run-wp-unit-tests.sh deleted file mode 100755 index 2e5dc5b0809146..00000000000000 --- a/bin/run-wp-unit-tests.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash - -# Exit if any command fails -set -e - -npm ci - -npm run build - -# Set up environment variables -. "$(dirname "$0")/bootstrap-env.sh" - -# Include useful functions -. "$(dirname "$0")/includes.sh" - -cd "$(dirname "$0")/../" - -export PATH="$HOME/.composer/vendor/bin:$PATH" -if [[ $DOCKER = "true" ]]; then - # Download image updates. - echo -e $(status_message "Downloading Docker image updates...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS pull composer mysql wordpress_phpunit - - # Launch the containers. - echo -e $(status_message "Starting Docker containers...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS up -d composer mysql wordpress_phpunit >/dev/null - - # Install the PHPUnit test scaffolding. - echo -e $(status_message "Installing PHPUnit test scaffolding...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm wordpress_phpunit /app/bin/install-wp-tests.sh wordpress_test root example mysql $WP_VERSION false > /dev/null - - # Install Composer. This is only used to run WordPress Coding Standards checks. - echo -e $(status_message "Installing and updating Composer modules...") - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm composer install -else - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION - source bin/install-php-phpunit.sh - - # Run the build because otherwise there will be a bunch of warnings about - # failed `stat` calls from `filemtime()`. - composer install -fi - -echo Running with the following versions: -if [[ $DOCKER = "true" ]]; then - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm wordpress_phpunit php -v - docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm wordpress_phpunit phpunit --version -else - php -v - phpunit --version -fi - -# Run PHPUnit tests -if [[ $DOCKER = "true" ]]; then - npm run test-php - npm run test-unit-php-multisite -else - phpunit - WP_MULTISITE=1 phpunit -fi diff --git a/bin/setup-local-env.sh b/bin/setup-local-env.sh index f618780e2d8c19..a427fb4e3f3ef1 100755 --- a/bin/setup-local-env.sh +++ b/bin/setup-local-env.sh @@ -1,52 +1,8 @@ #!/bin/bash -# Exit if any command fails +# Exit if any command fails. set -e -# Set up environment variables -. "$(dirname "$0")/bootstrap-env.sh" +echo "Hi there! It looks like you're trying to use the old local environment setup script. This script has been retired, running \`npm run env install\` will setup a local environment for you, instead. -# Include useful functions -. "$(dirname "$0")/includes.sh" - -# Change to the expected directory -cd "$(dirname "$0")/.." - -# Check Node and NVM are installed -. "$(dirname "$0")/install-node-nvm.sh" - -# Check Docker is installed and running -. "$(dirname "$0")/install-docker.sh" - -# Set up WordPress Development site. -# Note: we don't bother installing the test site right now, because that's -# done on every time `npm run test-e2e` is run. -. "$(dirname "$0")/install-wordpress.sh" - -# Install the PHPUnit test scaffolding. -echo -e $(status_message "Installing PHPUnit test scaffolding...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm wordpress_phpunit /app/bin/install-wp-tests.sh wordpress_test root example mysql $WP_VERSION false > /dev/null - -# Install Composer. This is only used to run WordPress Coding Standards checks. -echo -e $(status_message "Installing and updating Composer modules...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run --rm composer install - -! read -d '' GUTENBERG <<"EOT" -,⁻⁻⁻· . | -| ،⁓’. . |--- ,---. ,---. |---. ,---. ,---. ,---. -| | | | | |---' | | | | |---' | | | -`---' `---' `---’ `---’ ' ` `---' `---’ ` `---| - `---' -EOT - -CURRENT_URL=$(docker-compose $DOCKER_COMPOSE_FILE_OPTIONS run -T --rm cli option get siteurl) - -echo -e "\nWelcome to...\n" -echo -e "\033[95m$GUTENBERG\033[0m" - -# Give the user more context to what they should do next: Build Gutenberg and start testing! -echo -e "\nRun $(action_format "npm run dev") to build the latest Gutenberg packages," -echo -e "then open $(action_format "$CURRENT_URL") to get started!" - -echo -e "\n\nAccess the above install using the following credentials:" -echo -e "Default username: $(action_format "admin"), password: $(action_format "password")" +Check out the documentation for more information: https://developer.wordpress.org/block-editor/contributors/develop/getting-started/" diff --git a/bin/setup-travis-e2e-tests.sh b/bin/setup-travis-e2e-tests.sh deleted file mode 100755 index 0594f4724b2e58..00000000000000 --- a/bin/setup-travis-e2e-tests.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# Exit if any command fails -set -e - -npm ci - -# Force reduced motion in e2e tests -FORCE_REDUCED_MOTION=true npm run build - -# Set up environment variables -. "$(dirname "$0")/bootstrap-env.sh" - -# Include useful functions -. "$(dirname "$0")/includes.sh" - -# Change to the expected directory -cd "$(dirname "$0")/.." - -# Download image updates. -echo -e $(status_message "Downloading Docker image updates...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS pull mysql wordpress_e2e_tests cli_e2e_tests - -# Launch the containers. -echo -e $(status_message "Starting Docker containers...") -docker-compose $DOCKER_COMPOSE_FILE_OPTIONS up -d --remove-orphans mysql wordpress_e2e_tests cli_e2e_tests >/dev/null - -# Set up WordPress Development site. -. "$(dirname "$0")/install-wordpress.sh" --e2e_tests diff --git a/docker-compose-localdev.yml b/docker-compose-localdev.yml deleted file mode 100644 index 4d58031eaa74be..00000000000000 --- a/docker-compose-localdev.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: '3.1' - -services: - - wordpress: - volumes: - - ./wordpress:/var/www/html - - cli: - image: wordpress:cli - volumes: - - ./wordpress:/var/www/html diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 723578cce7465f..00000000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,88 +0,0 @@ -version: '3.1' - -services: - - wordpress: - image: wordpress - ports: - - 8888:80 - environment: - WORDPRESS_DB_HOST: mysql - WORDPRESS_DB_PASSWORD: example - ABSPATH: /usr/src/wordpress/ - WORDPRESS_DEBUG: 1 - WORDPRESS_CONFIG_EXTRA: | - define( 'SCRIPT_DEBUG', true ); - volumes: - - wordpress_data:/var/www/html - - .:/var/www/html/wp-content/plugins/gutenberg - - ./packages/e2e-tests/plugins:/var/www/html/wp-content/plugins/gutenberg-test-plugins - - ./packages/e2e-tests/mu-plugins:/var/www/html/wp-content/mu-plugins - depends_on: - - mysql - - cli: - image: wordpress:cli - user: xfs - volumes: - - wordpress_data:/var/www/html - - .:/var/www/html/wp-content/plugins/gutenberg - depends_on: - - mysql - - wordpress - - mysql: - image: mysql:5.7 - environment: - MYSQL_ROOT_PASSWORD: example - MYSQL_DATABASE: wordpress_test - - wordpress_phpunit: - image: chriszarate/wordpress-phpunit - environment: - PHPUNIT_DB_HOST: mysql - volumes: - - .:/app - - testsuite:/tmp - depends_on: - - mysql - - composer: - image: composer - volumes: - - .:/app - - wordpress_e2e_tests: - image: wordpress - ports: - - 8889:80 - environment: - WORDPRESS_DB_HOST: mysql - WORDPRESS_DB_NAME: wordpress_e2e_tests - WORDPRESS_DB_PASSWORD: example - ABSPATH: /usr/src/wordpress/ - WORDPRESS_DEBUG: 1 - WORDPRESS_CONFIG_EXTRA: | - define( 'SCRIPT_DEBUG', true ); - volumes: - - wordpress_e2e_tests_data:/var/www/html - - .:/var/www/html/wp-content/plugins/gutenberg - - ./packages/e2e-tests/plugins:/var/www/html/wp-content/plugins/gutenberg-test-plugins - - ./packages/e2e-tests/mu-plugins:/var/www/html/wp-content/mu-plugins - depends_on: - - mysql - - cli_e2e_tests: - image: wordpress:cli - user: xfs - volumes: - - wordpress_e2e_tests_data:/var/www/html - - .:/var/www/html/wp-content/plugins/gutenberg - depends_on: - - mysql - - wordpress_e2e_tests - -volumes: - testsuite: - wordpress_data: - wordpress_e2e_tests_data: diff --git a/docs/contributors/coding-guidelines.md b/docs/contributors/coding-guidelines.md index dac400e51f663e..2e02dfeaa10f7e 100644 --- a/docs/contributors/coding-guidelines.md +++ b/docs/contributors/coding-guidelines.md @@ -208,4 +208,4 @@ We use The easiest way to use PHPCS is [local environment](/docs/contributors/getting-started.md#local-environment). Once that's installed, you can check your PHP by running `npm run lint-php`. -If you prefer to install PHPCS locally, you should use `composer`. [Install `composer`](https://getcomposer.org/download/) on your computer, then run `composer install`. This will install `phpcs` and `WordPress-Coding-Standards` which you can the run via `vendor/bin/phpcs`. +If you prefer to install PHPCS locally, you should use `composer`. [Install `composer`](https://getcomposer.org/download/) on your computer, then run `composer install`. This will install `phpcs` and `WordPress-Coding-Standards` which you can then run via `composer lint`. diff --git a/docs/contributors/getting-started.md b/docs/contributors/getting-started.md index 24217faed45fd9..3105b6a0aa15da 100644 --- a/docs/contributors/getting-started.md +++ b/docs/contributors/getting-started.md @@ -2,74 +2,53 @@ Gutenberg is a Node.js-based project, built primarily in JavaScript. -The easiest way to get started (on MacOS, Linux, or Windows 10 with the Linux Subsystem) is by running the Local Environment setup script, `./bin/setup-local-env.sh`. This will check if you have everything installed and updated, and help you download any extra tools you need. +The first step is to install a recent version of Node. The easiest way (on MacOS, Linux, or Windows 10 with the Linux Subsystem) is by installing and running [nvm]. Once `nvm` is installed, you can install the correct version of Node by running `nvm install` in the Gutenberg directory. -For another version of Windows, or if you prefer to set things up manually, be sure to have Node.js installed first. You should be running a Node version matching the [current active LTS release](https://github.com/nodejs/Release#release-schedule) or newer for this plugin to work correctly. You can check your Node.js version by typing `node -v` in the Terminal prompt. - -If you have an incompatible version of Node in your development environment, you can use [nvm] to change node versions on the command line: +Once you have Node installed, run these scripts: ``` -nvm install -nvm use +npm install +npm run build ``` -You also should have the latest release of [npm installed][npm]. npm is a separate project from Node.js and is updated frequently. If you've just installed Node.js which includes a version of npm within the installation you most likely will need also to update your npm installation. To update npm, type this into your terminal: `npm install npm@latest -g` +This will build Gutenberg, ready to be used as a WordPress plugin! -To test the plugin, or to contribute to it, you can clone this repository and build the plugin files using Node. How you do that depends on whether you're developing locally or uploading the plugin to a remote host. +If you don't have a local WordPress environment to load Gutenberg in, we can help get that up and running, too. ## Local Environment -First, you need a WordPress Environment to run the plugin on. The quickest way to get up and running is to use the provided docker setup. Install [docker](https://www.docker.com/) and [docker-compose](https://docs.docker.com/compose/) by following the most recent instructions on the docker site. +The quickest way to get up and running is to use the provided Docker setup. If you don't already have it, you'll need to install Docker by following their instructions for [Windows 10 Pro](https://docs.docker.com/docker-for-windows/install/), [all other version of Windows](https://docs.docker.com/toolbox/toolbox_install_windows/), [macOS](https://docs.docker.com/docker-for-mac/install/), or [Linux](https://docs.docker.com/v17.12/install/linux/docker-ce/ubuntu/#install-using-the-convenience-script). -In the folder of your preference, clone this project and enter the working directory: -```bash -git clone git@github.com:WordPress/gutenberg.git -cd gutenberg -``` +Once Docker is installed and running, run this script to install WordPress, and build your local environment: -Then, run a setup script to check if docker and node are configured properly and starts the local WordPress instance. You may need to run this script multiple times if prompted. ``` -./bin/setup-local-env.sh +npm run env install ``` -**If you're developing themes, or core WordPress functionality alongside Gutenberg**, you can make the WordPress files accessible in `wordpress/` by following these instructions instead: +WordPress will be installed in the `wordpress` directory, if you need to access WordPress core files directly, you can find them there. -1. If this is your first time setting up the environment, run `DOCKER_ENV=localwpdev ./bin/setup-local-env.sh` instead of `./bin/setup-local-env.sh` -2. If you've already had the previous environment set up, you need to start fresh, and you can do that by first running `docker-compose down --rmi all`. After that, you can repeat step 1. -3. If you turn off your computer or restart Docker, you can get your local WordPress dev environment back by typing `docker-compose -f docker-compose.yml -f docker-compose-localdev.yml up`. If you just run `docker-compose up`, you will get the vanilla install that doesn't expose the WordPress folder. +If you already have WordPress checked out in a different directory, you can use that installation, instead, by running these commands: -**If everything was successful**, you'll see the following ASCII art: ``` -Welcome to... - -,⁻⁻⁻· . | -| ،⁓’. . |--- ,---. ,---. |---. ,---. ,---. ,---. -| | | | | |---' | | | | |---' | | | -`---' `---' `---’ `---’ ' ` `---' `---’ ` `---| - `---' +export WP_DEVELOP_DIR=/path/to/wordpress-develop +npm run env connect ``` -The WordPress installation should be available at `http://localhost:8888` (**Username**: `admin`, **Password**: `password`). -Inside the "docker" directory, you can use any docker command to interact with your containers. If this port is in use, you can override it in your `docker-compose.override.yml` file. If you're running [e2e tests](/docs/contributors/testing-overview.md#end-to-end-testing), this change will be used correctly. +This will use WordPress' own local environment, and mount your Gutenberg directory as a volume there. -To bring down this local WordPress instance later run: -``` -docker-compose down -``` +In Windows, you can set the `WP_DEVELOP_DIR` environment variable using the appropriate method for your shell: -If you'd like to see your changes reflected in this local WordPress instance, run: -``` -npm install -npm run dev -``` + CMD: set WP_DEVELOP_DIR=/path/to/wordpress-develop + PowerShell: $env:WP_DEVELOP_DIR = "/path/to/wordpress-develop" -Alternatively, you can use your own local WordPress environment and clone this repository right into your `wp-content/plugins` directory. +The WordPress installation should be available at `http://localhost:8889` (**Username**: `admin`, **Password**: `password`). +If this port is in use, you can override it using the `LOCAL_PORT` environment variable. For example, `export LOCAL_PORT=7777` will change the URL to `http://localhost:7777` . If you're running [e2e tests](/docs/contributors/testing-overview.md#end-to-end-testing), this change will be used correctly. -Next, open a terminal (or if on Windows, a command prompt) and navigate to the repository you cloned. Now type `npm install` to get the dependencies all set up. Then you can type `npm run dev` in your terminal or command prompt to keep the plugin building in the background as you work on it. +To bring down this local WordPress instance later run `npm run env stop`. To bring it back up again, run `npm run env start`. -WordPress comes with specific [debug systems](https://wordpress.org/support/article/debugging-in-wordpress/) designed to simplify the process as well as standardize code across core, plugins and themes. It is possible to use environment variables (`WP_DEBUG` and `SCRIPT_DEBUG`) to update a site's configuration constants located in `wp-config.php` file. Both flags can be disabled at any time by running the following command: +WordPress comes with specific [debug systems](https://wordpress.org/support/article/debugging-in-wordpress/) designed to simplify the process as well as standardize code across core, plugins and themes. It is possible to use environment variables (`LOCAL_WP_DEBUG` and `LOCAL_SCRIPT_DEBUG`) to update a site's configuration constants located in `wp-config.php` file. Both flags can be disabled at any time by running the following command: ``` -SCRIPT_DEBUG=false WP_DEBUG=false ./bin/setup-local-env.sh +LOCAL_SCRIPT_DEBUG=false LOCAL_WP_DEBUG=false npm run env install ``` By default, both flags will be set to `true`. diff --git a/package-lock.json b/package-lock.json index b7f5355b393f64..442fe4ca5fc62a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5268,16 +5268,22 @@ "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", "jest": "^24.7.1", "jest-puppeteer": "^4.3.0", + "js-yaml": "3.13.1", + "lodash": "^4.17.14", "minimist": "^1.2.0", "npm-package-json-lint": "^3.6.0", "puppeteer": "^1.19.0", "read-pkg-up": "^1.0.1", + "request": "2.88.0", "resolve-bin": "^0.4.0", "source-map-loader": "^0.2.4", + "sprintf-js": "^1.1.1", "stylelint": "^9.10.1", "stylelint-config-wordpress": "^13.1.0", "thread-loader": "^2.1.2", @@ -5285,6 +5291,97 @@ "webpack-bundle-analyzer": "^3.3.2", "webpack-cli": "^3.1.2", "webpack-livereload-plugin": "^2.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + } } }, "@wordpress/server-side-render": { @@ -6722,6 +6819,16 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -7116,6 +7223,12 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -7307,6 +7420,23 @@ "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==", "dev": true }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + }, + "dependencies": { + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + } + } + }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -9808,6 +9938,47 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress-zip": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.2.2.tgz", + "integrity": "sha512-v+Na3Ck86Px7s2ix+f77pMQC3GlkxHHN+YyvnkEW7+xX5F39pcDpIV/VFvGYk8MznTFcMoPjL3XNWEJLXWoSPw==", + "dev": true, + "requires": { + "binary": "^0.3.0", + "graceful-fs": "^4.1.3", + "mkpath": "^0.1.0", + "nopt": "^3.0.1", + "q": "^1.1.2", + "readable-stream": "^1.1.8", + "touch": "0.0.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -18495,6 +18666,12 @@ "mkdirp": "*" } }, + "mkpath": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", + "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=", + "dev": true + }, "modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", @@ -25636,6 +25813,26 @@ "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", "dev": true }, + "touch": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", + "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", + "dev": true, + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + } + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", diff --git a/package.json b/package.json index df3d6103b44bd3..238c6a0dc1be32 100644 --- a/package.json +++ b/package.json @@ -188,13 +188,13 @@ "dev:packages": "node ./bin/packages/watch.js", "docs:build": "node ./docs/tool/index.js && node ./bin/update-readmes.js", "fixtures:clean": "rimraf \"packages/e2e-tests/fixtures/blocks/*.+(json|serialized.html)\"", - "fixtures:server-registered": "docker-compose run -w /var/www/html/wp-content/plugins/gutenberg --rm wordpress ./bin/get-server-blocks.php > test/integration/full-content/server-registered.json", + "fixtures:server-registered": "wp-scripts env docker-run php ./bin/get-server-blocks.php > test/integration/full-content/server-registered.json", "fixtures:generate": "npm run fixtures:server-registered && cross-env GENERATE_MISSING_FIXTURES=y npm run test-unit", "fixtures:regenerate": "npm run fixtures:clean && npm run fixtures:generate", "lint": "concurrently \"npm run lint-js\" \"npm run lint-pkg-json\" \"npm run lint-css\" \"npm run lint-types\"", "lint-js": "wp-scripts lint-js", "lint-js:fix": "npm run lint-js -- --fix", - "lint-php": "docker-compose run --rm composer run-script lint", + "lint-php": "wp-scripts env lint-php", "lint-pkg-json": "wp-scripts lint-pkg-json ./packages", "lint-css": "wp-scripts lint-style '**/*.scss'", "lint-css:fix": "npm run lint-css -- --fix", @@ -206,7 +206,7 @@ "publish:dev": "npm run build:packages && lerna publish --npm-tag next", "publish:prod": "npm run build:packages && lerna publish", "test": "npm run lint && npm run test-unit", - "pretest-e2e": "cross-env SCRIPT_DEBUG=false ./bin/reset-local-e2e-tests.sh", + "pretest-e2e": "npm run env reinstall", "test-e2e": "wp-scripts test-e2e --config packages/e2e-tests/jest.config.js", "test-e2e:watch": "npm run test-e2e -- --watch", "test-performance": "wp-scripts test-e2e --config packages/e2e-tests/jest.performance.config.js", @@ -214,12 +214,14 @@ "test-unit": "wp-scripts test-unit-js --config test/unit/jest.config.js", "test-unit:update": "npm run test-unit -- --updateSnapshot", "test-unit:watch": "npm run test-unit -- --watch", - "test-unit-php": "docker-compose run --rm wordpress_phpunit phpunit", - "test-unit-php-multisite": "docker-compose run -e WP_MULTISITE=1 --rm wordpress_phpunit phpunit", + "test-unit-php": "wp-scripts env test-php", + "test-unit-php-multisite": "cross-env WP_MULTISITE=1 wp-scripts env test-php", "test-unit:native": "cd test/native/ && cross-env NODE_ENV=test jest --config ./jest.config.js", "test-unit:native:debug": "cd test/native/ && node --inspect ../../node_modules/.bin/jest --runInBand --config ./jest.config.js", "playground:build": "npm run build:packages && parcel build playground/src/index.html -d playground/dist", - "playground:start": "concurrently \"npm run dev:packages\" \"parcel playground/src/index.html -d playground/dist\"" + "playground:start": "concurrently \"npm run dev:packages\" \"parcel playground/src/index.html -d playground/dist\"", + "preenv": "npm run check-engines", + "env": "wp-scripts env" }, "lint-staged": { "packages/*/package.json": [ @@ -237,5 +239,18 @@ "packages/**/*.js": [ "node ./bin/update-readmes.js" ] + }, + "wp-env": { + "plugin-dir": "gutenberg", + "plugin-name": "Gutenberg", + "docker-template": "./bin/docker-compose.override.yml.template", + "welcome-logo": [ + ",⁻⁻⁻· . |", + "| ،⁓’. . |--- ,---. ,---. |---. ,---. ,---. ,---.", + "| | | | | |---' | | | | |---' | | |", + "`---' `---' `---’ `---’ ' ` `---' `---’ ` `---|", + " `---'" + ], + "welcome-build-command": "npm run dev" } } diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 0558ef4dc33abc..8817e8a699bfa4 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New Features + +- Add the new `env` family of scripts [(#17004](https://github.com/WordPress/gutenberg/pull/17004/)). + ## 4.0.0 (2019-08-29) ### Breaking Changes diff --git a/packages/scripts/README.md b/packages/scripts/README.md index 50b95ff07c5e3e..ff62c86c3352d4 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -117,6 +117,56 @@ _Flags_: - `--gpl2`: Validates against [GPLv2 license compatibility](https://www.gnu.org/licenses/license-list.en.html) - `--ignore=a,b,c`: A comma-separated set of package names to ignore for validation. This is intended to be used primarily in cases where a dependency’s `license` field is malformed. It’s assumed that any `ignored` package argument would be manually vetted for compatibility by the project owner. +### `env` + +`env` is a family of scripts for setting up a local Docker-based development environment that plugin contributors can work in. + +To get started, it requires some configuration in your `package.json`: + +_Example:_ + +```json +{ + "scripts": { + "env": "wp-scripts env" + }, + "wp-env": { + "plugin-dir": "gutenberg", + "plugin-name": "Gutenberg", + "docker-template": "./bin/docker-compose.override.yml.template", + "welcome-logo": [ + ",⁻⁻⁻· . |", + "| ،⁓’. . |--- ,---. ,---. |---. ,---. ,---. ,---.", + "| | | | | |---' | | | | |---' | | |", + "`---' `---' `---’ `---’ ' ` `---' `---’ ` `---|", + " `---'" + ], + "welcome-build-command": "npm run dev" + } +} +``` + +In the `wp-env` config block, each entry can be configured like so: +- `plugin-dir`: Required. The name of the plugin directory within `wp-content/plugins` that this plugin will be mounted in. +- `plugin-name`: Required. The display name for this plugin. +- `docker-template`: Optional. If you need to customize the default `docker-compose.override.yml.template`, this is the path to your customized version. +- `welcome-logo`: Optional. An ASCII art logo to show after `npm run env install` finishes. +- `welcome-build-command`: Optional. The build command to show after `npm run env install` finishes, helping contributors move on to the next step. + +#### Available Sub-Scripts + +- `install`: Automatically downloads, builds, and installs a copy of WordPress to work with. This will be installed in the `wordpress` folder inside your project. You should add `wordpress` to your `.gitignore` file. +- `connect`: For contributors that have a WordPress respository already, they can define the `WP_DEVELOP_DIR` environment variable with the path to their repository, then run this command to add your plugin to it. +- `start`: Starts the Docker containers. +- `stop`: Stops the Docker containers. +- `update`: For contributors that used `npm run env install` to setup WordPress, running this command will update it to the latest checkout. +- `reinstall`: Resets the database and re-configures WordPress again. +- `cli`: Runs WP-CLI commands against the WordPress install. +- `lint-php`: Run PHPCS linting on your plugin. You will need to have `composer.json` configured to install PHPCS, with a `lint` script that runs your linting. You will also need to have an appropriately configured `phpcs.xml.dist` file. +- `test-php`: Runs your plugin's PHPUnit tests. You will need to have an appropriately configured `phpunit.xml.dist` file. +- `docker-run`: For more advanced debugging, contributors may sometimes need to run commands in the Docker containers. This is the equivalent of running `docker-compose run` within the WordPress directory. + + ### `lint-js` Helps enforce coding style guidelines for your JavaScript files. diff --git a/packages/scripts/config/docker-compose.override.yml.template b/packages/scripts/config/docker-compose.override.yml.template new file mode 100644 index 00000000000000..092d2df9c3568c --- /dev/null +++ b/packages/scripts/config/docker-compose.override.yml.template @@ -0,0 +1,13 @@ +services: + wordpress-develop: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% + php: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% + cli: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% + phpunit: + volumes: + - %PLUGIN_MOUNT_DIR%:/var/www/${LOCAL_DIR-src}/wp-content/plugins/%PLUGIN_INSTALL_DIR% diff --git a/packages/scripts/package.json b/packages/scripts/package.json index eb3e0f90fa9344..043c2fec77f2c7 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -41,16 +41,22 @@ "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", "jest": "^24.7.1", "jest-puppeteer": "^4.3.0", + "js-yaml": "3.13.1", + "lodash": "^4.17.14", "minimist": "^1.2.0", "npm-package-json-lint": "^3.6.0", "puppeteer": "^1.19.0", "read-pkg-up": "^1.0.1", + "request": "2.88.0", "resolve-bin": "^0.4.0", "source-map-loader": "^0.2.4", + "sprintf-js": "^1.1.1", "stylelint": "^9.10.1", "stylelint-config-wordpress": "^13.1.0", "thread-loader": "^2.1.2", diff --git a/packages/scripts/scripts/env.js b/packages/scripts/scripts/env.js new file mode 100644 index 00000000000000..000a4fca2e270f --- /dev/null +++ b/packages/scripts/scripts/env.js @@ -0,0 +1,62 @@ +/** + * External dependencies + */ +const chalk = require( 'chalk' ); + +/** + * Node dependencies. + */ +const { env, exit, stdout, cwd } = require( 'process' ); +const { normalize } = require( 'path' ); +const { existsSync } = require( 'fs' ); + +/** + * Internal dependencies + */ +const { + getArgsFromCLI, + spawnScript, +} = require( '../utils' ); + +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.', + 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.', + 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' ) + '.', + }; + + 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' ) ); + + Object.keys( scripts ).forEach( ( script ) => { + stdout.write( chalk.green( script ) + '\n ' + chalk.white( scripts[ script ] ) + '\n\n' ); + } ); + exit( 0 ); +} + +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' ); + 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" ) ); + exit( 1 ); + } +} + +spawnScript( `env/${ command }`, args ); diff --git a/packages/scripts/scripts/env/cli.js b/packages/scripts/scripts/env/cli.js new file mode 100644 index 00000000000000..ec1141a710965e --- /dev/null +++ b/packages/scripts/scripts/env/cli.js @@ -0,0 +1,17 @@ +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env } = require( 'process' ); + +/** + * Internal dependencies + */ +const { getArgsFromCLI } = require( '../../utils' ); + +const args = getArgsFromCLI(); + +const localDir = env.LOCAL_DIR || 'src'; + +// Run WP-CLI with the working directory set correctly. +execSync( `npm run env:cli -- --path=/var/www/${ localDir } ` + args.join( ' ' ), { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/connect.js b/packages/scripts/scripts/env/connect.js new file mode 100644 index 00000000000000..a18bdf5c323740 --- /dev/null +++ b/packages/scripts/scripts/env/connect.js @@ -0,0 +1,77 @@ +/** + * External dependencies + */ +const yaml = require( 'js-yaml' ); + +/** + * Node dependencies. + */ +const { existsSync, readFileSync, writeFileSync } = require( 'fs' ); +const { normalize } = require( 'path' ); +const { cwd, env, exit, stdout } = require( 'process' ); +const { execSync } = require( 'child_process' ); + +/** + * Internal dependencies + */ +const { + fromConfigRoot, + mergeYAMLConfigs, +} = require( '../../utils' ); + +const composeFile = normalize( `${ env.WP_DEVELOP_DIR }/docker-compose.override.yml` ); +let compose = {}; +if ( existsSync( composeFile ) ) { + try { + compose = yaml.safeLoad( readFileSync( composeFile, 'utf8' ) ); + } catch ( error ) { + stdout.write( 'There was an error loading your docker-compose.override.yml file. Please fix or delete it, and try again.\n' ); + stdout.write( error.toString() ); + exit( 1 ); + } +} + +const coreComposeFile = normalize( `${ env.WP_DEVELOP_DIR }/docker-compose.yml` ); +if ( ! existsSync( coreComposeFile ) ) { + stdout.write( "docker-compose.yml doesn't seem to exist. Are you sure WP_DEVELOP_DIR is a WordPress source directory?\n" ); + exit( 1 ); +} + +let coreCompose = {}; +try { + coreCompose = yaml.safeLoad( readFileSync( coreComposeFile, 'utf8' ) ); +} catch ( error ) { + stdout.write( 'There was an error loading your docker-compose.yml in your WordPress directory. Please revert any changes to it, and try again.\n' ); + stdout.write( error.toString() ); + exit( 1 ); +} + +const pluginMountDir = cwd(); + +const composeTemplateFile = env.npm_package_wp_env_docker_template ? normalize( cwd() + `/${ env.npm_package_wp_env_docker_template }` ) : fromConfigRoot( 'docker-compose.override.yml.template' ); + +const composeTemplate = readFileSync( composeTemplateFile, 'utf8' ) + .replace( /%PLUGIN_MOUNT_DIR%/gi, pluginMountDir ) + .replace( /%PLUGIN_INSTALL_DIR%/gi, env.npm_package_wp_env_plugin_dir ); + +let pluginCompose = {}; +try { + pluginCompose = yaml.safeLoad( composeTemplate ); +} catch ( error ) { + stdout.write( 'There was an error loading your docker-compose.override.yml.template file. Please revert any changes to it, and try again.\n' ); + stdout.write( error.toString() ); + exit( 1 ); +} + +stdout.write( 'Updating docker-compose.override.yml...\n' ); + +compose.version = coreCompose.version; + +const mergedCompose = mergeYAMLConfigs( compose, pluginCompose, pluginMountDir ); + +writeFileSync( composeFile, yaml.safeDump( mergedCompose, { lineWidth: -1 } ) ); + +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' } ); diff --git a/packages/scripts/scripts/env/docker-run.js b/packages/scripts/scripts/env/docker-run.js new file mode 100644 index 00000000000000..bde99a4dadfdc3 --- /dev/null +++ b/packages/scripts/scripts/env/docker-run.js @@ -0,0 +1,17 @@ +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env } = require( 'process' ); + +/** + * Internal dependencies + */ +const { getArgsFromCLI } = require( '../../utils' ); + +const args = getArgsFromCLI(); + +const localDir = env.LOCAL_DIR || 'src'; + +// Execute any docker-compose command passed to this script, in the WordPress Docker environment. +execSync( `docker-compose run -w /var/www/${ localDir }/wp-content/plugins/${ env.npm_package_wp_env_plugin_dir } --rm ` + args.join( ' ' ), { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/install.js b/packages/scripts/scripts/env/install.js new file mode 100644 index 00000000000000..7eee086a05d84e --- /dev/null +++ b/packages/scripts/scripts/env/install.js @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +const { sync: commandExistsSync } = require( 'command-exists' ); + +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env, exit, cwd, stdout } = require( 'process' ); +const { normalize } = require( 'path' ); +const { existsSync } = require( 'fs' ); + +/** + * Internal dependencies + */ +const { + buildWordPress, + downloadWordPressZip, +} = require( '../../utils' ); +const { hasArgInCLI } = require( '../../utils' ); + +env.WP_DEVELOP_DIR = normalize( cwd() + '/wordpress' ); + +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' ); + 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 ); + } ); +} diff --git a/packages/scripts/scripts/env/lint-php.js b/packages/scripts/scripts/env/lint-php.js new file mode 100644 index 00000000000000..7c93519e933e93 --- /dev/null +++ b/packages/scripts/scripts/env/lint-php.js @@ -0,0 +1,17 @@ +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env } = require( 'process' ); + +/** + * Internal dependencies + */ +const { getArgsFromCLI } = require( '../../utils' ); + +const args = getArgsFromCLI(); + +const localDir = env.LOCAL_DIR || 'src'; + +// Run PHPUnit with the working directory set correctly. +execSync( `docker-compose run --rm -w /var/www/${ localDir }/wp-content/plugins/${ env.npm_package_wp_env_plugin_dir } php composer lint ` + args.join( ' ' ), { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/reinstall.js b/packages/scripts/scripts/env/reinstall.js new file mode 100644 index 00000000000000..a2cfc8cbadf1a7 --- /dev/null +++ b/packages/scripts/scripts/env/reinstall.js @@ -0,0 +1,10 @@ +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); + +// Reset the database. +execSync( 'npm run env cli db reset -- --yes --quiet', { stdio: 'inherit' } ); + +// Do a fast install, no need to re-run the build commands again. +execSync( 'npm run env install -- --fast', { stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/start.js b/packages/scripts/scripts/env/start.js new file mode 100644 index 00000000000000..b563b897ba0c81 --- /dev/null +++ b/packages/scripts/scripts/env/start.js @@ -0,0 +1,30 @@ +/** + * External dependencies + */ +const { sync: commandExistsSync } = require( 'command-exists' ); + +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env, stdout } = require( 'process' ); +const { normalize } = require( 'path' ); +const { statSync } = require( 'fs' ); + +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 lastUpdated = new Date( stat.mtimeMs ); + if ( Date.now() - lastUpdated.getTime() > 7 * 24 * 60 * 60 * 1000 ) { + stdout.write( "\nIt's been a while since you updated WordPress. Run `npm run env update` to update it.\n\n" ); + } +} + +// Start the environment in the WordPress directory. +execSync( 'npm run env:start', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/stop.js b/packages/scripts/scripts/env/stop.js new file mode 100644 index 00000000000000..f0218c606411d8 --- /dev/null +++ b/packages/scripts/scripts/env/stop.js @@ -0,0 +1,8 @@ +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env } = require( 'process' ); + +// Stop the environment in the WordPress directory. +execSync( 'npm run env:stop', { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/test-php.js b/packages/scripts/scripts/env/test-php.js new file mode 100644 index 00000000000000..da3529bd7ec6b6 --- /dev/null +++ b/packages/scripts/scripts/env/test-php.js @@ -0,0 +1,17 @@ +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env } = require( 'process' ); + +/** + * Internal dependencies + */ +const { getArgsFromCLI } = require( '../../utils' ); + +const args = getArgsFromCLI(); + +const localDir = env.LOCAL_DIR || 'src'; + +// Run PHPUnit with the working directory set correctly. +execSync( `npm run test:php -- -c /var/www/${ localDir }/wp-content/plugins/${ env.npm_package_wp_env_plugin_dir }/phpunit.xml.dist ` + args.join( ' ' ), { cwd: env.WP_DEVELOP_DIR, stdio: 'inherit' } ); diff --git a/packages/scripts/scripts/env/update.js b/packages/scripts/scripts/env/update.js new file mode 100644 index 00000000000000..f912992f0b115f --- /dev/null +++ b/packages/scripts/scripts/env/update.js @@ -0,0 +1,32 @@ +/** + * External dependencies + */ +const { sync: commandExistsSync } = require( 'command-exists' ); + +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env, cwd, stdout } = require( 'process' ); +const { normalize } = require( 'path' ); + +/** + * Internal dependencies + */ +const { + buildWordPress, + downloadWordPressZip, +} = 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 ); + } ); +} diff --git a/packages/scripts/utils/env.js b/packages/scripts/utils/env.js new file mode 100644 index 00000000000000..7b2f6d46d6ec8a --- /dev/null +++ b/packages/scripts/utils/env.js @@ -0,0 +1,165 @@ +/** + * External dependencies + */ +const { isPlainObject } = require( 'lodash' ); +const request = require( 'request' ); +const DecompressZip = require( 'decompress-zip' ); +const chalk = require( 'chalk' ); +const { sprintf } = require( 'sprintf-js' ); + +/** + * Node dependencies. + */ +const { execSync } = require( 'child_process' ); +const { env, exit, stdout } = require( 'process' ); +const { normalize } = require( 'path' ); +const { createWriteStream } = require( 'fs' ); +const { tmpdir } = require( 'os' ); + +/** + * Merges two YAML configs together. + * + * All new data from newConfig will be added to originalConfig. When arrays in newConfig look like lists of volume + * mount instructions, it will attempt to replace items that mount from the same location. This allows the config + * to be safely updated, and it'll be reflected in the updated config. + * + * @param {Object} originalConfig The original config object that we're overwriting. + * @param {Object} newConfig A new config object to merge into originalConfig. + * @param {string} baseDir The base directory of the plugin, volumes in this directory belong to the plugin. + * @return {Object} The merged config object. + */ +function mergeYAMLConfigs( originalConfig, newConfig, baseDir ) { + // Loop through each element of newConfig, and test what should be done with them. + Object.keys( newConfig ).forEach( ( key ) => { + if ( ! originalConfig[ key ] ) { + // If the originalConfig object doesn't have this element, we can just add it. + originalConfig[ key ] = newConfig[ key ]; + } else if ( Array.isArray( newConfig[ key ] ) ) { + // If the newConfig element is an array, we need to try and merge them. + // This is intended to merge Docker volume configs, which exist in the form: + // /path/to/local/dir:/path/to/container/dir:config:stuff + + // Build an array from the original config, with items that belong to this plugin removed. + const cleanOriginal = originalConfig[ key ].filter( ( element ) => { + return ! element.startsWith( baseDir ); + } ); + + // Append the newConfig to the remaining config. + originalConfig[ key ] = [ ...cleanOriginal, ...newConfig[ key ] ]; + } else if ( isPlainObject( newConfig[ key ] ) ) { + // If the newConfig element is an object, we need to recursively merge it. + originalConfig[ key ] = mergeYAMLConfigs( originalConfig[ key ], newConfig[ key ], baseDir ); + } else { + // Any other data types are overwritten by the newConfig. + originalConfig[ key ] = newConfig[ key ]; + } + } ); + + return originalConfig; +} + +/** + * Downloads and extracts WordPress from the GitHub repo zip file. + * + * @return {Promise} A promise that resolves when WordPress has been downloaded and extracted. + */ +function downloadWordPressZip() { + return new Promise( ( resolve ) => { + const tmpZip = normalize( tmpdir() + '/wordpress-develop.zip' ); + const tmpZipWriter = createWriteStream( tmpZip ); + + // Set up the unzipper to unzip the archive when it finishes downloading. + tmpZipWriter.on( 'finish', () => { + const unzipper = new DecompressZip( tmpZip ); + + unzipper.on( 'error', ( error ) => { + stdout.write( "ERROR: The zip file couldn't be unzipped.\n" ); + stdout.write( error.toString() ); + exit( 1 ); + } ); + + unzipper.on( 'extract', resolve ); + + stdout.write( 'Extracting...\n' ); + + unzipper.extract( { + path: env.WP_DEVELOP_DIR, + strip: 1, + filter: ( file ) => file.type !== 'Directory', + } ); + } ); + + stdout.write( 'Downloading...\n' ); + // Download the archive. + request + .get( 'https://github.com/WordPress/wordpress-develop/archive/master.zip' ) + .on( 'error', ( error ) => { + stdout.write( "ERROR: The zip file couldn't be downloaded.\n" ); + stdout.write( error.toString() ); + exit( 1 ); + } ) + .pipe( tmpZipWriter ); + } ); +} + +/** + * Runs the appropriate build/install commands in the WordPress directory. + * + * @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 ) { + if ( ! fastInstall ) { + execSync( 'npm install', { 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' } ); + } + } + + 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' } ); + + const currentUrl = execSync( 'npm run --silent env cli option get siteurl' ).toString().trim(); + + stdout.write( chalk.white( '\nWelcome to...\n' ) ); + for ( let ii = 0; env[ `npm_package_wp_env_welcome_logo_${ ii }` ]; ii++ ) { + stdout.write( chalk.green( env[ `npm_package_wp_env_welcome_logo_${ ii }` ] ) + '\n' ); + } + + if ( env.npm_package_wp_env_welcome_build_command ) { + const nextStep = sprintf( + '\nRun %s to build the latest version of %s, then open %s to get started!\n', + chalk.blue( env.npm_package_wp_env_welcome_build_command ), + chalk.green( env.npm_package_wp_env_plugin_name ), + chalk.blue( currentUrl ) + ); + stdout.write( chalk.white( nextStep ) ); + } + + stdout.write( chalk.white( '\nAccess the above install using the following credentials:\n' ) ); + + const access = sprintf( + 'Default username: %s, password: %s\n', + chalk.blue( 'admin' ), + chalk.blue( 'password' ) + ); + + stdout.write( chalk.white( access ) ); + } +} + +module.exports = { + buildWordPress, + downloadWordPressZip, + mergeYAMLConfigs, +}; diff --git a/packages/scripts/utils/index.js b/packages/scripts/utils/index.js index c45b1b6abbee1e..3d5e3bd7ac4386 100644 --- a/packages/scripts/utils/index.js +++ b/packages/scripts/utils/index.js @@ -14,6 +14,11 @@ const { hasBabelConfig, hasJestConfig, } = require( './config' ); +const { + buildWordPress, + downloadWordPressZip, + mergeYAMLConfigs, +} = require( './env' ); const { fromConfigRoot, hasProjectFile, @@ -26,6 +31,7 @@ const { } = require( './string' ); module.exports = { + buildWordPress, camelCaseDash, fromConfigRoot, getArgFromCLI, @@ -38,5 +44,7 @@ module.exports = { hasJestConfig, hasPackageProp, hasProjectFile, + downloadWordPressZip, + mergeYAMLConfigs, spawnScript, }; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 2eb5f4eae3c4b8..e799a44754caf4 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -7,7 +7,7 @@ convertWarningsToExceptions="true" > - + ./phpunit/ diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index 8aab3cac808dd7..17989ee336b117 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -5,6 +5,11 @@ * @package Gutenberg */ +// If we're running in WP's build directory, ensure that WP knows that, too. +if ( 'build' === getenv( 'LOCAL_DIR' ) ) { + define( 'WP_RUN_CORE_TESTS', true ); +} + // Determine the tests directory (from a WP dev checkout). // Try the WP_TESTS_DIR environment variable first. $_tests_dir = getenv( 'WP_TESTS_DIR' );