From 0940a1fb27f3e199d35696f0add9561c8c73c880 Mon Sep 17 00:00:00 2001 From: Tsvetan Stoychev Date: Mon, 21 Sep 2026 13:11:41 +0300 Subject: [PATCH] Keep Playwright Docker images in sync --- AGENTS.md | 5 +- CONTRIBUTING.md | 2 +- Makefile | 3 +- checklist.md | 2 + docker-compose.yml | 3 +- docker/woocommerce-e2e.yml | 4 +- tools/verify-playwright-consistency.sh | 107 +++++++++++++++++++++++++ 7 files changed, 119 insertions(+), 7 deletions(-) create mode 100755 tools/verify-playwright-consistency.sh diff --git a/AGENTS.md b/AGENTS.md index 985538f..8d22a5b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,8 +78,9 @@ in the matching skill. WooCommerce version and checksum synchronized in `tools/setup-woocommerce-e2e.sh`. The setup disables WooCommerce Coming soon mode so anonymous storefront tests can see the seeded product. - Review and update each Docker image tag and digest together in - `docker/woocommerce-e2e.yml`. + Keep `@playwright/test`, its locked packages, and the Playwright Docker image + tags synchronized. Review and update each Docker image tag and digest together + in `docker-compose.yml` and `docker/woocommerce-e2e.yml`. - Pin third-party GitHub Actions to full 40-character commit SHAs. Keep the reviewed release tag in the adjacent comment and update pins through reviewed Dependabot pull requests. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc069a9..e52fd72 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ The development site is available at with `admin` / `ba The installable plugin is [`plugins/basicrum/`](plugins/basicrum/). Repository root files provide development, browser-test, Docker, CI, and release tooling. -Follow the permanent conventions in [AGENTS.md](AGENTS.md), including WordPress Coding Standards, PHP 7.4 compatibility, ASCII hyphens, the assigned WordPress.org text domain, synchronized version metadata, privacy-safe consent behavior, and immutable GitHub Actions pins. +Follow the permanent conventions in [AGENTS.md](AGENTS.md), including WordPress Coding Standards, PHP 7.4 compatibility, ASCII hyphens, the assigned WordPress.org text domain, synchronized version metadata, synchronized Playwright packages and Docker images, privacy-safe consent behavior, and immutable GitHub Actions pins. When changing user-facing text, regenerate the WordPress POT template. Locale-specific PO and MO files are not bundled. When changing settings, keep defaults, rendering, validation, runtime behavior, tests, and documentation synchronized. diff --git a/Makefile b/Makefile index 2ab5322..c1cc506 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ help: @echo " analyse Run PHPStan static analysis" @echo " composer-validate Validate Composer metadata and lock file" @echo " composer-audit Audit locked Composer dependencies" - @echo " conventions Enforce ASCII hyphens and version consistency" + @echo " conventions Enforce repository metadata consistency" @echo " translations Update the POT translation template" @echo " js-install Install locked JavaScript test dependencies" @echo " js-test Run loader behavior tests in Chromium" @@ -95,6 +95,7 @@ conventions: sh tools/verify-ascii-hyphens.sh sh tools/verify-version-consistency.sh sh tools/verify-text-domain.sh + sh tools/verify-playwright-consistency.sh sh tools/verify-boomerang-provenance.sh translations: diff --git a/checklist.md b/checklist.md index b647cf9..5affd75 100644 --- a/checklist.md +++ b/checklist.md @@ -167,6 +167,8 @@ Acceptance criteria: - [x] Add a WordPress.org slug and text-domain consistency check covering the plugin header, source literals, WPCS configuration, POT filename, and release package identity. +- [x] Add a Playwright consistency check covering npm metadata and the pinned + Docker images used by local JavaScript and WooCommerce browser tests. - [x] Run all convention checks in pull requests and pushes to the main branch. - [x] Document the checks in `AGENTS.md` and the contributor documentation. diff --git a/docker-compose.yml b/docker-compose.yml index 0f78c4c..03527c9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -78,7 +78,8 @@ services: tty: true javascript: - image: mcr.microsoft.com/playwright:v1.62.1-noble + # Reviewed tag: mcr.microsoft.com/playwright:v1.63.0-noble + image: mcr.microsoft.com/playwright:v1.63.0-noble@sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27 working_dir: /workspace environment: HOME: /tmp diff --git a/docker/woocommerce-e2e.yml b/docker/woocommerce-e2e.yml index a7c642b..0de6a76 100644 --- a/docker/woocommerce-e2e.yml +++ b/docker/woocommerce-e2e.yml @@ -72,8 +72,8 @@ services: - plugin_workspace:/workspace javascript: - # Reviewed tag: mcr.microsoft.com/playwright:v1.62.1-noble - image: mcr.microsoft.com/playwright:v1.62.1-noble@sha256:dcc5531e97840b9b5e794f2814476b21571c5124a3fca2267d73041f56e7580e + # Reviewed tag: mcr.microsoft.com/playwright:v1.63.0-noble + image: mcr.microsoft.com/playwright:v1.63.0-noble@sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27 working_dir: /workspace environment: CI: "true" diff --git a/tools/verify-playwright-consistency.sh b/tools/verify-playwright-consistency.sh new file mode 100755 index 0000000..b9b29c3 --- /dev/null +++ b/tools/verify-playwright-consistency.sh @@ -0,0 +1,107 @@ +#!/bin/sh + +set -eu + +fail() { + printf '%s\n' "$1" >&2 + exit 1 +} + +require_single_value() { + label=$1 + value=$2 + + if [ -z "$value" ]; then + fail "Could not find $label." + fi + + line_count=$( printf '%s\n' "$value" | awk 'END { print NR }' ) + + if [ "$line_count" -ne 1 ]; then + fail "Expected exactly one $label, found $line_count." + fi + + printf '%s\n' "$value" +} + +lock_package_version() { + package_name=$1 + + awk -v package_key="\"node_modules/${package_name}\": {" ' + index($0, package_key) { + in_package = 1 + next + } + + in_package && match($0, /"version": "[^"]+"/) { + version = substr($0, RSTART, RLENGTH) + sub(/^"version": "/, "", version) + sub(/"$/, "", version) + print version + exit + } + ' package-lock.json +} + +repository_root=$( git rev-parse --show-toplevel 2>/dev/null ) || { + fail 'Playwright consistency check must run inside a Git worktree.' +} + +cd "$repository_root" + +for required_file in package.json package-lock.json docker-compose.yml docker/woocommerce-e2e.yml; do + if [ ! -f "$required_file" ]; then + fail "Required Playwright metadata file is missing: $required_file" + fi +done + +package_version=$( require_single_value '@playwright/test package version' "$( + sed -n 's/^[[:space:]]*"@playwright\/test":[[:space:]]*"\([^"]*\)",*[[:space:]]*$/\1/p' package.json +)" ) + +if ! printf '%s\n' "$package_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then + fail "@playwright/test must use an exact X.Y.Z version, found $package_version." +fi + +for lock_package in '@playwright/test' playwright playwright-core; do + lock_version=$( require_single_value "$lock_package lockfile version" "$( lock_package_version "$lock_package" )" ) + + if [ "$lock_version" != "$package_version" ]; then + fail "$lock_package lockfile version ($lock_version) does not match @playwright/test ($package_version)." + fi +done + +expected_image="mcr.microsoft.com/playwright:v${package_version}-noble" +expected_digest='' + +for compose_file in docker-compose.yml docker/woocommerce-e2e.yml; do + image=$( require_single_value "$compose_file Playwright image" "$( + sed -n 's/^[[:space:]]*image:[[:space:]]*\(mcr\.microsoft\.com\/playwright:[^[:space:]]*\)[[:space:]]*$/\1/p' "$compose_file" + )" ) + + case "$image" in + "${expected_image}@sha256:"*) + ;; + *) + fail "$compose_file must use ${expected_image} with an immutable SHA-256 digest, found $image." + ;; + esac + + digest=${image##*@sha256:} + + if ! printf '%s\n' "$digest" | grep -Eq '^[0-9a-f]{64}$'; then + fail "$compose_file has an invalid Playwright image digest: $digest" + fi + + if ! grep -Fq "# Reviewed tag: $expected_image" "$compose_file"; then + fail "$compose_file does not document the reviewed Playwright tag $expected_image." + fi + + if [ -z "$expected_digest" ]; then + expected_digest=$digest + elif [ "$digest" != "$expected_digest" ]; then + fail "Playwright Docker image digests differ: $expected_digest and $digest." + fi +done + +printf '%s\n' "Playwright consistency check passed: $package_version sha256:$expected_digest"