Skip to content

[Docs] Add initial setup instructions (#3819) #15179

[Docs] Add initial setup instructions (#3819)

[Docs] Add initial setup instructions (#3819) #15179

Workflow file for this run

name: CI
on:
push:
branches:
- trunk
pull_request:
# Disable permissions for all available scopes by default.
# Any needed permissions should be configured at the job level.
permissions: {}
jobs:
# This step:
# * Warms up the node_modules cache
# * Performs linting and typechecking
# * Checks for orphaned documentation pages
#
# The linting tasks take ~5s to complete and it doesn't
# make sense to separate them into separate steps that would
# take ~25s just to run git clone and restore node_modules.
lint-and-typecheck:
name: 'Lint and typecheck'
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- run: npx nx affected --target=lint
- run: npx nx affected --target=typecheck
- run: npx nx check-orphan-pages docs-site
- run: bash tools/check-node-engine-alignment.sh
test-unit-asyncify:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
strategy:
fail-fast: false
matrix:
include:
- name: test-unit-asyncify (1/7)
target: test
- name: test-unit-asyncify (2/7)
target: test-group-1-asyncify
- name: test-unit-asyncify (3/7)
target: test-group-2-asyncify
- name: test-unit-asyncify (4/7)
target: test-group-3-asyncify
- name: test-unit-asyncify (5/7)
target: test-group-4-asyncify
- name: test-unit-asyncify (6/7)
target: test-group-5-asyncify
- name: test-unit-asyncify (7/7)
target: test-group-6-asyncify
name: ${{ matrix.name }}
services:
mysql:
image: mysql:5.7
env:
MYSQL_DATABASE: test_db
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpassword
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping --silent"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 20
- run: node --expose-gc node_modules/nx/bin/nx affected --target=${{ matrix.target }}
env:
MYSQL_DATABASE: test_db
MYSQL_USER: user
MYSQL_PASSWORD: password
test-unit-jspi:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
strategy:
fail-fast: false
matrix:
include:
- name: test-unit-jspi (1/6)
target: test-group-1-jspi
- name: test-unit-jspi (2/6)
target: test-group-2-jspi
- name: test-unit-jspi (3/6)
target: test-group-3-jspi
- name: test-unit-jspi (4/6)
target: test-group-4-jspi
- name: test-unit-jspi (5/6)
target: test-group-5-jspi
- name: test-unit-jspi (6/6)
target: test-group-6-jspi
name: ${{ matrix.name }}
services:
mysql:
image: mysql:5.7
env:
MYSQL_DATABASE: test_db
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpassword
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping --silent"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 24
- run: node --expose-gc node_modules/nx/bin/nx affected --target=${{ matrix.target }}
env:
MYSQL_DATABASE: test_db
MYSQL_USER: user
MYSQL_PASSWORD: password
test-playground-cli:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
continue-on-error: true
runs-on: ${{ matrix.os }}
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
name: 'test-playground-cli (${{ matrix.os }})'
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 22
- name: Run full test suite
run: node node_modules/nx/bin/nx affected --target=test-playground-cli
test-file-locking:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
async-strategy: [asyncify, jspi]
continue-on-error: true
runs-on: ${{ matrix.os }}
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
name: 'test-file-locking-${{ matrix.async-strategy }} (${{ matrix.os }})'
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 22
- name: Run full test suite
run: node node_modules/nx/bin/nx affected --target=test-file-locking-${{ matrix.async-strategy }}
test-e2e-php-wasm-web-jspi:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- run: sudo npx playwright install
- run: sudo CI=true JSPI=true npx nx e2e php-wasm-web
test-e2e-php-wasm-web-asyncify:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- run: sudo npx playwright install
- run: sudo CI=true npx nx e2e php-wasm-web
test-e2e:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
# Run as root to allow node to bind to port 80
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- run: sudo ./node_modules/.bin/cypress install --force
- run: sudo CYPRESS_CI=1 npx nx e2e playground-website --configuration=ci --verbose
# Upload the Cypress screenshots as artifacts if the job fails
- uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: cypress-screenshots
path: dist/cypress/packages/playground/website/screenshots
# E2E Playwright tests - builds inline per runner for faster parallel execution
# Previously used a prepare job + artifact sharing, but inline builds allow
# all shards to start immediately in parallel, reducing total wall time.
test-e2e-playwright:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
strategy:
fail-fast: false
matrix:
# 3 shards per browser for balanced parallel execution
# (4 shards caused uneven distribution due to serial test files)
include:
- browser: 'chromium'
shard: '1/3'
shard_name: '1-of-3'
- browser: 'chromium'
shard: '2/3'
shard_name: '2-of-3'
- browser: 'chromium'
shard: '3/3'
shard_name: '3-of-3'
- browser: 'firefox'
shard: '1/3'
shard_name: '1-of-3'
- browser: 'firefox'
shard: '2/3'
shard_name: '2-of-3'
- browser: 'firefox'
shard: '3/3'
shard_name: '3-of-3'
- browser: 'webkit'
shard: '1/3'
shard_name: '1-of-3'
- browser: 'webkit'
shard: '2/3'
shard_name: '2-of-3'
- browser: 'webkit'
shard: '3/3'
shard_name: '3-of-3'
steps:
- name: Free up runner disk space
shell: bash
run: |
set -euo pipefail
echo "Disk usage before cleanup:"
df -h
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/share/dotnet
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
echo "Disk usage after cleanup:"
df -h
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- name: Install Playwright Browser
run: sudo npx playwright install ${{ matrix.browser }} --with-deps
- name: Build app for E2E tests
run: CORS_PROXY_URL=http://127.0.0.1:5263/cors-proxy.php? npx nx e2e:playwright:prepare-app-deploy-and-offline-mode playground-website
- name: Run Playwright tests - ${{ matrix.browser }}${{ matrix.shard && format(' (shard {0})', matrix.shard) || '' }}
run: |
SHARD_ARG=""
if [ -n "${{ matrix.shard }}" ]; then
SHARD_ARG="--shard=${{ matrix.shard }}"
fi
if [ "${{ matrix.browser }}" = "firefox" ]; then
sudo -E HOME=/root XDG_RUNTIME_DIR=/root CI=true npx playwright test --config=packages/playground/website/playwright/playwright.ci.config.ts --project=${{ matrix.browser }} $SHARD_ARG
else
sudo CI=true npx playwright test --config=packages/playground/website/playwright/playwright.ci.config.ts --project=${{ matrix.browser }} $SHARD_ARG
fi
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report-${{ matrix.browser }}${{ matrix.shard_name && format('-shard-{0}', matrix.shard_name) || '' }}
path: packages/playground/website/playwright-report/
if-no-files-found: ignore
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-snapshots-${{ matrix.browser }}${{ matrix.shard_name && format('-shard-{0}', matrix.shard_name) || '' }}
path: packages/playground/website/playwright/e2e/deployment.spec.ts-snapshots/
if-no-files-found: ignore
test-e2e-personal-wp:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- name: Install Playwright Browser
run: npx playwright install chromium --with-deps
- name: Run personal-wp Playwright e2e tests
run: CI=true npx playwright test --config=packages/playground/personal-wp/playwright/playwright.config.ts --project=chromium
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-personal-wp-report
path: packages/playground/personal-wp/playwright-report/
if-no-files-found: ignore
test-e2e-components:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
- name: Run Playwright tests for components
run: npx nx e2e playground-components
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-components-report
path: packages/playground/components/playwright-report/
if-no-files-found: ignore
# Run MCP e2e tests independently from other tests because running a local version of the MCP server from TypeScript files requires Node 22+
test-e2e-mcp:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: '22'
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
- name: Run MCP e2e tests
run: npx nx test:mcp playground-mcp
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-mcp-report
path: packages/playground/mcp/playwright-report/
if-no-files-found: ignore
test-docs-api-reference:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- name: Install Playwright Browsers
run: npx playwright install --with-deps chromium
- name: Verify docs API reference
run: npx nx run docs-site:api-e2e
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: docs-api-e2e-report
path: packages/docs/site/test-results/
if-no-files-found: ignore
test-built-npm-packages:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 22
- name: Validate publish package overrides
run: node tools/scripts/check-publish-package-overrides.mjs
- name: Install Playwright Browsers
run: npx --no-install playwright install --with-deps chromium
- name: Build packages, start local registry, and run integration tests
run: packages/playground/test-built-npm-packages/run-tests.sh
test-playground-client-types-rollup:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 22
- name: Verify bundled client declarations
run: |
npm exec -- nx run playground-client:test:rollup-declarations
npm pack --dry-run dist/packages/playground/client
test-running-unbuilt-playground-cli:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 22
- run: packages/playground/cli/tests/test-running-unbuilt-cli.sh
test-php-wasm-cli-smoke:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 20
- run: packages/php-wasm/cli/tests/smoke-test.sh
detect-compile-extension-helper-changes:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo and fetch commit history.
outputs:
changed: ${{ steps.changed.outputs.changed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- id: changed
name: Check compile-extension package changes
shell: bash
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "pull_request" ]; then
base_sha="${{ github.event.pull_request.base.sha }}"
else
base_sha="${{ github.event.before }}"
fi
if [ -z "$base_sha" ] || [[ "$base_sha" =~ ^0+$ ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
git fetch --no-tags --depth=1 origin "$base_sha"
if git diff --name-only "$base_sha" "$GITHUB_SHA" -- packages/php-wasm/compile-extension/ | grep -q .; then
echo "changed=true" >> "$GITHUB_OUTPUT"
else
echo "changed=false" >> "$GITHUB_OUTPUT"
fi
test-compile-extension-helper:
needs: detect-compile-extension-helper-changes
if: (github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request') && needs.detect-compile-extension-helper-changes.outputs.changed == 'true'
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read # Required to clone the repo.
steps:
- name: Free up runner disk space
shell: bash
run: |
set -euo pipefail
cleanup_path() {
echo "Removing $1"
sudo rm -rf "$1"
}
echo "Disk usage before cleanup:"
df -h
cleanup_path /usr/local/lib/android
cleanup_path /usr/share/dotnet
cleanup_path /opt/ghc
cleanup_path /opt/hostedtoolcache/CodeQL
timeout 120s docker system prune -af || true
echo "Disk usage after cleanup:"
df -h
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 24
- name: Verify lazy Docker asset fetch from built package
run: node --expose-gc node_modules/nx/bin/nx run php-wasm-compile-extension:test-lazy-docker-asset-fetch --output-style=stream
- name: Build and load PHP.wasm extension fixtures
run: node --expose-gc node_modules/nx/bin/nx affected --target=test-compile-extension-integration --parallel=1 --output-style=stream
test-legacy-wp-version-boot:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- name: Install Playwright Browser
run: npx playwright install chromium --with-deps
- name: Start dev server
run: |
npm run dev > /tmp/playground-dev.log 2>&1 &
timeout=120; elapsed=0
until curl -s -o /dev/null http://127.0.0.1:5400/website-server/ 2>/dev/null; do
sleep 3
elapsed=$((elapsed + 3))
if [ $elapsed -ge $timeout ]; then
echo "Dev server failed to start within ${timeout}s"
cat /tmp/playground-dev.log | tail -50
exit 1
fi
done
- name: Test legacy WordPress version boot
run: node packages/playground/wordpress/tests/test-legacy-wp-version-boot.mjs
# Redis extension tests - verifies the php-redis extension loads
# and provides the expected API, and can connect to a real Redis server.
# Redis requires JSPI because asyncify cannot properly handle exceptions
# during network I/O. Attempting to load Redis with asyncify throws an error.
test-redis-extension:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
services:
redis:
image: redis:7-alpine
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 24
- name: Run Redis extension tests (JSPI)
run: node --expose-gc node_modules/nx/bin/nx run php-wasm-node:test-redis-extension-jspi
env:
REDIS_HOST: 127.0.0.1
REDIS_PORT: 6379
- name: Run Redis network tests (JSPI)
run: node --expose-gc node_modules/nx/bin/nx run php-wasm-node:test-redis-network-jspi
env:
REDIS_HOST: 127.0.0.1
REDIS_PORT: 6379
# Memcached extension tests - verifies the php-memcached extension loads
# and provides the expected API, and can connect to a real memcached server.
test-memcached-extension:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
services:
memcached:
image: memcached:1.6-alpine
ports:
- 11211:11211
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 24
- name: Run memcached extension tests
run: node --expose-gc node_modules/nx/bin/nx run php-wasm-node:test-memcached-extension-jspi
- name: Run memcached network tests
run: node --expose-gc node_modules/nx/bin/nx run php-wasm-node:test-memcached-network-jspi
env:
MEMCACHED_HOST: 127.0.0.1
MEMCACHED_PORT: 11211
build:
if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read # Required to clone the repo.
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
with:
node-version: 20
- run: |
if ADDITIONAL_REMOTE_ORIGINS=invalid-origin npx nx build playground-client; then
echo "The Playground client build should have failed due to an invalid additional origin."
echo "The build does not appear to be applying ADDITIONAL_REMOTE_ORIGINS."
exit 1
fi
npx nx affected --target=build --parallel=3 --verbose
- name: Verify npm pack works (catches override conflicts before publish)
run: npm pack --dry-run --workspace=packages/php-wasm/logger
# Deploy documentation job
deploy_docs:
# Only deploy docs when pushing to the WordPress/wordpress-playground repository
if: >
github.repository == 'WordPress/wordpress-playground' &&
github.ref == 'refs/heads/trunk' &&
github.event_name == 'push'
# Add a dependency to the build job
needs: [test-unit-asyncify, test-e2e, test-e2e-components, build]
name: 'Deploy doc site'
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
contents: read # Required to clone the repo.
pages: write # Required to deploy to GitHub Pages.
id-token: write # Required to verify the deployment originates from an appropriate source.
# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
# Specify runner + deployment step
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- run: npm run build:docs
- uses: actions/upload-pages-artifact@v3
with: { path: dist/docs/build }
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4