Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/actions/smoke-check/smoke-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ code="${RUNNER_TEMP}/http-code.txt"
http_code=''

version="$(wp core version)"
# Both are translated on a localized site.
first_post_title="$(wp eval "echo get_the_title( 1 );")"
no_update_required="$(wp eval "echo __( 'No Update Required' );")"
# An empty marker would match any page.
: "${first_post_title:?}" "${no_update_required:?}"

# Nothing undoes these, so the site is only good for this check afterwards.
wp option update home "${site_url}"
Expand Down Expand Up @@ -83,15 +88,15 @@ check() {
}

# A fatal mid-page still returns 200, so every check also asks for the closing tag.
check '/' "content=\"WordPress ${version}\"" 'Hello world!' '</html>'
check '/' "content=\"WordPress ${version}\"" "${first_post_title}" '</html>'

fetch '/?rest_route=/' --fail-with-body || fail "/?rest_route=/ returned HTTP ${http_code}"
jq -e --arg url "${site_url}" '.url == $url and ( .namespaces | index( "wp/v2" ) )' "${response}" > /dev/null \
|| fail 'the REST index was not the expected JSON'
echo 'ok /?rest_route=/'

# It prints this for an empty database too, which the checks above rule out.
check '/wp-admin/upgrade.php' 'No Update Required' '</html>'
check '/wp-admin/upgrade.php' "${no_update_required}" '</html>'

fetch '/?p=99999999' || true
[ "${http_code}" = '404' ] || fail "a missing post returned ${http_code}, expected 404"
Expand Down
191 changes: 190 additions & 1 deletion .github/workflows/install-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,202 @@ jobs:
admin-user: ${{ env.WP_ADMIN_USER }}
admin-password: ${{ env.WP_ADMIN_PASSWORD }}

# Builds the list of locales that are expected to have a localized package for the version being tested.
#
# Localized packages are built after the en_US package, usually 1-3 hours later and sometimes days later. Right after
# a release, dispatch this workflow only after the localized packages are published, or every locale job will fail.
#
# "latest" and "nightly" are tested as the latest stable release, because there are no localized nightly builds.
# This lets the weekly scheduled run check the localized packages of the current release.
#
# A locale is expected when it has a localized package for an earlier version on the same branch: the first
# release of the branch (X.Y) or the previous minor release. Locales below the translation thresholds have no
# localized package, so they are not expected. A version with no earlier release on its branch (X.Y) has no baseline,
# and neither has a version that is not a stable release. No locale is tested for those.
#
# Also returns the version of PHP and MySQL to test with, and the version each locale starts from in upgrade tests.
#
# Keep this job the same in install-testing.yml and upgrade-testing.yml.
build-locale-matrix:
name: Build Locale Test Matrix
runs-on: ubuntu-24.04
permissions:
contents: read
if: ${{ github.repository == 'WordPress/wordpress-develop' }}
timeout-minutes: 5
outputs:
version: ${{ steps.locales.outputs.version }}
locales: ${{ steps.locales.outputs.locales }}
start-versions: ${{ steps.locales.outputs.start-versions }}
php-version: ${{ steps.locales.outputs.php-version }}
mysql-version: ${{ steps.locales.outputs.mysql-version }}

steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }}
persist-credentials: false
sparse-checkout: |
.version-support-php.json
.version-support-mysql.json
sparse-checkout-cone-mode: false

- name: Find the locales that are expected to have a localized package
id: locales
env:
WP_VERSION: ${{ inputs.wp-version || 'nightly' }}
run: |
set -o pipefail

if [[ "$WP_VERSION" == 'latest' || "$WP_VERSION" == 'nightly' ]]; then
WP_VERSION="$( curl -fsS --retry 3 'https://api.wordpress.org/core/version-check/1.7/' | jq -r '.offers[0].version' )"
fi

branch="$( cut -d . -f 1-2 <<< "$WP_VERSION" )"
stable="$( curl -fsS --retry 3 'https://api.wordpress.org/core/stable-check/1.0/' | jq -r 'keys[]' | sort -V )"
previous="$( grep -B 1 -x -F "$WP_VERSION" <<< "$stable" | head -n 1 || true )"

if [[ "$previous" == "$WP_VERSION" || "$( cut -d . -f 1-2 <<< "$previous" )" != "$branch" ]]; then
echo "::notice::No locales are tested, because ${WP_VERSION} is not a stable release with an earlier release on its branch."
echo "locales=[]" >> "$GITHUB_OUTPUT"
echo "start-versions={}" >> "$GITHUB_OUTPUT"
exit 0
fi

# Any answer but 200 or 404 fails the step, so an outage cannot drop locales from the test.
has_package() {
local code
code="$( curl -sI --retry 3 -o /dev/null -w '%{http_code}' "https://downloads.wordpress.org/release/${1}/wordpress-${2}.zip" || true )"
case "$code" in
200) return 0 ;;
404) return 1 ;;
*) echo "::error::Checking the ${2} package for ${1} returned HTTP ${code}." >&2; exit 1 ;;
esac
}

start_versions="$(
curl -fsS --retry 3 "https://api.wordpress.org/translations/core/1.0/?version=${WP_VERSION}" \
| jq -r '.translations[].language' \
| while read -r locale; do
if has_package "$locale" "$branch"; then
echo "$locale $branch"
elif has_package "$locale" "$previous"; then
echo "$locale $previous"
fi
done \
| jq -Rsc 'split("\n") | map(select(length > 0) | split(" ") | { (.[0]): .[1] }) | add // {}'
)"

support_key="${branch//./-}"
php_version="$( jq -r --arg v "$support_key" '.[$v][-1] // empty' .version-support-php.json )"
mysql_version="$( jq -r --arg v "$support_key" '.[$v] // [] | first(("8.4", "8.0", "5.7") as $x | select(index($x)) | $x) // empty' .version-support-mysql.json )"

if [[ -z "$php_version" || -z "$mysql_version" ]]; then
echo "::error::No supported PHP or MySQL version is listed for WordPress ${branch}."
exit 1
fi

{
echo "version=${WP_VERSION}"
echo "locales=$( jq -c 'keys' <<< "$start_versions" )"
echo "start-versions=${start_versions}"
echo "php-version=${php_version}"
echo "mysql-version=${mysql_version}"
} >> "$GITHUB_OUTPUT"

# Tests installing the localized package of each locale through WP-CLI.
#
# Performs the following steps:
# - Sets up PHP.
# - Downloads the localized package of the version being tested.
# - Confirms the WordPress version and the locale of the package.
# - Verifies the files against the localized package checksums.
# - Creates a `wp-config.php` file.
# - Installs WordPress.
# - Serves the installed site and confirms it renders.
install-tests-locale:
name: WP ${{ needs.build-locale-matrix.outputs.version }} / ${{ matrix.locale }}
permissions:
contents: read
runs-on: ubuntu-24.04
if: ${{ github.repository == 'WordPress/wordpress-develop' && needs.build-locale-matrix.outputs.locales != '[]' }}
timeout-minutes: 10
needs: [ build-locale-matrix ]

env:
WP_ADMIN_USER: admin
WP_ADMIN_PASSWORD: password
WP_VERSION: ${{ needs.build-locale-matrix.outputs.version }}
WP_LOCALE: ${{ matrix.locale }}
strategy:
fail-fast: false
matrix:
locale: ${{ fromJSON( needs.build-locale-matrix.outputs.locales ) }}
php: [ '${{ needs.build-locale-matrix.outputs.php-version }}' ]
db-version: [ '${{ needs.build-locale-matrix.outputs.mysql-version }}' ]

services:
database:
image: mysql:${{ matrix.db-version }}
ports:
- 3306
# Ping over TCP, to wait for the TCP server rather than the Unix socket.
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 --protocol=tcp"
--health-interval="30s"
--health-timeout="10s"
--health-retries="5"
-e MYSQL_ROOT_PASSWORD="root"
-e MYSQL_DATABASE="test_db"
--entrypoint sh mysql:${{ matrix.db-version }}
-c "exec docker-entrypoint.sh mysqld${{ contains( fromJSON('["5.4", "5.5", "5.6", "7.0", "7.1", "7.2", "7.3"]'), matrix.php ) && ( matrix.db-version == '8.4' && ' --mysql-native-password=ON --authentication-policy=mysql_native_password' || ' --default-authentication-plugin=mysql_native_password' ) || '' }}"

steps:
- name: Set up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
with:
php-version: '${{ matrix.php }}'
coverage: none
tools: wp-cli

- name: Download WordPress
run: wp core download --version="${WP_VERSION}" --locale="${WP_LOCALE}"

- name: Check the version and locale of the package
run: |
actual="$( wp core version --extra | sed -n -e 's/^WordPress version:[[:space:]]*//p' -e 's/^Package language:[[:space:]]*//p' | paste -s -d ' ' - )"
if [[ "$actual" != "${WP_VERSION} ${WP_LOCALE}" ]]; then
echo "::error::Expected WordPress ${WP_VERSION} ${WP_LOCALE}, found ${actual}."
exit 1
fi

- name: Verify the checksums of the localized package
run: wp core verify-checksums --locale="${WP_LOCALE}"

- name: Create wp-config.php file
run: wp config create --dbname=test_db --dbuser=root --dbpass=root --dbhost="127.0.0.1:${DB_PORT}"
env:
DB_PORT: ${{ job.services.database.ports['3306'] }}

- name: Install WordPress
run: |
wp core install --url=http://localhost/ --title="Install Test" --admin_user="${WP_ADMIN_USER}" \
--admin_password="${WP_ADMIN_PASSWORD}" --admin_email=me@example.org --skip-email --locale="${WP_LOCALE}"

- name: Post-install smoke check
uses: WordPress/wordpress-develop/.github/actions/smoke-check@trunk # zizmor: ignore[unpinned-uses]
with:
admin-user: ${{ env.WP_ADMIN_USER }}
admin-password: ${{ env.WP_ADMIN_PASSWORD }}

slack-notifications:
name: Slack Notifications
uses: ./.github/workflows/slack-notifications.yml
permissions:
actions: read
contents: read
needs: [ install-tests-mysql ]
needs: [ install-tests-mysql, build-locale-matrix, install-tests-locale ]
if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
with:
calling_status: ${{ contains( needs.*.result, 'cancelled' ) && 'cancelled' || contains( needs.*.result, 'failure' ) && 'failure' || 'success' }}
Expand Down
Loading
Loading