Skip to content

Document when to stack a PR and how to drive gh stack #234

Document when to stack a PR and how to drive gh stack

Document when to stack a PR and how to drive gh stack #234

Workflow file for this run

# cspell:ignore DotReporter
name: PHP Tests
on:
pull_request:
push:
branches:
- main
workflow_dispatch:
# This workflow only reads the repository. Narrow the token accordingly.
permissions:
contents: read
# A superseded PR run is a result nobody is waiting on any more. Pushes to a
# long-lived branch are left alone so their history stays complete.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
# A broken WordPress nightly is upstream's problem, not this library's, so
# those legs report without blocking the PR.
continue-on-error: ${{ matrix.wp == 'nightly' }}
strategy:
fail-fast: false
matrix:
# The ends of the supported range only. A deprecation introduced at any
# PHP version fires on every later one, so 8.5 catches what 8.0-8.4
# would, and every leg resolves identical dependencies because
# config.platform.php pins resolution to 7.4 regardless of runtime.
#
# That pin is also the only reason the 8.5 leg has a test harness at
# all: wp-browser 3.8.1 declares php ">=7.1 <8.0", so it installs
# because resolution sees 7.4, then executes on 8.5. Its constraint is
# bypassed rather than satisfied. That is deliberate -- wp-browser 4.x
# is unreachable while 7.4 is the floor -- and the leg passes today. If
# it ever stops passing, drop the column rather than chasing it.
php:
- "7.4"
- "8.5"
# The nightly column is early warning for core regressions; when a
# nightly leg is red, its latest counterpart on the same PHP tells you
# whether WordPress or PHP is at fault.
wp:
- "latest"
- "nightly"
name: "Tests: PHP ${{ matrix.php }} / WP ${{ matrix.wp }}"
steps:
- name: Checkout the repository
uses: actions/checkout@v6
with:
fetch-depth: 1
# This workflow reaches into slic's own file layout, so tracking its main
# branch would let an upstream reorganisation change CI without a commit
# here. Pin to a tag and bump it deliberately when slic is upgraded.
- name: Checkout slic
uses: actions/checkout@v6
with:
repository: stellarwp/slic
ref: "2.3.0"
path: slic
fetch-depth: 1
# Codeception refuses to start unless register_argc_argv is On. slic's
# php.ini does not set it, so the base image default applies, and that
# differs between PHP versions -- 7.4 is On, 8.5 is Off. This file is
# bind-mounted into the slic container as conf.d/zz-docker.ini, which
# loads after the main php.ini, so appending here wins. The existence
# check is there because a bare append would happily create the file if
# slic ever moves or renames it, leaving the override silently unapplied
# and the 8.5 legs failing later at "cc build" for no visible reason.
- name: Enable register_argc_argv for Codeception
run: |
php_ini="${GITHUB_WORKSPACE}/slic/containers/slic/php.ini"
if [ ! -f "${php_ini}" ]; then
echo "Expected slic php.ini at ${php_ini}, but it does not exist. slic's layout has changed; update this workflow." >&2
exit 1
fi
echo "register_argc_argv=On" >> "${php_ini}"
- name: Set up slic env vars
run: |
echo "SLIC_BIN=${GITHUB_WORKSPACE}/slic/slic" >> $GITHUB_ENV
echo "SLIC_WP_DIR=${GITHUB_WORKSPACE}/slic/_wordpress" >> $GITHUB_ENV
echo "SLIC_WORDPRESS_DOCKERFILE=Dockerfile.base" >> $GITHUB_ENV
- name: Set run context for slic
run: echo "SLIC=1" >> $GITHUB_ENV
- name: Start ssh-agent
run: |
eval `ssh-agent -s`
echo "SSH_AUTH_SOCK=${SSH_AUTH_SOCK}" >> $GITHUB_ENV
- name: Set up slic for CI
run: |
cd ${GITHUB_WORKSPACE}/..
${SLIC_BIN} here
${SLIC_BIN} interactive off
${SLIC_BIN} build-prompt off
${SLIC_BIN} build-subdir off
${SLIC_BIN} xdebug off
${SLIC_BIN} debug on
${SLIC_BIN} php-version set ${{ matrix.php }} --skip-rebuild
- name: Set up the library
run: |
${SLIC_BIN} use ${{ github.event.repository.name }}
${SLIC_BIN} composer set-version 2
${SLIC_BIN} composer install
# The slic image ships a fixed WordPress that varies by PHP version, and
# no environment variable overrides it -- this step is the only lever.
# Without it a leg named "WP latest" silently tests whatever core the
# image happened to bake in. WPLoader installs from this codebase, so
# pinning here is what puts the suite on the version the leg claims.
- name: Pin the WordPress version
run: ${SLIC_BIN} site-cli core update --version=${{ matrix.wp }} --force
- name: Build codeception
id: build
run: ${SLIC_BIN} cc build
- name: Run unit tests (singlesite)
run: ${SLIC_BIN} run unit --env singlesite --ext DotReporter
# Run even when singlesite failed: one run should report both envs rather
# than making you fix one and rediscover the other. It is gated on the
# build having succeeded, because running the suite after a failed
# install or build only stacks a second, misleading failure on top of the
# real one.
- name: Run unit tests (multisite)
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: ${SLIC_BIN} run unit --env multisite --ext DotReporter
# continue-on-error keeps a red nightly leg from blocking the PR, but it
# also makes it report as a pass in the checks list, so the only way to
# notice is to open the run. Leave a trace where it will actually be seen.
- name: Flag a failing nightly leg
if: ${{ failure() && matrix.wp == 'nightly' }}
run: |
echo "::warning title=WordPress nightly failed::PHP ${{ matrix.php }} against WordPress nightly is red. This does not block the PR."
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> PHP ${{ matrix.php }} / WP nightly failed. Non-blocking, but worth a look." >> $GITHUB_STEP_SUMMARY
- name: Upload test output
if: failure()
uses: actions/upload-artifact@v7
with:
name: "test-output-php${{ matrix.php }}-wp${{ matrix.wp }}"
path: tests/_output
if-no-files-found: ignore
retention-days: 7