Cuando alguien abre un PR en un plugin de WordPress, el proceso habitual para revisarlo implica descargar la rama, instalarla en local, activar el plugin y probar los cambios a mano. Eso tiene fricciones: hay que tener un entorno local preparado y dedicar tiempo a instalar algo que igual está roto a medias. Si el revisor no es desarrollador, directamente no puede.
Con este setup, el propio PR genera un enlace que abre el plugin funcionando en el navegador. Un clic, y ya está probando.
¿Qué es WordPress Playground?
WordPress Playground es un entorno de WordPress que corre completamente en el navegador, sin servidor. Usa WebAssembly (WASM) para ejecutar PHP directamente en el cliente. No necesitas Docker, XAMPP, ni nada instalado en local.
Cualquier persona puede abrir una URL y tener un WordPress funcional en segundos, con el plugin instalado y activado. Cuando cierra la pestaña, todo desaparece. Sin rastro, sin instalaciones, sin conflictos.
Esto lo hace perfecto para revisiones de código, demos rápidas y pruebas de plugins sin comprometer ningún entorno real.
Cómo funciona el sistema completo
Son tres piezas que encajan juntas:
- build-dist.yml — se ejecuta en cada push. Instala las dependencias de Composer sin
--dev, genera unblueprint.jsonapuntando a esa rama concreta, y hace un push forzado a una ramadist/nombre-rama. También elimina la rama dist cuando se elimina la original. - playground-preview.yml — se ejecuta cuando se abre, reabre o actualiza un PR. Construye la URL de Playground con el blueprint de la rama dist y publica o actualiza un comentario en el PR. Usa un marcador HTML para no duplicar comentarios.
- pr-blueprint.json — plantilla del blueprint para revisar el trunk manualmente, sin abrir un PR. Define la página de aterrizaje dentro de wp-admin, hace login automático como admin, instala el plugin desde la URL del zip y lo activa.
Guía paso a paso
1. Crea la estructura de carpetas
Necesitas dos carpetas en la raíz del repositorio: .github/workflows/ para los workflows y .github/ para el blueprint.
2. Añade build-dist.yml
Este workflow hace tres cosas: instala dependencias, genera el blueprint con la rama correcta, y hace push a la rama dist. Ajusta la landingPage y el nombre del plugin en la sección de generación del blueprint.
name: Build dist branch
on:
push:
branches:
- '**'
delete:
permissions:
contents: write
jobs:
build:
if: github.event_name == 'push' && !startsWith(github.ref_name, 'dist/')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer
- name: Install production dependencies
run: composer install --no-dev --optimize-autoloader
- name: Generate Playground blueprint
env:
BRANCH_NAME: ${{ github.ref_name }}
run: |
mkdir -p .wordpress-playground
cat > .github/pr-blueprint.json << EOF
{
"\$schema": "https://playground.wordpress.net/blueprint-schema.json",
"landingPage": "/wp-admin/options-general.php?page=tu-plugin",
"steps": [
{
"step": "login",
"username": "admin",
"password": "password"
},
{
"step": "installPlugin",
"pluginZipFile": {
"resource": "url",
"url": "https://github.com/tu-org/tu-plugin/archive/refs/heads/dist/${BRANCH_NAME}.zip"
},
"options": { "activate": true }
}
]
}
EOF
- name: Push to dist branch
env:
BRANCH_NAME: ${{ github.ref_name }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -f vendor/ .wordpress-playground/
git diff --cached --quiet || git commit -m "Build: add vendor and playground blueprint"
git push origin HEAD:dist/${BRANCH_NAME} --force
delete-dist:
if: github.event_name == 'delete' && github.event.ref_type == 'branch' && !startsWith(github.event.ref, 'dist/')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Delete dist branch
env:
BRANCH_NAME: ${{ github.event.ref }}
run: |
git push origin ":refs/heads/dist/${BRANCH_NAME}" || true3. Añade playground-preview.yml
Este workflow publica el comentario en el PR. El marcador HTML evita que se creen comentarios duplicados en cada push. Cámbialo por el nombre de tu plugin.
name: Playground PR Preview
on:
pull_request:
types: [opened, reopened, synchronize]
permissions:
issues: write
pull-requests: write
jobs:
playground-preview:
name: Comment with Playground preview link
runs-on: ubuntu-latest
steps:
- name: Post Playground preview comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const marker = '<!-- tu-plugin-playground-preview -->';
const issue_number = context.payload.pull_request.number;
const branchName = context.payload.pull_request.head.ref;
const owner = context.repo.owner;
const repo = context.repo.repo;
const blueprintUrl = `https://raw.githubusercontent.com/${owner}/${repo}/dist/${branchName}/.wordpress-playground/blueprint.json`;
const playgroundUrl = `https://playground.wordpress.net/?blueprint-url=${encodeURIComponent(blueprintUrl)}`;
const body = [
marker,
'## Test in WordPress Playground',
`[**Open PR #${issue_number} in Playground ↗**](${playgroundUrl})`,
'> El enlace se activa cuando termina el workflow **Build dist branch**.',
'- Login: `admin` / `password`',
'- El plugin se instala y activa automáticamente.',
].join('\n');
const comments = await github.paginate(
github.rest.issues.listComments,
{ owner, repo, issue_number, per_page: 100 }
);
const existing = comments.find(c => c.body?.includes(marker));
if (existing) {
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
} else {
await github.rest.issues.createComment({ owner, repo, issue_number, body });
}4. Verifica los permisos del workflow
En build-dist.yml ya viene permissions: contents: write. En playground-preview.yml necesitas issues: write y pull-requests: write. Si tu repo tiene las Actions con permisos restringidos por defecto, revísalo en Settings → Actions → General → Workflow permissions.
5. Haz el primer push y verifica
Empuja cualquier rama, ve a Actions y comprueba que el workflow Build dist branch acaba en verde. En las ramas del repo debería aparecer dist/nombre-de-tu-rama con el vendor y el blueprint dentro.
6. Abre un PR y espera el comentario automático
Al abrir el PR se ejecuta el workflow Playground PR Preview. En unos segundos verás un comentario con el enlace directo a Playground con el plugin instalado, login hecho como admin y la página de ajustes abierta.
Personalizar el blueprint
El blueprint es un JSON que Playground interpreta. Puedes añadir más pasos según lo que necesite tu plugin.
Instalar un plugin de dependencia
{
"step": "installPlugin",
"pluginZipFile": {
"resource": "wordpress.org/plugins",
"slug": "woocommerce"
},
"options": { "activate": true }
}Crear datos de prueba con WP-CLI
{
"step": "wp-cli",
"command": "wp post create --post_title='Producto de prueba' --post_status=publish"
}Fijar versión de WordPress o PHP
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"preferredVersions": {
"php": "8.1",
"wp": "6.4"
}
}Notas importantes
El vendor de Composer se registra en la rama dist con git add -f vendor/. Es intencionado: Playground descarga el zip de esa rama y necesita todas las dependencias incluidas. No entra en conflicto con tu .gitignore porque solo ocurre en la rama dist.
El build es forzado (--force), así que la rama dist siempre refleja el estado actual. No hay historial acumulado.
Si un PR recibe varios pushes seguidos, el workflow actualiza el mismo comentario en lugar de crear uno nuevo. Eso lo controla el marcador HTML. Cámbialo por algo único para tu plugin para evitar colisiones si tienes varios repos con el mismo setup.