From 0a1fb161f0227db38470708cad80c7a55e71fdd0 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Thu, 17 Mar 2022 10:15:15 +0100 Subject: [PATCH] CI: switch to GitHub Actions - step 6: PHP integration tests This commit: * Adds a GH Actions workflow for the PHPUnit Integration test CI check. * Removes all references to that check from the `.travis.yml` configuration. * Replaces the "Build Status" badge in the Readme with a badge using the results from the GH `IntegrationTest` Action runs. All other workflows have their own status badges, so the Travis badge can now be safely removed. Notes: 1. Builds will run on: - Select pushes using branch filtering similar to before. - All pull requests. - When manually triggered. Note: manual triggering of builds has to be [explicitly allowed](https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/). This is not a feature which is enabled by default. 2. If a previous GH actions run for the same branch hadn't finished yet when the same branch is pushed again, the previous run will be cancelled. In Travis, this was an option on the "Settings" page - "Auto cancellation" -, which was turned on for most, if not all, Yoast repos. The `concurrency` configuration in the GHA script emulates the same behaviour. 3. In contrast to various other scripts, the matrix for these integration tests is explicitly set with all variables explicitly defined for each build, as we want full control over the three variables (`php_version`, `wp_version` and `multisite`) used for each run. 4. As a MySQL database is needed, we need to explicitly add that service. The MySQL version used varies based on the PHP version against which the tests are run for two reasons: 1. It's good practice to test against multiple different MySQL versions to verify that any queries run are MySQL cross-version compatible. 2. While WP is _supposed to_ support MySQL 8.0 since WP 5.4, in actual fact, WordPress doesn't fully support MySQL 8.0 on PHP < 7.4. Also see: https://core.trac.wordpress.org/ticket/52496 Note: in the Travis script, the PHP 5.6 build was explicitly set to use the `trusty` dist to force the use of MySQL 5.6. In GH Actions, this is not directly linked to the Ubuntu image used. All the same, the script has been set up to explicitly use MySQL 5.6 for PHP 5.6, same as before. 5. The default ini settings used by the `setup-php` action are based on the `php.ini-production` configuration. This means that `error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT`, `display_errors` is set to `Off` and `zend.assertions` is set to `-1` (= do not compile). For the purposes of CI, especially for linting and testing code, I'd recommend running with `zend.assertions=-1`, `error_reporting=-1` and `display_errors=On` to ensure **all** PHP notices are shown. Note: the defaults will be changed in the next major of `setup-php` to be based on the `php.ini-develop` configuration, but that may still be a while off. Refs: * https://github.com/shivammathur/setup-php/issues/450 * https://github.com/shivammathur/setup-php/issues/469 6. While the `setup-php` action offers the ability to [install the PHAR file for PHPUnit](https://github.com/shivammathur/setup-php#wrench-tools-support), I've elected not to use that option as we need to do a `composer install` anyway to get the other dependencies, like WP Test Utils. 7. The PHPUnit version(s) supported and needed to run the tests depend on **both** the WP version used as well as the PHP version used. As an `if` condition on a step would get pretty complicated to handle this, I've introduced a separate - fully documented - step to determine the "type" of install we need. The output of that step is subsequently used in the `if` condition for follow-on steps to make sure the correct PHPUnit version will be installed by Composer. 8. Composer dependency downloads will be cached for faster builds using a [predefined GH action](https://github.com/marketplace/actions/install-composer-dependencies) specifically created for this purpose. The alternative would be to handle the caching manually, which would add three extra steps to the script. Note: Caching works differently between Travis and GH Actions. On GH Actions, once a cache has been created, it can't be updated. It can only be replaced by a new cache with a different key. As the PHP version, the `composer.json` and a potential `composer.lock` hash are all part of the key used by the above mentioned action, this difference should not have a significant impact. Ref: https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows 9. As there is a committed `composer.lock` file and the PHPUnit version is locked at PHPUnit 5.x, we have to do an on-the-fly update of the PHPUnit version depending on the WP and PHP version used for the current build. As we still also want to benefit from the Composer caching which the `ramsey/composer-install` action sets up, I've done some nifty trickery with the options passed to the `composer-install` action to get that working. - The `dependency-versions: "highest"` basically changes the command used by the action from `composer install` to `composer update`, however we don't want to update _all_ dependencies as run-time dependencies should remain locked at their original version. - To that end, I'm passing additional `composer-options` which will limit the update to just and only the test dependencies. - These type of updates are only run when needed based on the "install type" determination as described in (7). 10. Installing WordPress was previously done via inline commands in the Travis script. This has now been replaced by the more comprehensive `tests/bin/install-wp-tests.sh` script as made available by the WP CLI `scaffold` command. As WPCLI is not used anywhere else in the workflow, a copy of the script, with source annotations, is being introduced into the plugin codebase. Note: this script needs to have the `x` flag set to allow it to be executed. Ref: https://github.com/wp-cli/scaffold-command/blob/master/templates/install-wp-tests.sh Some differences between the scripts: - The plugin will no longer be copied into the WordPress install, as, to be honest, that's just not necessary with the current test setup/test bootstrap. - The location to which WP is downloaded and installed is different between the scripts, however, this makes no difference for our purposes as the WP Test Utils library already takes the default install locations from the `install-wp-tests.sh` script into account. - To test against the "nightly" of WordPress, the matrix needs to set the `wp_version` to `trunk` or `nightly` instead of `master` (as was previously used in some scripts). - WordPress will be set up to always use `mysqli` for database commands, even on PHP 5.6. Differences with the Travis implementation: * The most appropriate version of the test dependencies will now be used for _all_ builds, not just for builds against PHP 8.0/`nightly`. * Except for the test dependencies, no other dependencies will be updated during the test run. * In Travis, there was a reference to a `atanamo/php-codeshift` package, which was removed after the prefixing was finished. This package is not a (root) dependency of the WPSEO Free plugin, so removing it doesn't actually have any effect. Instead, the `league/oauth2-client` package is removed, as that package should not be used during the test run as it will be prefixed and the prefixed version should be used instead. * The "mix" of PHP/WP versions + Multisite used in the matrix has been adjusted slightly compared to Travis. The current mix in GHA ensure there is a run against high + low WP on low PHP, a run against high + low WP on high PHP and a run against mulisite for all supported WP versions. * In addition to the PHP versions against which the tests were previously run on Travis, the tests will now also be run against PHP 8.1. As PHP 8.1 has been released, the (remaining) test failures on this build need to be fixed, though as these are only _deprecation notices_, the fact that these tests are currently failing is nothing to be too concerned about for the time being. To prevent new failures from being introduced in the mean time, I'm not allowing the build to fail, but will instead add expectations for the deprecations or skip requirements to the few tests which still have them for the time being. Builds against WP `trunk`, will be "allowed to fail". Note: if a "allowed to fail" job actually fails, the workflow will show as successful, but there will still be a red `x` next to a PR. This is a known issue in GHA: https://github.com/actions/toolkit/issues/399 There are work-arounds possible for this, however, the work-arounds would hide failures even more, meaning that chances are they won't be seen until they actually become a problem (no longer allowed to fail), which is too late. * Instead of using Git to clone WP, the WP-CLI script is now used to retrieve the relevant parts of WP and initiate the database and the `wp-config` settings. * There are a number of files which are usually created by Grunt and are needed during the test run. In Travis, these files were created on the fly from within the Travis script to ensure tests would not error out on these files missing.. As this was only done in Travis, PHP focussed plugin developers who rarely use Grunt locally, would still end up with these errors when they would run the tests locally. As the need for these files is inherent to the integration tests, creating these files from within the integration test bootstrap file will make this more stable and will allow this to work both in CI as for dev-local test runs. * In Travis, test runs would run either as single site or as multisite. In GH Actions, each build will always run the tests against WP in single site mode and for those builds with the `multisite` flag set to `true` in the matrix, the test will **_also_** be run in multisite mode. * In Travis, for select test runs, code coverage would be calculated and uploaded to CodeClimate. As CodeClimate did not signal back to PRs if a PR changed the code coverage and by how much, this was not very effective, other than to keep track over time, though in practice, nobody seemed to even check on this or check on the reports at all. With this in mind, code coverage will no longer be run, nor uploaded to CodeClimate. The intention is to eventually run code coverage on the Jenkins server. --- .github/workflows/integrationtest.yml | 176 ++++++++++++++++++++++++ .travis.yml | 135 +----------------- README.md | 2 +- config/scripts/install-wp-tests.sh | 189 ++++++++++++++++++++++++++ tests/integration/bootstrap.php | 54 ++++++++ 5 files changed, 424 insertions(+), 132 deletions(-) create mode 100644 .github/workflows/integrationtest.yml create mode 100755 config/scripts/install-wp-tests.sh diff --git a/.github/workflows/integrationtest.yml b/.github/workflows/integrationtest.yml new file mode 100644 index 00000000000..2c46215e655 --- /dev/null +++ b/.github/workflows/integrationtest.yml @@ -0,0 +1,176 @@ +name: Integration Test + +on: + # Run on pushes to select branches and on all pull requests. + push: + branches: + - master + - trunk + - 'release/**' + - 'hotfix/[0-9]+.[0-9]+*' + - 'feature/**' + pull_request: + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + integration-test: + runs-on: ubuntu-latest + + strategy: + matrix: + include: + - php_version: '5.6' + wp_version: '5.8' + multisite: true + + - php_version: '7.0' + wp_version: 'latest' + multisite: false + + - php_version: '7.3' + wp_version: 'trunk' + multisite: true + + - php_version: '7.4' + wp_version: 'latest' + multisite: false + + # WP 5.6 is the earliest version which (sort of) supports PHP 8.0. + - php_version: '8.0' + wp_version: '5.8' + multisite: false + + # WP 5.9 is the earliest version which (sort of) supports PHP 8.1. + - php_version: '8.1' + wp_version: 'latest' + multisite: true + + name: "Integration Test: PHP ${{ matrix.php_version }} | WP ${{ matrix.wp_version }}${{ matrix.multisite == true && ' (+ ms)' || '' }}" + + # Allow builds to fail on as-of-yet unreleased WordPress versions. + continue-on-error: ${{ matrix.wp_version == 'trunk' }} + + services: + mysql: + # Use MySQL 5.6 for PHP 5.6, use MySQL 5.7 for PHP 7.0 < 7.4, otherwise MySQL 8.0. + # Also see: https://core.trac.wordpress.org/ticket/52496 + image: mysql:${{ ( matrix.php_version == '5.6' && '5.6' ) || ( matrix.php_version < '7.4' && '5.7' ) || '8.0' }} + env: + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=10s --health-retries=10 + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + # The prefix-dependencies task makes use of reflection-based PHP code that only works on PHP > 7.2. + - name: Install PHP 7.x for generating the vendor_prefixed directory and dependency injection + uses: shivammathur/setup-php@v2 + with: + php-version: 7.2 + coverage: none + + - name: Install Composer dependencies, generate vendor_prefixed directory and run dependency injection + uses: ramsey/composer-install@v2 + + # Remove packages which are not PHP cross-version compatible and only used for the prefixing. + # - humbug/php-scoper is only needed to actually do the prefixing, so won't be shipped anyway. + # - league/oauth2-client and its dependencies *are* the packages being prefixed. + - name: Delete dependencies which are not cross-version compatible + run: composer remove --dev --no-scripts humbug/php-scoper league/oauth2-client + + - name: Remove vendor directory + run: rm -rf vendor/* + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php_version }} + ini-values: zend.assertions=1, error_reporting=-1, display_errors=On + coverage: none + + # Determine the type of Composer install which is needed. + # 1: WP 5.9 or higher - all PHPUnit versions needed are supported, use the most appropriate one. + # 2. WP < 5.9 with PHP 8.0 or higher - PHPUnit 5 - 7 supported, locked at 5.x, but needs upgrade to 7 for PHP >= 8.0. + # 3. WP < 5.9 with PHP < 8.0 - just use the locked PHPUnit 5 version. + - name: Determine the type of Composer install to use + id: composer_toggle + run: | + if [[ "${{ matrix.wp_version }}" =~ ^(trunk|latest|5\.9|[6789]\.[0-9])$ ]]; then + echo '::set-output name=TYPE::1' + elif [[ "${{ matrix.php_version }}" > "7.4" ]]; then + echo '::set-output name=TYPE::2' + else + echo '::set-output name=TYPE::3' + fi + + - name: Debug info - show type determined + run: echo ${{ steps.composer_toggle.outputs.TYPE }} + + # Install dependencies and handle caching in one go. + # Includes updating the test dependencies to the most appropriate version + # for the PHP/WP version combination on which the tests will be run. + # @link https://github.com/marketplace/actions/install-composer-dependencies + + ### Install type 1. + - name: "Install type 1: remove PHPUnit root requirement" + if: ${{ steps.composer_toggle.outputs.TYPE == '1' }} + run: composer remove --dev phpunit/phpunit --no-update --no-scripts + + - name: "Install type 1: install Composer dependencies - WP 5.9 or higher" + if: ${{ steps.composer_toggle.outputs.TYPE == '1' }} + uses: ramsey/composer-install@v2 + with: + # Force a `composer update` run. + dependency-versions: "highest" + # But make it selective. + composer-options: "yoast/wp-test-utils --with-dependencies --no-scripts" + + ### Install type 2. + - name: "Install type 2: conditionally require a higher PHPUnit version" + if: ${{ steps.composer_toggle.outputs.TYPE == '2' }} + run: composer require --dev phpunit/phpunit:"^7.5" --no-update --ignore-platform-req=php --no-scripts + + - name: "Install type 2: install Composer dependencies - WP < 5.9 with PHP >= 8.0" + if: ${{ steps.composer_toggle.outputs.TYPE == '2' }} + uses: ramsey/composer-install@v2 + with: + # Force a `composer update` run. + dependency-versions: "highest" + # But make it selective. + composer-options: "yoast/wp-test-utils phpunit/phpunit --with-dependencies --no-scripts --ignore-platform-req=php" + + ### Install type 3. + # As PHPUnit is a root requirement and some of the PHPUnit dependencies are locked at versions incompatible + # with all supported PHP versions, the PHPUnit dependency needs to explicitly also be allowed to update + # (within the version constraints as per the `composer.json` file, i.e. PHPUnit 5.7). + - name: "Install type 3: install Composer dependencies - WP < 5.9 with PHP < 8.0" + if: ${{ steps.composer_toggle.outputs.TYPE == '3' }} + uses: ramsey/composer-install@v2 + with: + # Force a `composer update` run. + dependency-versions: "highest" + # But make it selective. + composer-options: "yoast/wp-test-utils phpunit/phpunit --with-dependencies --no-scripts" + + - name: Install WP + shell: bash + run: config/scripts/install-wp-tests.sh wordpress_test root '' 127.0.0.1:3306 ${{ matrix.wp_version }} + + - name: Run unit tests - single site + run: composer integration-test + + - name: Run unit tests - multisite + if: ${{ matrix.multisite == true }} + run: composer integration-test + env: + WP_MULTISITE: 1 diff --git a/.travis.yml b/.travis.yml index 104e997bdfa..6a6d7b2dc42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,6 @@ os: linux dist: xenial language: php -services: - - mysql - branches: only: - master @@ -15,33 +12,13 @@ branches: # Also build tags like 1.1.1 or 1.1 for deployment. - /^\d+\.\d+(\.\d+)?(-\S*)?$/ -stages: - # Don't run the test steps on tag builds, this makes tag deployments a ton faster. - - name: test - if: NOT tag is present - - 🚀 deployment - jobs: fast_finish: true include: - - php: 7.3.24 - env: WP_VERSION=latest WP_MULTISITE=1 COVERAGE=1 - - php: 5.6 - env: WP_VERSION=5.8 WP_MULTISITE=1 PHPUNIT=1 - # Use 'trusty' to test against MySQL 5.6, 'xenial' contains 5.7 by default. - dist: trusty - - php: 7.3 - env: WP_VERSION=trunk PHPUNIT=1 - - php: 7.4 - env: WP_VERSION=latest PHPUNIT=1 - - php: 8.0 - env: WP_VERSION=latest PHPUNIT=1 - - php: "nightly" - stage: 🚀 deployment name: "Deploy to S3" if: branch = deploy # Only build when on the `deploy` branch, this functionality is not used yet and is taking a long time to complete. env: SC_ATTR=wordpress-seo - before_script: skip script: grunt artifact install: - yarn global add grunt-cli @@ -66,7 +43,6 @@ jobs: install: - yarn global add grunt-cli - yarn install - before_script: skip script: - | if [[ ! -z "$TRAVIS_TAG" ]]; then @@ -93,12 +69,6 @@ jobs: repo: $TRAVIS_REPO_SLUG all_branches: true - allow_failures: - # Allow failures for unstable builds. - - php: "nightly" - - php: 7.3 - env: WP_VERSION=trunk PHPUNIT=1 - cache: yarn: true directories: @@ -106,12 +76,11 @@ cache: - node_modules before_install: - - if [[ -z "$CC_TEST_REPORTER_ID" ]]; then COVERAGE="0"; fi - - if [[ "$COVERAGE" != "1" ]]; then phpenv config-rm xdebug.ini || echo 'No xdebug config.'; fi + - phpenv config-rm xdebug.ini || echo 'No xdebug config.' install: - | - if [[ "$PHPUNIT" == "1" || "$COVERAGE" == "1" || "$TRAVIS_BUILD_STAGE_NAME" == "🚀 deployment" ]]; then + if [[ "$TRAVIS_BUILD_STAGE_NAME" == "🚀 deployment" ]]; then # The prefix-dependencies task only works on PHP 7.1 and we need to prefix our dependencies to accurately test them. # So we temporarily switch PHP versions, do a full install and then remove the package. # Then switch back to the PHP version we want to test and delete the vendor directory. @@ -126,110 +95,14 @@ install: rm -rf vendor/* fi - | - if [[ "$COVERAGE" == "1" ]]; then - # Install phpcov so we can combine the coverage results of unit and integration tests. - travis_retry composer require phpunit/phpcov ^3.1 --no-interaction - fi - - | - if [[ ${TRAVIS_PHP_VERSION:0:1} == "8" || $TRAVIS_PHP_VERSION == "nightly" ]]; then - travis_retry composer install --no-interaction --ignore-platform-reqs --no-scripts --no-suggest - elif [[ "$PHPUNIT" == "1" || "$COVERAGE" == "1" ]]; then - # Run composer update as we have dev dependencies locked at PHP ^7.0 versions. - travis_retry composer update --no-interaction --no-scripts - travis_retry composer install --no-interaction --no-scripts - travis_retry composer du --no-scripts - elif [[ "$TRAVIS_BUILD_STAGE_NAME" == "🚀 deployment" ]]; then + if [[ "$TRAVIS_BUILD_STAGE_NAME" == "🚀 deployment" ]]; then travis_retry composer update --no-interaction travis_retry composer install --no-dev --no-interaction composer du fi -before_script: - # Careful: The HTTPS version of the following URL is different, therefore we need to use HTTP. - - | - if [[ "$PHPUNIT" == "1" || "$COVERAGE" == "1" ]]; then - if [[ "$WP_VERSION" == "latest" ]]; then - curl -s http://api.wordpress.org/core/version-check/1.7/ > /tmp/wp-latest.json - WP_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') - fi - PLUGIN_SLUG=$(basename $(pwd)) - export WP_DEVELOP_DIR=/tmp/wordpress/ - git clone --depth=1 --branch="$WP_VERSION" git://develop.git.wordpress.org/ /tmp/wordpress - cd .. - cp -r "$PLUGIN_SLUG" "/tmp/wordpress/src/wp-content/plugins/$PLUGIN_SLUG" - cd /tmp/wordpress/ - cp wp-tests-config-sample.php wp-tests-config.php - sed -i "s/youremptytestdbnamehere/wordpress_tests/" wp-tests-config.php - sed -i "s/yourusernamehere/travis/" wp-tests-config.php - sed -i "s/yourpasswordhere//" wp-tests-config.php - mysql -e "CREATE DATABASE wordpress_tests;" -uroot - cd "/tmp/wordpress/src/wp-content/plugins/$PLUGIN_SLUG" - mkdir src/generated/assets - echo " [ 'dependencies' => [], 'version' => 'test' ], 'installation-success.js' => [ 'dependencies' => [], 'version' => 'test' ], 'workouts.js' => [ 'dependencies' => [], 'version' => 'test' ] ];" >> src/generated/assets/plugin.php - echo "> src/generated/assets/externals.php - echo "> src/generated/assets/languages.php - fi - - phpenv rehash - - | - if [[ "$COVERAGE" == "1" ]]; then - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter - ./cc-test-reporter before-build - mkdir -p /tmp/coverage - fi - - export -f travis_fold - - export -f travis_time_start - - export -f travis_time_finish - - mysql --version - - phpenv versions - - php --version - - php -m - - curl --version - - git --version - - svn --version - - locale -a - script: - # PHP Unit - - | - if [[ "$PHPUNIT" == "1" && ${TRAVIS_PHP_VERSION:0:1} != "8" && $TRAVIS_PHP_VERSION != "nightly" ]]; then - # PHP < 8 - travis_fold start "PHP.integration-tests" && travis_time_start - vendor/bin/phpunit -c phpunit-integration.xml.dist - travis_time_finish && travis_fold end "PHP.integration-tests" - elif [[ "$PHPUNIT" == "1" ]] && [[ ${TRAVIS_PHP_VERSION:0:1} == "8" || $TRAVIS_PHP_VERSION == "nightly" ]] && [[ ${WP_VERSION:0:3} == "5.9" || ${WP_VERSION:0:1} == "6" || $WP_VERSION == "trunk" ]]; then - # PHP >= 8 with WP >= 5.9 - travis_fold start "PHP.integration-tests" && travis_time_start - travis_retry composer remove --dev phpunit/phpunit --no-update --no-interaction && - travis_retry composer update yoast/wp-test-utils --no-interaction --with-dependencies --ignore-platform-req=php && - vendor/bin/phpunit -c phpunit-integration.xml.dist - travis_time_finish && travis_fold end "PHP.integration-tests" - elif [[ "$PHPUNIT" == "1" ]] && [[ ${TRAVIS_PHP_VERSION:0:1} == "8" || $TRAVIS_PHP_VERSION == "nightly" ]]; then - # PHP >= 8 with WP < 5.9 - travis_fold start "PHP.integration-tests" && travis_time_start - travis_retry composer require --dev phpunit/phpunit:"^7.5" --update-with-dependencies --ignore-platform-reqs --no-interaction && - vendor/bin/phpunit -c phpunit-integration.xml.dist - travis_time_finish && travis_fold end "PHP.integration-tests" - fi - - | - if [[ "$COVERAGE" == "1" ]]; then - travis_fold start "PHP.coverage" && travis_time_start - vendor/bin/phpunit -c phpunit-integration.xml.dist --coverage-php /tmp/coverage/integration-tests.cov - travis_time_finish && travis_fold end "PHP.coverage" - fi - - | - if [[ "$COVERAGE" == "1" ]]; then - travis_fold start "PHP.coverage" && travis_time_start - vendor/bin/phpunit --coverage-php /tmp/coverage/tests.cov - travis_time_finish && travis_fold end "PHP.coverage" - fi - -after_script: - - | - if [[ "$COVERAGE" == "1" ]]; then - ./vendor/bin/phpcov merge /tmp/coverage --clover build/logs/clover.xml - fi - - if [[ "$COVERAGE" == "1" ]]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT; fi + - git status notifications: slack: diff --git a/README.md b/README.md index 42f5518ea88..bf777e76b6c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![LintJS](https://github.com/Yoast/wordpress-seo/actions/workflows/jslint.yml/badge.svg)](https://github.com/Yoast/wordpress-seo/actions/workflows/jslint.yml) [![TestJS](https://github.com/Yoast/wordpress-seo/actions/workflows/jstest.yml/badge.svg)](https://github.com/Yoast/wordpress-seo/actions/workflows/jstest.yml) [![Unit Tests](https://github.com/Yoast/wordpress-seo/actions/workflows/unittest.yml/badge.svg)](https://github.com/Yoast/wordpress-seo/actions/workflows/unittest.yml) -[![Build Status](https://api.travis-ci.com/Yoast/wordpress-seo.svg?branch=master)](https://travis-ci.com/Yoast/wordpress-seo) +[![Integration Tests](https://github.com/Yoast/wordpress-seo/actions/workflows/integrationtest.yml/badge.svg)](https://github.com/Yoast/wordpress-seo/actions/workflows/integrationtest.yml) [![Stable Version](https://poser.pugx.org/yoast/wordpress-seo/v/stable.svg)](https://packagist.org/packages/yoast/wordpress-seo) [![License](https://poser.pugx.org/yoast/wordpress-seo/license.svg)](https://packagist.org/packages/yoast/wordpress-seo) diff --git a/config/scripts/install-wp-tests.sh b/config/scripts/install-wp-tests.sh new file mode 100755 index 00000000000..44ec8df9cb1 --- /dev/null +++ b/config/scripts/install-wp-tests.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash + +######################################################################## +# Script to download and install WordPress for use in automated testing. +# +# Source: https://github.com/wp-cli/scaffold-command/blob/master/templates/install-wp-tests.sh +# Last updated based on commit https://github.com/wp-cli/scaffold-command/commit/acf73159e1773a052d43a13cb63b5040e1f43c8f +# dated March 11 2021. +######################################################################## + +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} + +TMPDIR=${TMPDIR-/tmp} +TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//") +WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib} +WP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/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]+\-(beta|RC)[0-9]+$ ]]; then + WP_BRANCH=${WP_VERSION%\-*} + WP_TESTS_TAG="branches/$WP_BRANCH" + +elif [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then + WP_TESTS_TAG="branches/$WP_VERSION" +elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + WP_TESTS_TAG="tags/${WP_VERSION%??}" + else + WP_TESTS_TAG="tags/$WP_VERSION" + fi +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 $TMPDIR/wordpress-trunk + rm -rf $TMPDIR/wordpress-trunk/* + svn export --quiet https://core.svn.wordpress.org/trunk $TMPDIR/wordpress-trunk/wordpress + mv $TMPDIR/wordpress-trunk/wordpress/* $WP_CORE_DIR + else + if [ $WP_VERSION == 'latest' ]; then + local ARCHIVE_NAME='latest' + elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+ ]]; then + # https serves multiple offers, whereas http serves single. + download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + LATEST_VERSION=${WP_VERSION%??} + else + # otherwise, scan the releases and get the most up to date minor version of the major release + local VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\./\\\\./g'` + LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1) + fi + if [[ -z "$LATEST_VERSION" ]]; then + local ARCHIVE_NAME="wordpress-$WP_VERSION" + else + local ARCHIVE_NAME="wordpress-$LATEST_VERSION" + fi + else + local ARCHIVE_NAME="wordpress-$WP_VERSION" + fi + download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz + tar --strip-components=1 -zxmf $TMPDIR/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 + rm -rf $WP_TESTS_DIR/{includes,data} + svn export --quiet --ignore-externals https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + svn export --quiet --ignore-externals 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:__DIR__ . '/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 + +} + +recreate_db() { + shopt -s nocasematch + if [[ $1 =~ ^(y|yes)$ ]] + then + mysqladmin drop $DB_NAME -f --user="$DB_USER" --password="$DB_PASS"$EXTRA + create_db + echo "Recreated the database ($DB_NAME)." + else + echo "Leaving the existing database ($DB_NAME) in place." + fi + shopt -u nocasematch +} + +create_db() { + mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA +} + +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 + if [ $(mysql --user="$DB_USER" --password="$DB_PASS"$EXTRA --execute='show databases;' | grep ^$DB_NAME$) ] + then + echo "Reinstalling will delete the existing test database ($DB_NAME)" + read -p 'Are you sure you want to proceed? [y/N]: ' DELETE_EXISTING_DB + recreate_db $DELETE_EXISTING_DB + else + create_db + fi +} + +install_wp +install_test_suite +install_db diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php index b8499778d50..efca4acd347 100755 --- a/tests/integration/bootstrap.php +++ b/tests/integration/bootstrap.php @@ -9,6 +9,60 @@ require_once dirname( dirname( __DIR__ ) ) . '/vendor/yoast/wp-test-utils/src/WPIntegration/bootstrap-functions.php'; + +/* *****[ Ensure a couple of required files are present ]***** */ + +/** + * Creates asset files. + * + * @throws RuntimeException If the directory or file creation failed. + */ +function create_required_asset_files() { + $target_dir = dirname( dirname( __DIR__ ) ) . '/src/generated/assets'; + + // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged -- Silencing warnings when function fails. + if ( @is_dir( $target_dir ) === false ) { + if ( @mkdir( $target_dir, 0777, true ) === false ) { + throw new RuntimeException( sprintf( 'Failed to create the %s directory.', $target_dir ) ); + } + } // phpcs:enable WordPress + + $required_files = [ + 'plugin.php' => " [ + 'dependencies' => [], + 'version' => 'test', + ], + 'installation-success.js' => [ + 'dependencies' => [], + 'version' => 'test', + ], + 'workouts.js' => [ + 'dependencies' => [], + 'version' => 'test', + ] +]; +", + 'externals.php' => ' ' $contents ) { + $target_file = $target_dir . '/' . $file_name; + if ( file_exists( $target_file ) === false ) { + if ( file_put_contents( $target_file, $contents ) === false ) { + throw new RuntimeException( sprintf( 'Failed to write to target location: %s', $target_file ) ); + } + } + } +} + +create_required_asset_files(); + + +/* *****[ Wire in the integration ]***** */ + $_tests_dir = WPIntegration\get_path_to_wp_test_dir(); // Give access to tests_add_filter() function.