From a9222a93fc00e8f1d299960111d952b65acb41cc Mon Sep 17 00:00:00 2001 From: Senad Uka Date: Sun, 5 Jul 2020 16:49:14 +0200 Subject: [PATCH] Initial commit --- .travis.yml | 29 ++++++++ README.md | 137 ++++++++++++++++++++++++++++++++++++ bin/install-wp-tests.sh | 127 +++++++++++++++++++++++++++++++++ bin/install-wp.sh | 16 +++++ class-my-plugin.php | 18 +++++ docker-compose.phpunit.yml | 17 +++++ docker-compose.yml | 57 +++++++++++++++ phpcs.ruleset.xml | 10 +++ phpunit.xml.dist | 14 ++++ tests/bootstrap.php | 25 +++++++ tests/class-test-sample.php | 20 ++++++ 11 files changed, 470 insertions(+) create mode 100644 .travis.yml create mode 100644 README.md create mode 100755 bin/install-wp-tests.sh create mode 100755 bin/install-wp.sh create mode 100644 class-my-plugin.php create mode 100644 docker-compose.phpunit.yml create mode 100644 docker-compose.yml create mode 100644 phpcs.ruleset.xml create mode 100644 phpunit.xml.dist create mode 100644 tests/bootstrap.php create mode 100644 tests/class-test-sample.php diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b230c62 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +sudo: false + +language: php + +notifications: + email: + on_success: never + on_failure: change + +branches: + only: + - master + +php: + - 5.6 + +matrix: + include: + - php: 5.6 + env: WP_VERSION=latest + +before_script: + - export PATH="$HOME/.composer/vendor/bin:$PATH" + - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION + - composer global require "phpunit/phpunit=4.8.*|5.7.*" + +script: + - phpunit + - WP_MULTISITE=1 phpunit diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c1df65 --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +# WordPress plugin or theme development with Docker Compose + +[![Build status][build-status]][travis-ci] + +This is an example repo for how one might wire up Docker Compose for local +plugin or theme development. It provides WordPress, MariaDB, WP-CLI, PHPUnit, +and the WordPress unit testing suite. + + +## Set up + +1. Clone or fork this repo. + +2. Put your plugin or theme code in the root of this folder and adjust the + `services/wordpress/volumes` section of `docker-compose.yml` so that it + syncs to the appropriate directory. + +3. Add `project.test` to `/etc/hosts`, e.g.: + + ``` + 127.0.0.1 localhost project.test + ``` + + +## Start environment + +```sh +docker-compose up -d +``` + +The first time you run this, it will take a few minutes to pull in the required +images. On subsequent runs, it should take less than 30 seconds before you can +connect to WordPress in your browser. (Most of this time is waiting for MariaDB +to be ready to accept connections.) + +The `-d` flag backgrounds the process and log output. To view logs for a +specific container, use `docker-compose logs [container]`, e.g.: + +```sh +docker-compose logs wordpress +``` + +Please refer to the [Docker Compose documentation][docker-compose] for more +information about starting, stopping, and interacting with your environment. + + +## Install WordPress + +```sh +docker-compose run --rm wp-cli install-wp +``` + +Log in to `http://project.test/wp-admin/` with `wordpress` / `wordpress`. + +Alternatively, you can navigate to `http://project.test/` and manually perform +the famous five-second install. + + +## WP-CLI + +You will probably want to [create a shell alias][3] for this: + +```sh +docker-compose run --rm wp-cli wp [command] +``` + + +## Running tests (PHPUnit) + +The tests in this example repo were generated with WP-CLI, e.g.: + +```sh +docker-compose run --rm wp-cli wp scaffold plugin-tests my-plugin +``` + +This is not required, however, and you can bring your own test scaffold. The +important thing is that you provide a script to install your test dependencies, +and that these dependencies are staged in `/tmp`. + +The testing environment is provided by a separate Docker Compose file +(`docker-compose.phpunit.yml`) to ensure isolation. To use it, you must first +start it, then manually run your test installation script. These commands work +for this example repo, but may not work for you if you use a different test +scaffold. + +Note that, in the PHPUnit container, your code is mapped to `/app`. + +```sh +docker-compose -f docker-compose.yml -f docker-compose.phpunit.yml up -d +docker-compose -f docker-compose.phpunit.yml run --rm wordpress_phpunit /app/bin/install-wp-tests.sh wordpress_test root '' mysql_phpunit latest true +``` + +Now you are ready to run PHPUnit. Repeat this command as necessary: + +```sh +docker-compose -f docker-compose.phpunit.yml run --rm wordpress_phpunit phpunit +``` + + +## Changing the hostname + +You can change the hostname from the default `project.test` by adding a `.env` +file at the project root and defining the `DOCKER_DEV_DOMAIN` environment +variable: + +``` +DOCKER_DEV_DOMAIN=myproject.test +``` + + +## Seed MariaDB database + +The `mariadb` image supports initializing the database with content by mounting +a volume to the database container at `/docker-entrypoint-initdb.d`. See the +[MariaDB Docker docs][mariadb-docs] for more information. + + +## Troubleshooting + +If your stack is not responding, the most likely cause is that a container has +stopped or failed to start. Check to see if all of the containers are "Up": + +``` +docker-compose ps +``` + +If not, inspect the logs for that container, e.g.: + +``` +docker-compose logs wordpress +``` + + +[build-status]: https://travis-ci.org/chriszarate/docker-compose-wordpress.svg?branch=master +[travis-ci]: https://travis-ci.org/chriszarate/docker-compose-wordpress +[docker-compose]: https://docs.docker.com/compose/ +[mariadb-docs]: https://github.com/docker-library/docs/tree/master/mariadb#initializing-a-fresh-instance diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh new file mode 100755 index 0000000..73bb4c7 --- /dev/null +++ b/bin/install-wp-tests.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash + +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/} + +download() { + if [ `which curl` ]; then + curl -s "$1" > "$2"; + elif [ `which wget` ]; then + wget -nv -O "$2" "$1" + fi +} + +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 + mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA +} + +install_wp +install_test_suite +install_db diff --git a/bin/install-wp.sh b/bin/install-wp.sh new file mode 100755 index 0000000..2c84d97 --- /dev/null +++ b/bin/install-wp.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +# Install WordPress. +wp core install \ + --title="Project" \ + --admin_user="wordpress" \ + --admin_password="wordpress" \ + --admin_email="admin@example.com" \ + --url="http://project.test" \ + --skip-email + +# Update permalink structure. +wp option update permalink_structure "/%year%/%monthnum%/%postname%/" --skip-themes --skip-plugins + +# Activate plugin. +wp plugin activate my-plugin diff --git a/class-my-plugin.php b/class-my-plugin.php new file mode 100644 index 0000000..9d5e4d6 --- /dev/null +++ b/class-my-plugin.php @@ -0,0 +1,18 @@ + + + Generally-applicable sniffs for WordPress plugins + + + + + */node_modules/* + */vendor/* + diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..c6bd903 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + ./tests/ + + + diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..99a8fbe --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,25 @@ +assertTrue( class_exists( 'My_Plugin' ) ); + } +}