diff --git a/CLAUDE.md b/CLAUDE.md index 9986d6f..93c993c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -114,7 +114,7 @@ The Playground blueprint at `playground/blueprint.json` configures the GitHub/re ## CI overview - **ci.yml** — lint, Jest, PHPUnit, Psalm, Playwright Playground E2E, coverage upload, package artifact -- **runtime-matrix.yml** — smoke tests across PHP 7.4–8.4, WP 6.4+, Apache/Nginx, MySQL via Docker. They run against the packaged release ZIP contents (`WP_BIBLIO_PLUGIN_DIR`), not the checkout. Beyond activation and the read routes, `scripts/runtime-matrix/smoke.sh` checks formatter parity with `tests/fixtures/csl-styles/` goldens on each PHP version, times a 200-entry `/format` request over HTTP with `scripts/time-format-route.sh` (also usable by hand against any site), and exercises the write routes over HTTP with an application password. +- **runtime-matrix.yml** — smoke tests across PHP 7.4–8.4, WP 6.4+, Apache/Nginx, MySQL via Docker. They run against the packaged release ZIP contents (`WP_BIBLIO_PLUGIN_DIR`), not the checkout. Beyond activation and the read routes, `scripts/runtime-matrix/smoke.sh` checks formatter parity with `tests/fixtures/csl-styles/` goldens on each PHP version, times a 200-entry `/format` request over HTTP with `scripts/time-format-route.sh` (also usable by hand against any site), exercises the write routes over HTTP with an application password, and runs the Abilities API on WordPress 6.9+. - **release.yml** — GitHub Release and ZIP publication on a version bump merged to `main`, a `v*` tag, or by hand - **wp-deploy.yml** — deploys to WordPress.org SVN on published GitHub release, release dispatch, or manual run - **codeql.yml** — security analysis diff --git a/scripts/runtime-matrix/check-abilities.php b/scripts/runtime-matrix/check-abilities.php new file mode 100644 index 0000000..87f73ae --- /dev/null +++ b/scripts/runtime-matrix/check-abilities.php @@ -0,0 +1,99 @@ + --user=admin + * Prints "abilities-ok ", "abilities-skip" (no Abilities API), or + * "abilities-fail ". + * PHP 7.4-compatible on purpose. + * + * @package BibliographyBuilder + */ + +if ( ! function_exists( 'wp_get_ability' ) ) { + echo "abilities-skip\n"; + return; +} + +$post_id = isset( $args[0] ) ? (int) $args[0] : 0; +$fail = function ( $reason ) { + echo 'abilities-fail ' . $reason . "\n"; +}; + +$read = wp_get_ability( 'borges/get-bibliographies' ); +$add = wp_get_ability( 'borges/add-citations' ); + +if ( ! $read || ! $add ) { + $fail( 'ability-not-registered' ); + return; +} + +$listed = $read->execute( array( 'post_id' => $post_id ) ); + +if ( is_wp_error( $listed ) ) { + $fail( 'get-bibliographies ' . $listed->get_error_code() ); + return; +} + +if ( empty( $listed['bibliographies'][0]['entryCount'] ) ) { + $fail( 'get-bibliographies-empty' ); + return; +} + +$before_count = (int) $listed['bibliographies'][0]['entryCount']; +$before_content = get_post( $post_id )->post_content; + +$result = $add->execute( + array( + 'post_id' => $post_id, + 'index' => 0, + 'dry_run' => true, + 'items' => array( + array( + 'type' => 'book', + 'title' => 'Gamma Ability Book', + 'author' => array( + array( + 'family' => 'Gamma', + 'given' => 'Gus', + ), + ), + 'issued' => array( 'date-parts' => array( array( 2022 ) ) ), + ), + ), + ) +); + +if ( is_wp_error( $result ) ) { + $fail( 'add-citations ' . $result->get_error_code() ); + return; +} + +if ( true !== ( $result['dryRun'] ?? null ) ) { + $fail( 'not-a-dry-run' ); + return; +} + +if ( empty( $result['etag'] ) ) { + $fail( 'no-etag' ); + return; +} + +$after_count = (int) ( $result['bibliography']['entryCount'] ?? -1 ); + +if ( $after_count !== $before_count + 1 ) { + $fail( 'entry-count ' . $before_count . ' -> ' . $after_count ); + return; +} + +if ( get_post( $post_id )->post_content !== $before_content ) { + $fail( 'dry-run-changed-post' ); + return; +} + +echo 'abilities-ok ' . $before_count . "\n"; diff --git a/scripts/runtime-matrix/smoke.sh b/scripts/runtime-matrix/smoke.sh index b33406f..69d1e0f 100755 --- a/scripts/runtime-matrix/smoke.sh +++ b/scripts/runtime-matrix/smoke.sh @@ -443,4 +443,19 @@ grep -q 'Z3988' "$ARTIFACT_RESPONSE_DIR/write-reformat-frontend.body" wp_exec "wp eval-file /smoke/check-blocks.php $POST_ID --allow-root --path=/var/www/html" > "$ARTIFACT_DIR/check-blocks.txt" 2>&1 || true grep -q '^blocks-ok 1$' "$ARTIFACT_DIR/check-blocks.txt" +# --- Abilities API (WordPress 6.9+) ----------------------------------------- +# +# Runs the abilities through the Abilities API itself, in PHP as the admin user: +# a read, then a write-ability dry run that must leave the post untouched. The +# write abilities register because the mu-plugin above enables the write routes. +# Older WordPress has no Abilities API, so the check skips. +wp_exec "wp eval-file /smoke/check-abilities.php $POST_ID --user=admin --allow-root --path=/var/www/html" > "$ARTIFACT_DIR/check-abilities.txt" 2>&1 || true +if grep -q '^abilities-skip$' "$ARTIFACT_DIR/check-abilities.txt"; then + echo "Skipping Abilities API checks: this WordPress has no Abilities API (needs 6.9+)" +elif ! grep -q '^abilities-ok [1-9]' "$ARTIFACT_DIR/check-abilities.txt"; then + echo "Abilities API check failed:" >&2 + head -c 4000 "$ARTIFACT_DIR/check-abilities.txt" >&2 + exit 1 +fi + echo "Runtime smoke passed: server=${SERVER} php=${PHP_VERSION} wp=${WP_VERSION} db=${DB_ENGINE} multisite=${MULTISITE}"