Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .github/workflows/runtime-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ jobs:
multisite: '1'
http_port: '8901'
db_port: '33081'
- name: nginx-php83-wplatest
server: nginx
php: '8.3'
wp: latest
db_engine: mysql
http_port: '8897'
db_port: '33077'

steps:
- name: Checkout
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- The runtime matrix's nginx cells pass again. The smoke test sent the write routes' `PATCH`, `PUT`, and `DELETE` requests to `/?rest_route=…`, which nginx answers with its own `405` for those methods, so the request never reached WordPress. It now uses `/index.php?rest_route=…`, the form WordPress itself builds for plain permalinks. Sites were not affected. Pull requests now also run an nginx cell, so a server-specific failure shows up before merge.

## [1.7.0] - 2026-09-26

### Added
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ The GitHub Actions runtime matrix currently covers:
- Nginx + PHP 8.2 + latest WordPress
- Nginx + PHP 8.3 + latest WordPress

Pull requests run a four-cell subset: Apache with PHP 7.4 and WordPress 6.4, Apache with PHP 8.3 and latest WordPress (single site and Multisite), and Nginx with PHP 8.3. Pushes to `main` run all ten.

Every cell tests the packaged release, built with `npm run package:release` and including its production `vendor/`, not the source checkout. Each cell:

- activates the plugin and checks the front-end render and the read routes;
Expand Down
27 changes: 16 additions & 11 deletions scripts/runtime-matrix/smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ MULTISITE="${WP_BIBLIO_MULTISITE:-0}"
HTTP_PORT="${WP_BIBLIO_HTTP_PORT:-8899}"
DB_PORT="${WP_BIBLIO_DB_PORT:-33069}"
SITE_URL="http://127.0.0.1:${HTTP_PORT}"
# REST requests use index.php?rest_route=, the form WordPress itself builds
# for plain permalinks. A bare /?rest_route= only works for GET, HEAD, and
# POST on nginx: its index module hands the directory request to index.php
# for those methods alone, so PATCH, PUT, and DELETE get nginx's own 405.
REST_URL="${SITE_URL}/index.php?rest_route="
WORKDIR="${RUNTIME_ROOT}/${SERVER}-php${PHP_VERSION}-wp${WP_VERSION}-${DB_ENGINE}$([ "$MULTISITE" = "1" ] && printf '%s' '-multisite' || true)"
SITE_DIR="${WORKDIR}/site"
COMPOSE_FILE="${WORKDIR}/docker-compose.yml"
Expand Down Expand Up @@ -195,11 +200,11 @@ wait_for_http() {
# 404s with rest_no_route. Poll the REST index instead of racing it.
wait_for_plugin_routes() {
attempt=0
until curl -fsS "$SITE_URL/?rest_route=/" 2>/dev/null | grep -q 'bibliography\\*/v1'; do
until curl -fsS "${REST_URL}/" 2>/dev/null | grep -q 'bibliography\\*/v1'; do
attempt=$((attempt + 1))
if [ "$attempt" -gt 30 ]; then
echo "Timed out waiting for bibliography/v1 routes at $SITE_URL" >&2
curl -sS "$SITE_URL/?rest_route=/" | head -c 2000 >&2 || true
curl -sS "${REST_URL}/" | head -c 2000 >&2 || true
echo >&2
exit 1
fi
Expand Down Expand Up @@ -334,9 +339,9 @@ printf '%s\n' "$POST_ID" > "$ARTIFACT_DIR/post-id.txt"
wait_for_plugin_routes

capture_http frontend "$SITE_URL/?p=$POST_ID"
capture_http rest-collection "$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies"
capture_http rest-text "$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies/0&format=text"
capture_http rest-csl-json "$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies/0&format=csl-json"
capture_http rest-collection "${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies"
capture_http rest-text "${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies/0&format=text"
capture_http rest-csl-json "${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies/0&format=csl-json"

grep -q 'bibliography-builder-entry-text' "$ARTIFACT_RESPONSE_DIR/frontend.body"
grep -q '"entryCount":1' "$ARTIFACT_RESPONSE_DIR/rest-collection.body"
Expand Down Expand Up @@ -378,21 +383,21 @@ fi
# until opcache revalidates it (see wait_for_plugin_routes). Until then the
# password is ignored and write requests arrive logged out, so wait for it.
attempt=0
until [ "$(curl -sS -o /dev/null -w '%{http_code}' -u "admin:$APP_PASSWORD" "$SITE_URL/?rest_route=/wp/v2/users/me")" = "200" ]; do
until [ "$(curl -sS -o /dev/null -w '%{http_code}' -u "admin:$APP_PASSWORD" "${REST_URL}/wp/v2/users/me")" = "200" ]; do
attempt=$((attempt + 1))
if [ "$attempt" -gt 30 ]; then
echo "Application password never authenticated at $SITE_URL" >&2
curl -sS -u "admin:$APP_PASSWORD" "$SITE_URL/?rest_route=/wp/v2/users/me" | head -c 2000 >&2 || true
curl -sS -u "admin:$APP_PASSWORD" "${REST_URL}/wp/v2/users/me" | head -c 2000 >&2 || true
echo >&2
exit 1
fi
sleep 1
done

CITATIONS_URL="$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies/0/citations"
CITATIONS_URL="${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies/0/citations"
NEW_ITEM='{"items":[{"type":"article-journal","title":"Beta Findings","author":[{"family":"Beta","given":"Bea"}],"container-title":"Journal of Smoke Tests","volume":"3","issue":"1","page":"10-20","issued":{"date-parts":[[2021]]}}]}'

rest_call write-read GET "$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies" 200
rest_call write-read GET "${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies" 200
rest_call write-dry-run POST "$CITATIONS_URL" 200 "$NEW_ITEM"
grep -q '"dryRun":true' "$ARTIFACT_RESPONSE_DIR/write-dry-run.body"
ETAG=$(header_etag write-dry-run)
Expand All @@ -406,15 +411,15 @@ rest_call write-commit POST "$CITATIONS_URL&dry_run=false" 200 "$NEW_ITEM" "$ETA
grep -q '"dryRun":false' "$ARTIFACT_RESPONSE_DIR/write-commit.body"
[ "$(header_etag write-commit)" != "$ETAG" ]

capture_http write-text "$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies/0&format=text"
capture_http write-text "${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies/0&format=text"
grep -q 'Beta, Bea' "$ARTIFACT_RESPONSE_DIR/write-text.body"
grep -q 'Journal of Smoke Tests 3, no. 1 (2021): 10–20' "$ARTIFACT_RESPONSE_DIR/write-text.body"
capture_http write-frontend "$SITE_URL/?p=$POST_ID"
grep -q 'Beta Findings' "$ARTIFACT_RESPONSE_DIR/write-frontend.body"

# Block settings and reformatting (Tier 3). The settings PATCH shares its path
# with the public GET route, so this also proves the method falls through to it.
BIBLIOGRAPHY_URL="$SITE_URL/?rest_route=/bibliography/v1/posts/$POST_ID/bibliographies/0"
BIBLIOGRAPHY_URL="${REST_URL}/bibliography/v1/posts/$POST_ID/bibliographies/0"
rest_call write-settings PATCH "$BIBLIOGRAPHY_URL&dry_run=false" 200 '{"headingText":"Smoke Sources","outputCoins":true}' "$(header_etag write-commit)"
grep -q '"headingText":"Smoke Sources"' "$ARTIFACT_RESPONSE_DIR/write-settings.body"
rest_call write-reformat POST "$BIBLIOGRAPHY_URL/reformat&dry_run=false" 200 '{"style":"apa-7"}' "$(header_etag write-settings)"
Expand Down
Loading