From 1c0f0881ffc74edbe1b5b329dfc846aa4d9c785b Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:35:50 -0400 Subject: [PATCH 01/13] Initial attempt at context aware upgrade testing. --- .github/workflows/upgrade-testing.yml | 195 ++++++++++++++++++++++++-- 1 file changed, 187 insertions(+), 8 deletions(-) diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index 0370c8770bd58..c1d0022181ad2 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -9,20 +9,24 @@ on: - trunk # Always test the workflow after it's updated. paths: + - '.version-support-*.json' - '.github/workflows/upgrade-testing.yml' - '.github/workflows/reusable-upgrade-testing.yml' + - '.github/workflows/reusable-support-json-reader-v1.yml' pull_request: # This workflow is only meant to run from trunk. Pull requests changing this file with different BASE branches should be ignored. branches: - trunk # Always test the workflow when changes are suggested. paths: + - '.version-support-*.json' - '.github/workflows/upgrade-testing.yml' - '.github/workflows/reusable-upgrade-testing.yml' + - '.github/workflows/reusable-support-json-reader-v1.yml' workflow_dispatch: inputs: new-version: - description: 'The version to test installing. Accepts major and minor versions, "latest", or "nightly". Major releases must not end with ".0".' + description: 'The version to test upgrading to. Accepts major and minor versions, "latest", or "nightly". Major releases must not end with ".0".' type: string default: 'latest' @@ -37,6 +41,10 @@ concurrency: # Any needed permissions should be configured at the job level. permissions: {} +env: + CURRENTLY_SUPPORTED_BRANCH: '6.9' + OLDEST_SECURITY_BRANCH: '4.7' + # Because the number of jobs spawned can quickly balloon out of control, the following methodology is applied when # building out the matrix below: # @@ -57,11 +65,111 @@ permissions: {} # - 5.6.x Docker containers are available and work, but 5.6 only accounts for ~2.3% of installs as of 12/6/2024.defaults: # - 5.7.x accounts for ~20% of installs, so this is used below instead. jobs: + # Determines whether an older branch is being tested. + # + # When an older version is specified, a reduced matrix tailored to that branch is run. + determine-workflow-type: + name: Determine workflow type + runs-on: 'ubuntu-24.04' + timeout-minutes: 5 + if: ${{ github.repository == 'WordPress/wordpress-develop' }} + outputs: + testing-old-branch: ${{ steps.old-branch-check.outputs.testing-old-branch }} + steps: + - name: Determine if an older branch is being tested + id: old-branch-check + env: + NEW_VERSION: ${{ inputs.new-version }} + CURRENTLY_SUPPORTED_BRANCH: ${{ env.CURRENTLY_SUPPORTED_BRANCH }} + run: | + case "$NEW_VERSION" in + "" | "latest" | "nightly" | "$CURRENTLY_SUPPORTED_BRANCH" | "$CURRENTLY_SUPPORTED_BRANCH".*) + echo "testing-old-branch=false" >> "$GITHUB_OUTPUT" + ;; + *) + echo "testing-old-branch=true" >> "$GITHUB_OUTPUT" + ;; + esac + + # Determines the PHP and database versions to test based on the WordPress version when testing old branches. + build-test-matrix: + name: Build Test Matrix + uses: ./.github/workflows/reusable-support-json-reader-v1.yml + permissions: + contents: read + secrets: inherit + needs: [ determine-workflow-type ] + if: ${{ needs.determine-workflow-type.outputs.testing-old-branch == 'true' }} + with: + wp-version: ${{ inputs.new-version }} + + # Determines the list of WordPress versions to upgrade from when testing an older branch. + # + # Generates a JSON array of all branches from OLDEST_SECURITY_BRANCH up to, but not + # including, the target branch. For example, when the target is 5.0, this produces + # ["4.7", "4.8", "4.9"]. WordPress branches are versioned as X.Y, where Y increments + # from 0 to 9 before X increments and Y resets to 0. + # + # Only runs when testing an older branch. + determine-from-versions: + name: Determine FROM WordPress versions + runs-on: 'ubuntu-24.04' + timeout-minutes: 5 + needs: [ determine-workflow-type, build-test-matrix ] + if: ${{ github.repository == 'WordPress/wordpress-develop' }} + outputs: + from-versions: ${{ steps.from-versions.outputs.from-versions }} + + steps: + - name: Determine the FROM WordPress versions + id: from-versions + env: + OLDEST_SECURITY_BRANCH: ${{ env.OLDEST_SECURITY_BRANCH }} + MAJOR_WP_VERSION: ${{ needs.build-test-matrix.outputs.major-wp-version }} + run: | + OLDEST_MAJOR=$(echo "$OLDEST_SECURITY_BRANCH" | cut -d'.' -f1) + OLDEST_MINOR=$(echo "$OLDEST_SECURITY_BRANCH" | cut -d'.' -f2) + + # Converts the target branch key (e.g. "5-0") to X.Y format. + TARGET=$(echo "$MAJOR_WP_VERSION" | tr '-' '.') + TARGET_MAJOR=$(echo "$TARGET" | cut -d'.' -f1) + TARGET_MINOR=$(echo "$TARGET" | cut -d'.' -f2) + + # Build a JSON array of all branches from OLDEST_SECURITY_BRANCH up to, but not + # including, the target branch. Y increments 0–9, then X increments and Y resets to 0. + VERSIONS="" + CURRENT_MAJOR=$OLDEST_MAJOR + CURRENT_MINOR=$OLDEST_MINOR + + while true; do + if [ "$CURRENT_MAJOR" -gt "$TARGET_MAJOR" ] || \ + { [ "$CURRENT_MAJOR" -eq "$TARGET_MAJOR" ] && [ "$CURRENT_MINOR" -ge "$TARGET_MINOR" ]; }; then + break + fi + + if [ -n "$VERSIONS" ]; then + VERSIONS="${VERSIONS}," + fi + VERSIONS="${VERSIONS}\"${CURRENT_MAJOR}.${CURRENT_MINOR}\"" + + if [ "$CURRENT_MINOR" -eq 9 ]; then + CURRENT_MAJOR=$((CURRENT_MAJOR + 1)) + CURRENT_MINOR=0 + else + CURRENT_MINOR=$((CURRENT_MINOR + 1)) + fi + done + + echo "from-versions=[${VERSIONS}]" >> "$GITHUB_OUTPUT" + # Tests the full list of PHP/MySQL combinations for the two most recent versions of WordPress. + # + # Only runs when testing the currently supported branch or latest/nightly. upgrade-tests-recent-releases: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + needs: [ determine-workflow-type ] + if: ${{ needs.determine-workflow-type.outputs.testing-old-branch != 'true' }} permissions: contents: read strategy: @@ -83,10 +191,13 @@ jobs: multisite: ${{ matrix.multisite }} # Tests 6.x releases where the WordPress database version changed on the oldest and newest supported versions of PHP 7 & 8. + # + # Only runs when testing the currently supported branch or latest/nightly. upgrade-tests-wp-6x-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + needs: [ determine-workflow-type ] + if: ${{ needs.determine-workflow-type.outputs.testing-old-branch != 'true' }} permissions: contents: read strategy: @@ -108,10 +219,13 @@ jobs: multisite: ${{ matrix.multisite }} # Tests 5.x releases where the WordPress database version changed on the only supported version of PHP 7. + # + # Only runs when testing the currently supported branch or latest/nightly. upgrade-tests-wp-5x-php-7x-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + needs: [ determine-workflow-type ] + if: ${{ needs.determine-workflow-type.outputs.testing-old-branch != 'true' }} permissions: contents: read strategy: @@ -137,10 +251,13 @@ jobs: # WordPress 5.0-5.2 are excluded from PHP 8+ testing because of the following fatal errors: # - Use of __autoload(). # - array/string offset with curly braces. + # + # Only runs when testing the currently supported branch or latest/nightly. upgrade-tests-wp-5x-php-8x-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + needs: [ determine-workflow-type ] + if: ${{ needs.determine-workflow-type.outputs.testing-old-branch != 'true' }} permissions: contents: read strategy: @@ -167,10 +284,13 @@ jobs: # WordPress 4.7 is excluded from PHP 8+ testing because of the following fatal errors: # - Use of __autoload(). # - array/string offset with curly braces. + # + # Only runs when testing the currently supported branch or latest/nightly. upgrade-tests-oldest-wp-mysql: name: ${{ matrix.wp }} to ${{ inputs.new-version && inputs.new-version || 'latest' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} + needs: [ determine-workflow-type ] + if: ${{ needs.determine-workflow-type.outputs.testing-old-branch != 'true' }} permissions: contents: read strategy: @@ -191,13 +311,72 @@ jobs: new-version: ${{ inputs.new-version && inputs.new-version || 'latest' }} multisite: ${{ matrix.multisite }} + # Tests an older WordPress branch against all PHP and database versions it supports, as + # documented in the version support JSON files. + # + # Uses the X.Y initial release of the branch as the FROM version to test the within-branch + # upgrade path. PHP and database versions unsupported by Docker are excluded, as are MySQL + # innovation releases other than the most recent. + # + # Only runs when testing an older branch (i.e. new-version is not empty, 'latest', 'nightly', + # or a version of the currently supported branch). + upgrade-tests-older-branch-mysql: + name: WP ${{ matrix.wp }} to ${{ inputs.new-version }} / PHP ${{ matrix.php }} / MySQL ${{ matrix.db-version }}${{ matrix.multisite && ' multisite' || '' }} + uses: ./.github/workflows/reusable-upgrade-testing.yml + if: ${{ github.repository == 'WordPress/wordpress-develop' }} + needs: [ build-test-matrix, determine-from-versions ] + permissions: + contents: read + strategy: + fail-fast: false + matrix: + os: [ 'ubuntu-24.04' ] + php: ${{ fromJSON( needs.build-test-matrix.outputs.php-versions ) }} + db-type: [ 'mysql' ] + db-version: ${{ fromJSON( needs.build-test-matrix.outputs.mysql-versions ) }} + wp: ${{ fromJSON( needs.determine-from-versions.outputs.from-versions ) }} + multisite: [ false, true ] + exclude: + # There are no local WordPress Docker environment containers for PHP <= 5.3. + - php: '5.2' + - php: '5.3' + # MySQL containers <= 5.5 do not exist or fail to start properly. + - db-version: '5.0' + - db-version: '5.1' + - db-version: '5.5' + # The PHP <= 7.3/MySQL 8.4 jobs currently fail due to mysql_native_password being disabled by default. See https://core.trac.wordpress.org/ticket/61218. + - php: '7.2' + db-version: '8.4' + - php: '7.3' + db-version: '8.4' + # Only test the latest innovation release. + - db-version: '9.0' + - db-version: '9.1' + - db-version: '9.2' + - db-version: '9.3' + - db-version: '9.4' + - db-version: '9.5' + # MySQL 9.0+ will not work on PHP 7.2 & 7.3. See https://core.trac.wordpress.org/ticket/61218. + - php: '7.2' + db-version: '9.6' + - php: '7.3' + db-version: '9.6' + with: + os: ${{ matrix.os }} + php: ${{ matrix.php }} + db-type: ${{ matrix.db-type }} + db-version: ${{ matrix.db-version }} + wp: ${{ matrix.wp }} + new-version: ${{ inputs.new-version }} + multisite: ${{ matrix.multisite }} + slack-notifications: name: Slack Notifications uses: ./.github/workflows/slack-notifications.yml permissions: actions: read contents: read - needs: [ upgrade-tests-recent-releases, upgrade-tests-wp-6x-mysql, upgrade-tests-wp-5x-php-7x-mysql, upgrade-tests-wp-5x-php-8x-mysql, upgrade-tests-oldest-wp-mysql ] + needs: [ upgrade-tests-recent-releases, upgrade-tests-wp-6x-mysql, upgrade-tests-wp-5x-php-7x-mysql, upgrade-tests-wp-5x-php-8x-mysql, upgrade-tests-oldest-wp-mysql, upgrade-tests-older-branch-mysql ] 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' }} @@ -209,7 +388,7 @@ jobs: failed-workflow: name: Failed workflow tasks - runs-on: ubuntu-24.04 + runs-on: 'ubuntu-24.04' permissions: actions: write needs: [ slack-notifications ] From 148a95d5c985e58b306ff10b997610d449e2d93a Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:37:51 -0400 Subject: [PATCH 02/13] Remove repo-specific restrictions. --- .github/workflows/upgrade-testing.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index c1d0022181ad2..87c7981a2898d 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -72,7 +72,6 @@ jobs: name: Determine workflow type runs-on: 'ubuntu-24.04' timeout-minutes: 5 - if: ${{ github.repository == 'WordPress/wordpress-develop' }} outputs: testing-old-branch: ${{ steps.old-branch-check.outputs.testing-old-branch }} steps: @@ -116,7 +115,6 @@ jobs: runs-on: 'ubuntu-24.04' timeout-minutes: 5 needs: [ determine-workflow-type, build-test-matrix ] - if: ${{ github.repository == 'WordPress/wordpress-develop' }} outputs: from-versions: ${{ steps.from-versions.outputs.from-versions }} @@ -323,7 +321,6 @@ jobs: upgrade-tests-older-branch-mysql: name: WP ${{ matrix.wp }} to ${{ inputs.new-version }} / PHP ${{ matrix.php }} / MySQL ${{ matrix.db-version }}${{ matrix.multisite && ' multisite' || '' }} uses: ./.github/workflows/reusable-upgrade-testing.yml - if: ${{ github.repository == 'WordPress/wordpress-develop' }} needs: [ build-test-matrix, determine-from-versions ] permissions: contents: read From a01b6d613a58ebfe03d399e12077d177d53d1ebc Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:45:35 -0400 Subject: [PATCH 03/13] Configure WP CLI correctly for PHP 5.4 & 5.5. --- .github/workflows/reusable-upgrade-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index f3659fab3ad26..10d0f4b4b444b 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -82,7 +82,7 @@ jobs: with: php-version: '${{ inputs.php }}' coverage: none - tools: wp-cli + tools: ${{ contains( fromJSON('["5.4", "5.5"]'), inputs.php ) && 'wp-cli:2.4.0' || 'wp-cli' }} - name: Download WordPress ${{ inputs.wp }} run: wp core download --version="${WP_VERSION}" From c78fb49b01c6c2a5f7a55f26ad058955d1c9165f Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:50:54 -0400 Subject: [PATCH 04/13] Exclude PHP 8.x for WP 4.7. --- .github/workflows/upgrade-testing.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index 87c7981a2898d..06ff0c02d2281 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -358,6 +358,8 @@ jobs: db-version: '9.6' - php: '7.3' db-version: '9.6' + - php: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] + wp: '4.7' with: os: ${{ matrix.os }} php: ${{ matrix.php }} From ceaf7982da8df6028e4f1e9d3fef794f06af80c5 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:57:09 -0400 Subject: [PATCH 05/13] Limit matrix to test. --- .github/workflows/upgrade-testing.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index 06ff0c02d2281..6f6416c83000f 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -360,6 +360,7 @@ jobs: db-version: '9.6' - php: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] wp: '4.7' + - php: [ '7.4', '8.2', '8.3', '8.4', '8.5' ] with: os: ${{ matrix.os }} php: ${{ matrix.php }} From 04e4823a8ce393f535203164540bc9134f8204c8 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:03:44 -0400 Subject: [PATCH 06/13] Test exclusions using an array. --- .github/workflows/test-exclude-array.yml | 34 ++++++++++++++++++++++++ .github/workflows/upgrade-testing.yml | 3 --- 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/test-exclude-array.yml diff --git a/.github/workflows/test-exclude-array.yml b/.github/workflows/test-exclude-array.yml new file mode 100644 index 0000000000000..b53f3a549b983 --- /dev/null +++ b/.github/workflows/test-exclude-array.yml @@ -0,0 +1,34 @@ +name: test-exclude-array.yml +on: + +jobs: + # Tests the full list of PHP/MySQL combinations for the two most recent versions of WordPress. + # + # Only runs when testing the currently supported branch or latest/nightly. + upgrade-tests-recent-releases: + name: ${{ matrix.wp }} to latest + uses: ./.github/workflows/reusable-upgrade-testing.yml + permissions: + contents: read + strategy: + fail-fast: false + matrix: + os: [ 'ubuntu-24.04' ] + php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] + db-type: [ 'mysql' ] + db-version: [ '5.7', '8.0', '8.4', '9.6' ] + wp: [ '4.7', '5.0', '6.7', '6.8' ] + multisite: [ false, true ] + + exclude: + - php: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] + wp: '4.7' + + with: + os: ${{ matrix.os }} + php: ${{ matrix.php }} + db-type: ${{ matrix.db-type }} + db-version: ${{ matrix.db-version }} + wp: ${{ matrix.wp }} + new-version: ${{ inputs.new-version && inputs.new-version || 'latest' }} + multisite: ${{ matrix.multisite }} diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index 6f6416c83000f..87c7981a2898d 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -358,9 +358,6 @@ jobs: db-version: '9.6' - php: '7.3' db-version: '9.6' - - php: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] - wp: '4.7' - - php: [ '7.4', '8.2', '8.3', '8.4', '8.5' ] with: os: ${{ matrix.os }} php: ${{ matrix.php }} From 23e278181919303eea126f9da9dc1e9fcbd1de22 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:06:09 -0400 Subject: [PATCH 07/13] Fix issues. --- .github/workflows/test-exclude-array.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-exclude-array.yml b/.github/workflows/test-exclude-array.yml index b53f3a549b983..73ee77e249f46 100644 --- a/.github/workflows/test-exclude-array.yml +++ b/.github/workflows/test-exclude-array.yml @@ -1,5 +1,8 @@ name: test-exclude-array.yml on: + push: + branches: + - 'make-upgrade-test-workflow-context-aware' jobs: # Tests the full list of PHP/MySQL combinations for the two most recent versions of WordPress. @@ -30,5 +33,5 @@ jobs: db-type: ${{ matrix.db-type }} db-version: ${{ matrix.db-version }} wp: ${{ matrix.wp }} - new-version: ${{ inputs.new-version && inputs.new-version || 'latest' }} + new-version: 'latest' multisite: ${{ matrix.multisite }} From d74dc7aa25715859dd636f42a12e0fb367bc55aa Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:20:49 -0400 Subject: [PATCH 08/13] Try breaking up tests. --- .github/workflows/test-exclude-array.yml | 37 ----- .github/workflows/upgrade-testing.yml | 165 +++++++++++++++++++---- 2 files changed, 139 insertions(+), 63 deletions(-) delete mode 100644 .github/workflows/test-exclude-array.yml diff --git a/.github/workflows/test-exclude-array.yml b/.github/workflows/test-exclude-array.yml deleted file mode 100644 index 73ee77e249f46..0000000000000 --- a/.github/workflows/test-exclude-array.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: test-exclude-array.yml -on: - push: - branches: - - 'make-upgrade-test-workflow-context-aware' - -jobs: - # Tests the full list of PHP/MySQL combinations for the two most recent versions of WordPress. - # - # Only runs when testing the currently supported branch or latest/nightly. - upgrade-tests-recent-releases: - name: ${{ matrix.wp }} to latest - uses: ./.github/workflows/reusable-upgrade-testing.yml - permissions: - contents: read - strategy: - fail-fast: false - matrix: - os: [ 'ubuntu-24.04' ] - php: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] - db-type: [ 'mysql' ] - db-version: [ '5.7', '8.0', '8.4', '9.6' ] - wp: [ '4.7', '5.0', '6.7', '6.8' ] - multisite: [ false, true ] - - exclude: - - php: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] - wp: '4.7' - - with: - os: ${{ matrix.os }} - php: ${{ matrix.php }} - db-type: ${{ matrix.db-type }} - db-version: ${{ matrix.db-version }} - wp: ${{ matrix.wp }} - new-version: 'latest' - multisite: ${{ matrix.multisite }} diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index 87c7981a2898d..aaa912be1bec5 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -102,12 +102,19 @@ jobs: with: wp-version: ${{ inputs.new-version }} - # Determines the list of WordPress versions to upgrade from when testing an older branch. + # Determines the lists of WordPress versions to upgrade from when testing an older branch. # - # Generates a JSON array of all branches from OLDEST_SECURITY_BRANCH up to, but not - # including, the target branch. For example, when the target is 5.0, this produces - # ["4.7", "4.8", "4.9"]. WordPress branches are versioned as X.Y, where Y increments - # from 0 to 9 before X increments and Y resets to 0. + # Produces two lists: + # - recent-from-versions: the preceding branch and the target branch itself. These are tested + # against the full PHP and database version matrix. + # - older-from-versions: all branches from OLDEST_SECURITY_BRANCH up to, but not including, + # the preceding branch. These are tested against a reduced PHP matrix. + # + # Also computes reduced-php-versions from the target branch's supported PHP versions, keeping + # only the oldest and newest version of each major (e.g. 7.0 and 7.4 from a 7.x range). + # + # WordPress branches are versioned as X.Y, where Y increments from 0 to 9 before X + # increments and Y resets to 0. # # Only runs when testing an older branch. determine-from-versions: @@ -116,7 +123,9 @@ jobs: timeout-minutes: 5 needs: [ determine-workflow-type, build-test-matrix ] outputs: - from-versions: ${{ steps.from-versions.outputs.from-versions }} + recent-from-versions: ${{ steps.from-versions.outputs.recent-from-versions }} + older-from-versions: ${{ steps.from-versions.outputs.older-from-versions }} + reduced-php-versions: ${{ steps.from-versions.outputs.reduced-php-versions }} steps: - name: Determine the FROM WordPress versions @@ -124,6 +133,7 @@ jobs: env: OLDEST_SECURITY_BRANCH: ${{ env.OLDEST_SECURITY_BRANCH }} MAJOR_WP_VERSION: ${{ needs.build-test-matrix.outputs.major-wp-version }} + PHP_VERSIONS: ${{ needs.build-test-matrix.outputs.php-versions }} run: | OLDEST_MAJOR=$(echo "$OLDEST_SECURITY_BRANCH" | cut -d'.' -f1) OLDEST_MINOR=$(echo "$OLDEST_SECURITY_BRANCH" | cut -d'.' -f2) @@ -133,22 +143,47 @@ jobs: TARGET_MAJOR=$(echo "$TARGET" | cut -d'.' -f1) TARGET_MINOR=$(echo "$TARGET" | cut -d'.' -f2) - # Build a JSON array of all branches from OLDEST_SECURITY_BRANCH up to, but not - # including, the target branch. Y increments 0–9, then X increments and Y resets to 0. - VERSIONS="" + # Determine the branch immediately preceding the target. + # Y decrements, rolling over from 0 to 9 and decrementing X. + if [ "$TARGET_MINOR" -eq 0 ]; then + PREV_MAJOR=$((TARGET_MAJOR - 1)) + PREV_MINOR=9 + else + PREV_MAJOR=$TARGET_MAJOR + PREV_MINOR=$((TARGET_MINOR - 1)) + fi + + # Clamp the preceding branch to OLDEST_SECURITY_BRANCH. + if [ "$PREV_MAJOR" -lt "$OLDEST_MAJOR" ] || \ + { [ "$PREV_MAJOR" -eq "$OLDEST_MAJOR" ] && [ "$PREV_MINOR" -lt "$OLDEST_MINOR" ]; }; then + PREV_MAJOR=$OLDEST_MAJOR + PREV_MINOR=$OLDEST_MINOR + fi + + # "recent" FROM versions: the preceding branch and the target branch. These are tested + # against the full PHP and database version matrix. + RECENT_VERSIONS="\"${PREV_MAJOR}.${PREV_MINOR}\"" + if [ "$PREV_MAJOR" != "$TARGET_MAJOR" ] || [ "$PREV_MINOR" != "$TARGET_MINOR" ]; then + RECENT_VERSIONS="${RECENT_VERSIONS},\"${TARGET_MAJOR}.${TARGET_MINOR}\"" + fi + echo "recent-from-versions=[${RECENT_VERSIONS}]" >> "$GITHUB_OUTPUT" + + # "older" FROM versions: all branches from OLDEST_SECURITY_BRANCH up to, but not + # including, the preceding branch. Y increments 0–9, then X increments and Y resets to 0. + OLDER_VERSIONS="" CURRENT_MAJOR=$OLDEST_MAJOR CURRENT_MINOR=$OLDEST_MINOR while true; do - if [ "$CURRENT_MAJOR" -gt "$TARGET_MAJOR" ] || \ - { [ "$CURRENT_MAJOR" -eq "$TARGET_MAJOR" ] && [ "$CURRENT_MINOR" -ge "$TARGET_MINOR" ]; }; then + if [ "$CURRENT_MAJOR" -gt "$PREV_MAJOR" ] || \ + { [ "$CURRENT_MAJOR" -eq "$PREV_MAJOR" ] && [ "$CURRENT_MINOR" -ge "$PREV_MINOR" ]; }; then break fi - if [ -n "$VERSIONS" ]; then - VERSIONS="${VERSIONS}," + if [ -n "$OLDER_VERSIONS" ]; then + OLDER_VERSIONS="${OLDER_VERSIONS}," fi - VERSIONS="${VERSIONS}\"${CURRENT_MAJOR}.${CURRENT_MINOR}\"" + OLDER_VERSIONS="${OLDER_VERSIONS}\"${CURRENT_MAJOR}.${CURRENT_MINOR}\"" if [ "$CURRENT_MINOR" -eq 9 ]; then CURRENT_MAJOR=$((CURRENT_MAJOR + 1)) @@ -158,7 +193,35 @@ jobs: fi done - echo "from-versions=[${VERSIONS}]" >> "$GITHUB_OUTPUT" + echo "older-from-versions=[${OLDER_VERSIONS}]" >> "$GITHUB_OUTPUT" + + # Reduced PHP versions: the oldest and newest version of each major PHP version, + # for use when testing older FROM branches. + declare -A OLDEST_PHP + declare -A NEWEST_PHP + + for version in $(echo "$PHP_VERSIONS" | tr -d '[]"' | tr ',' ' '); do + MAJOR=$(echo "$version" | cut -d'.' -f1) + if [ -z "${OLDEST_PHP[$MAJOR]}" ]; then + OLDEST_PHP[$MAJOR]=$version + fi + NEWEST_PHP[$MAJOR]=$version + done + + REDUCED_PHP="" + for MAJOR in $(printf '%s\n' "${!OLDEST_PHP[@]}" | sort -n); do + OLDEST=${OLDEST_PHP[$MAJOR]} + NEWEST=${NEWEST_PHP[$MAJOR]} + if [ -n "$REDUCED_PHP" ]; then + REDUCED_PHP="${REDUCED_PHP}," + fi + REDUCED_PHP="${REDUCED_PHP}\"${OLDEST}\"" + if [ "$OLDEST" != "$NEWEST" ]; then + REDUCED_PHP="${REDUCED_PHP},\"${NEWEST}\"" + fi + done + + echo "reduced-php-versions=[${REDUCED_PHP}]" >> "$GITHUB_OUTPUT" # Tests the full list of PHP/MySQL combinations for the two most recent versions of WordPress. # @@ -309,16 +372,11 @@ jobs: new-version: ${{ inputs.new-version && inputs.new-version || 'latest' }} multisite: ${{ matrix.multisite }} - # Tests an older WordPress branch against all PHP and database versions it supports, as - # documented in the version support JSON files. + # Tests the two most recent FROM branches (the target branch and the one immediately before it) + # against the full PHP and database version matrix supported by the target branch. # - # Uses the X.Y initial release of the branch as the FROM version to test the within-branch - # upgrade path. PHP and database versions unsupported by Docker are excluded, as are MySQL - # innovation releases other than the most recent. - # - # Only runs when testing an older branch (i.e. new-version is not empty, 'latest', 'nightly', - # or a version of the currently supported branch). - upgrade-tests-older-branch-mysql: + # Only runs when testing an older branch. + upgrade-tests-older-branch-recent-mysql: name: WP ${{ matrix.wp }} to ${{ inputs.new-version }} / PHP ${{ matrix.php }} / MySQL ${{ matrix.db-version }}${{ matrix.multisite && ' multisite' || '' }} uses: ./.github/workflows/reusable-upgrade-testing.yml needs: [ build-test-matrix, determine-from-versions ] @@ -331,7 +389,62 @@ jobs: php: ${{ fromJSON( needs.build-test-matrix.outputs.php-versions ) }} db-type: [ 'mysql' ] db-version: ${{ fromJSON( needs.build-test-matrix.outputs.mysql-versions ) }} - wp: ${{ fromJSON( needs.determine-from-versions.outputs.from-versions ) }} + wp: ${{ fromJSON( needs.determine-from-versions.outputs.recent-from-versions ) }} + multisite: [ false, true ] + exclude: + # There are no local WordPress Docker environment containers for PHP <= 5.3. + - php: '5.2' + - php: '5.3' + # MySQL containers <= 5.5 do not exist or fail to start properly. + - db-version: '5.0' + - db-version: '5.1' + - db-version: '5.5' + # The PHP <= 7.3/MySQL 8.4 jobs currently fail due to mysql_native_password being disabled by default. See https://core.trac.wordpress.org/ticket/61218. + - php: '7.2' + db-version: '8.4' + - php: '7.3' + db-version: '8.4' + # Only test the latest innovation release. + - db-version: '9.0' + - db-version: '9.1' + - db-version: '9.2' + - db-version: '9.3' + - db-version: '9.4' + - db-version: '9.5' + # MySQL 9.0+ will not work on PHP 7.2 & 7.3. See https://core.trac.wordpress.org/ticket/61218. + - php: '7.2' + db-version: '9.6' + - php: '7.3' + db-version: '9.6' + with: + os: ${{ matrix.os }} + php: ${{ matrix.php }} + db-type: ${{ matrix.db-type }} + db-version: ${{ matrix.db-version }} + wp: ${{ matrix.wp }} + new-version: ${{ inputs.new-version }} + multisite: ${{ matrix.multisite }} + + # Tests all remaining older FROM branches against a reduced PHP matrix: only the oldest and + # newest version of each major PHP version supported by the target branch. + # + # Only runs when testing an older branch and the target is more than one branch ahead of + # OLDEST_SECURITY_BRANCH (i.e. there are older FROM branches beyond the two most recent). + upgrade-tests-older-branch-older-mysql: + name: WP ${{ matrix.wp }} to ${{ inputs.new-version }} / PHP ${{ matrix.php }} / MySQL ${{ matrix.db-version }}${{ matrix.multisite && ' multisite' || '' }} + uses: ./.github/workflows/reusable-upgrade-testing.yml + needs: [ build-test-matrix, determine-from-versions ] + if: ${{ needs.determine-from-versions.outputs.older-from-versions != '[]' }} + permissions: + contents: read + strategy: + fail-fast: false + matrix: + os: [ 'ubuntu-24.04' ] + php: ${{ fromJSON( needs.determine-from-versions.outputs.reduced-php-versions ) }} + db-type: [ 'mysql' ] + db-version: ${{ fromJSON( needs.build-test-matrix.outputs.mysql-versions ) }} + wp: ${{ fromJSON( needs.determine-from-versions.outputs.older-from-versions ) }} multisite: [ false, true ] exclude: # There are no local WordPress Docker environment containers for PHP <= 5.3. @@ -373,7 +486,7 @@ jobs: permissions: actions: read contents: read - needs: [ upgrade-tests-recent-releases, upgrade-tests-wp-6x-mysql, upgrade-tests-wp-5x-php-7x-mysql, upgrade-tests-wp-5x-php-8x-mysql, upgrade-tests-oldest-wp-mysql, upgrade-tests-older-branch-mysql ] + needs: [ upgrade-tests-recent-releases, upgrade-tests-wp-6x-mysql, upgrade-tests-wp-5x-php-7x-mysql, upgrade-tests-wp-5x-php-8x-mysql, upgrade-tests-oldest-wp-mysql, upgrade-tests-older-branch-recent-mysql, upgrade-tests-older-branch-older-mysql ] 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' }} From 16f8c0cbdd984a9d1dc19bb432a8b78adfed9bc5 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:48:11 -0400 Subject: [PATCH 09/13] Fix old PHP and new MySQL. --- .github/workflows/reusable-upgrade-testing.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index 10d0f4b4b444b..2b99a2b2620be 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -75,6 +75,8 @@ jobs: --health-retries="5" -e MYSQL_ROOT_PASSWORD="root" -e MYSQL_DATABASE="test_db" + --entrypoint sh ${{ matrix.db-type }}:${{ matrix.db-version }} + -c "exec docker-entrypoint.sh mysqld${{ matrix.db-type == 'mysql' && 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 ${{ inputs.php }} From a21982fae51cec5094168266f903f742e65ce207 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:51:47 -0400 Subject: [PATCH 10/13] Remove entrypoint. --- .github/workflows/reusable-upgrade-testing.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index 2b99a2b2620be..6203e2b3282ae 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -75,7 +75,6 @@ jobs: --health-retries="5" -e MYSQL_ROOT_PASSWORD="root" -e MYSQL_DATABASE="test_db" - --entrypoint sh ${{ matrix.db-type }}:${{ matrix.db-version }} -c "exec docker-entrypoint.sh mysqld${{ matrix.db-type == 'mysql' && 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: From 5b844a8ed481a8ee387a1bc0cbcdf5dc2ade3051 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:53:31 -0400 Subject: [PATCH 11/13] Inputs not matrix. --- .github/workflows/reusable-upgrade-testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index 6203e2b3282ae..b4e21a640b559 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -75,7 +75,7 @@ jobs: --health-retries="5" -e MYSQL_ROOT_PASSWORD="root" -e MYSQL_DATABASE="test_db" - -c "exec docker-entrypoint.sh mysqld${{ matrix.db-type == 'mysql' && 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' ) || '' }}" + -c "exec docker-entrypoint.sh mysqld${{ inputs.db-type == 'mysql' && contains( fromJSON('["5.4", "5.5", "5.6", "7.0", "7.1", "7.2", "7.3"]'), inputs.php ) && ( inputs.db-version == '8.4' && ' --mysql-native-password=ON --authentication-policy=mysql_native_password' || ' --default-authentication-plugin=mysql_native_password' ) || '' }}" steps: - name: Set up PHP ${{ inputs.php }} From 420621421afa60bf4675dade6112e2bfe72c25cf Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 21:55:55 -0400 Subject: [PATCH 12/13] Re-add entrypoint. --- .github/workflows/reusable-upgrade-testing.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index b4e21a640b559..330f4b890e338 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -75,6 +75,7 @@ jobs: --health-retries="5" -e MYSQL_ROOT_PASSWORD="root" -e MYSQL_DATABASE="test_db" + --entrypoint sh ${{ matrix.db-type }}:${{ matrix.db-version }} -c "exec docker-entrypoint.sh mysqld${{ inputs.db-type == 'mysql' && contains( fromJSON('["5.4", "5.5", "5.6", "7.0", "7.1", "7.2", "7.3"]'), inputs.php ) && ( inputs.db-version == '8.4' && ' --mysql-native-password=ON --authentication-policy=mysql_native_password' || ' --default-authentication-plugin=mysql_native_password' ) || '' }}" steps: From 584b923d573008d6f00367bfdb776d35d1441c66 Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers <359867+desrosj@users.noreply.github.com> Date: Fri, 13 Mar 2026 22:54:09 -0400 Subject: [PATCH 13/13] Change logic. --- .github/workflows/reusable-upgrade-testing.yml | 2 -- .github/workflows/upgrade-testing.yml | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-upgrade-testing.yml b/.github/workflows/reusable-upgrade-testing.yml index 330f4b890e338..10d0f4b4b444b 100644 --- a/.github/workflows/reusable-upgrade-testing.yml +++ b/.github/workflows/reusable-upgrade-testing.yml @@ -75,8 +75,6 @@ jobs: --health-retries="5" -e MYSQL_ROOT_PASSWORD="root" -e MYSQL_DATABASE="test_db" - --entrypoint sh ${{ matrix.db-type }}:${{ matrix.db-version }} - -c "exec docker-entrypoint.sh mysqld${{ inputs.db-type == 'mysql' && contains( fromJSON('["5.4", "5.5", "5.6", "7.0", "7.1", "7.2", "7.3"]'), inputs.php ) && ( inputs.db-version == '8.4' && ' --mysql-native-password=ON --authentication-policy=mysql_native_password' || ' --default-authentication-plugin=mysql_native_password' ) || '' }}" steps: - name: Set up PHP ${{ inputs.php }} diff --git a/.github/workflows/upgrade-testing.yml b/.github/workflows/upgrade-testing.yml index aaa912be1bec5..99a98a1829143 100644 --- a/.github/workflows/upgrade-testing.yml +++ b/.github/workflows/upgrade-testing.yml @@ -125,6 +125,7 @@ jobs: outputs: recent-from-versions: ${{ steps.from-versions.outputs.recent-from-versions }} older-from-versions: ${{ steps.from-versions.outputs.older-from-versions }} + has-older-versions: ${{ steps.from-versions.outputs.has-older-versions }} reduced-php-versions: ${{ steps.from-versions.outputs.reduced-php-versions }} steps: @@ -194,6 +195,7 @@ jobs: done echo "older-from-versions=[${OLDER_VERSIONS}]" >> "$GITHUB_OUTPUT" + echo "has-older-versions=$( [ -n "$OLDER_VERSIONS" ] && echo 'true' || echo 'false' )" >> "$GITHUB_OUTPUT" # Reduced PHP versions: the oldest and newest version of each major PHP version, # for use when testing older FROM branches. @@ -434,7 +436,7 @@ jobs: name: WP ${{ matrix.wp }} to ${{ inputs.new-version }} / PHP ${{ matrix.php }} / MySQL ${{ matrix.db-version }}${{ matrix.multisite && ' multisite' || '' }} uses: ./.github/workflows/reusable-upgrade-testing.yml needs: [ build-test-matrix, determine-from-versions ] - if: ${{ needs.determine-from-versions.outputs.older-from-versions != '[]' }} + if: ${{ needs.determine-from-versions.outputs.has-older-versions == 'true' }} permissions: contents: read strategy: