From 84070f17036566fa3c2fa6d70aece7f393c5f87a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 10:13:57 +0000 Subject: [PATCH 1/5] Add WordPress Playground preview workflow for pull requests Adds a GitHub Actions workflow that automatically builds the plugin on every PR and posts a one-click Playground preview link as a PR comment. Also includes a blueprint.json with sensible defaults (PHP 8.1, latest WP, Frontblocks + GenerateBlocks pre-installed, block editor as landing page). Closes #131 https://claude.ai/code/session_01FXaWGPwXnqJf4PZWzmvUQv --- .github/workflows/playground-preview.yml | 171 +++++++++++++++++++++++ .wordpress-playground/blueprint.json | 36 +++++ 2 files changed, 207 insertions(+) create mode 100644 .github/workflows/playground-preview.yml create mode 100644 .wordpress-playground/blueprint.json diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml new file mode 100644 index 0000000..42d54a1 --- /dev/null +++ b/.github/workflows/playground-preview.yml @@ -0,0 +1,171 @@ +name: WordPress Playground Preview + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + playground-preview: + name: Generate Playground Preview + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install Node dependencies + run: npm ci + + - name: Build JS assets + run: npm run build + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + extensions: mbstring, xml, zip + + - name: Install Composer dependencies + run: composer install --no-dev --optimize-autoloader --ignore-platform-reqs + + - name: Create plugin ZIP + run: | + mkdir -p /tmp/plugin/frontblocks + rsync -a \ + --exclude='.git' \ + --exclude='node_modules' \ + --exclude='.github' \ + --exclude='.wordpress-playground' \ + --exclude='tests' \ + --exclude='docs' \ + --exclude='*.jsx' \ + --exclude='phpcs.xml.dist' \ + --exclude='phpstan.neon.dist' \ + --exclude='package.json' \ + --exclude='package-lock.json' \ + --exclude='composer.json' \ + --exclude='composer.lock' \ + --exclude='tailwind.config.js' \ + --exclude='postcss.config.js' \ + --exclude='vendor/squizlabs' \ + --exclude='vendor/phpcompatibility' \ + --exclude='vendor/sirbrillig' \ + --exclude='vendor/wp-coding-standards' \ + --exclude='vendor/phpcsstandards' \ + --exclude='vendor/phpunit' \ + --exclude='vendor/yoast' \ + --exclude='vendor/phpstan' \ + --exclude='vendor/szepeviktor' \ + ./ /tmp/plugin/frontblocks/ + cd /tmp/plugin + zip -r frontblocks.zip frontblocks/ + echo "Plugin ZIP size: $(du -sh frontblocks.zip | cut -f1)" + + - name: Upload plugin artifact + uses: actions/upload-artifact@v4 + with: + name: frontblocks-pr-${{ github.event.pull_request.number }}-${{ github.run_id }} + path: /tmp/plugin/frontblocks.zip + retention-days: 7 + + - name: Post Playground preview comment + uses: actions/github-script@v7 + with: + script: | + const prNumber = context.issue.number; + const branch = context.payload.pull_request.head.ref; + const owner = context.repo.owner; + const repo = context.repo.repo; + const runId = context.runId; + + const blueprint = { + "$schema": "https://playground.wordpress.net/blueprint-schema.json", + "landingPage": "/wp-admin/post-new.php", + "login": true, + "preferredVersions": { + "php": "8.1", + "wp": "latest" + }, + "steps": [ + { + "step": "login", + "username": "admin", + "password": "password" + }, + { + "step": "installPlugin", + "pluginZipFile": { + "resource": "url", + "url": `https://github.com/${owner}/${repo}/archive/refs/heads/${branch}.zip` + }, + "options": { + "activate": true + } + }, + { + "step": "installPlugin", + "pluginZipFile": { + "resource": "wordpress.org/plugins", + "slug": "generateblocks" + }, + "options": { + "activate": true + } + } + ] + }; + + const encoded = Buffer.from(JSON.stringify(blueprint)).toString('base64'); + const playgroundUrl = `https://playground.wordpress.net/#${encoded}`; + const artifactUrl = `https://github.com/${owner}/${repo}/actions/runs/${runId}`; + + const body = [ + `## 🎮 WordPress Playground Preview`, + ``, + `A live preview of this pull request is available via **WordPress Playground** — no local setup needed.`, + ``, + `| | |`, + `|---|---|`, + `| **Live preview** | [Open in WordPress Playground ↗](${playgroundUrl}) |`, + `| **Credentials** | Username: \`admin\` · Password: \`password\` |`, + `| **Plugin artifact** | [Download built ZIP ↗](${artifactUrl}) *(GitHub login required · expires in 7 days)* |`, + ``, + `> Installs Frontblocks from branch \`${branch}\` and opens the block editor ready to test.`, + `> GenerateBlocks is also pre-installed to test Accordion compatibility.`, + ``, + `---`, + `*Auto-generated · [View run](${artifactUrl})*` + ].join('\n'); + + // Remove previous bot preview comments to avoid clutter + const { data: comments } = await github.rest.issues.listComments({ + owner, + repo, + issue_number: prNumber + }); + + for (const comment of comments) { + if (comment.user.type === 'Bot' && comment.body.includes('WordPress Playground Preview')) { + await github.rest.issues.deleteComment({ + owner, + repo, + comment_id: comment.id + }); + } + } + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body + }); diff --git a/.wordpress-playground/blueprint.json b/.wordpress-playground/blueprint.json new file mode 100644 index 0000000..82404f6 --- /dev/null +++ b/.wordpress-playground/blueprint.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://playground.wordpress.net/blueprint-schema.json", + "landingPage": "/wp-admin/post-new.php", + "login": true, + "preferredVersions": { + "php": "8.1", + "wp": "latest" + }, + "steps": [ + { + "step": "login", + "username": "admin", + "password": "password" + }, + { + "step": "installPlugin", + "pluginZipFile": { + "resource": "wordpress.org/plugins", + "slug": "frontblocks" + }, + "options": { + "activate": true + } + }, + { + "step": "installPlugin", + "pluginZipFile": { + "resource": "wordpress.org/plugins", + "slug": "generateblocks" + }, + "options": { + "activate": true + } + } + ] +} From a43f14c9e3dea46fd441b4ef183833409ca3fc48 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 10:47:30 +0000 Subject: [PATCH 2/5] Fix: add explicit Composer installer step to playground preview workflow Matches the pattern used in deploy.yml where Composer is installed manually via the official installer script. https://claude.ai/code/session_01FXaWGPwXnqJf4PZWzmvUQv --- .github/workflows/playground-preview.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml index 42d54a1..c565114 100644 --- a/.github/workflows/playground-preview.yml +++ b/.github/workflows/playground-preview.yml @@ -34,6 +34,11 @@ jobs: php-version: '8.1' extensions: mbstring, xml, zip + - name: Install Composer + run: | + curl -sS https://getcomposer.org/installer | php + sudo mv composer.phar /usr/local/bin/composer + - name: Install Composer dependencies run: composer install --no-dev --optimize-autoloader --ignore-platform-reqs From fcf666f85d79a6a38fd24febb2ffd3940a084982 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 10:49:49 +0000 Subject: [PATCH 3/5] Use repository slug dynamically for plugin ZIP name and artifact Replaces hardcoded 'frontblocks' with github.event.repository.name so the ZIP and artifact names always match the repo slug. https://claude.ai/code/session_01FXaWGPwXnqJf4PZWzmvUQv --- .github/workflows/playground-preview.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml index c565114..1cab907 100644 --- a/.github/workflows/playground-preview.yml +++ b/.github/workflows/playground-preview.yml @@ -43,8 +43,10 @@ jobs: run: composer install --no-dev --optimize-autoloader --ignore-platform-reqs - name: Create plugin ZIP + env: + SLUG: ${{ github.event.repository.name }} run: | - mkdir -p /tmp/plugin/frontblocks + mkdir -p /tmp/plugin/$SLUG rsync -a \ --exclude='.git' \ --exclude='node_modules' \ @@ -70,16 +72,16 @@ jobs: --exclude='vendor/yoast' \ --exclude='vendor/phpstan' \ --exclude='vendor/szepeviktor' \ - ./ /tmp/plugin/frontblocks/ + ./ /tmp/plugin/$SLUG/ cd /tmp/plugin - zip -r frontblocks.zip frontblocks/ - echo "Plugin ZIP size: $(du -sh frontblocks.zip | cut -f1)" + zip -r $SLUG.zip $SLUG/ + echo "Plugin ZIP size: $(du -sh $SLUG.zip | cut -f1)" - name: Upload plugin artifact uses: actions/upload-artifact@v4 with: - name: frontblocks-pr-${{ github.event.pull_request.number }}-${{ github.run_id }} - path: /tmp/plugin/frontblocks.zip + name: ${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}-${{ github.run_id }} + path: /tmp/plugin/${{ github.event.repository.name }}.zip retention-days: 7 - name: Post Playground preview comment From 73b595dc85409101bed7b3679059a817ee68fe14 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 10:51:32 +0000 Subject: [PATCH 4/5] Remove auto-generated footer from Playground preview PR comment https://claude.ai/code/session_01FXaWGPwXnqJf4PZWzmvUQv --- .github/workflows/playground-preview.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml index 1cab907..ccd253a 100644 --- a/.github/workflows/playground-preview.yml +++ b/.github/workflows/playground-preview.yml @@ -147,10 +147,7 @@ jobs: `| **Plugin artifact** | [Download built ZIP ↗](${artifactUrl}) *(GitHub login required · expires in 7 days)* |`, ``, `> Installs Frontblocks from branch \`${branch}\` and opens the block editor ready to test.`, - `> GenerateBlocks is also pre-installed to test Accordion compatibility.`, - ``, - `---`, - `*Auto-generated · [View run](${artifactUrl})*` + `> GenerateBlocks is also pre-installed to test Accordion compatibility.` ].join('\n'); // Remove previous bot preview comments to avoid clutter From 32f25defc530a01b747c520427a1ddfa764fccc2 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Apr 2026 10:52:46 +0000 Subject: [PATCH 5/5] Open Playground preview link in a new tab (target="_blank") https://claude.ai/code/session_01FXaWGPwXnqJf4PZWzmvUQv --- .github/workflows/playground-preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml index ccd253a..07beaec 100644 --- a/.github/workflows/playground-preview.yml +++ b/.github/workflows/playground-preview.yml @@ -142,7 +142,7 @@ jobs: ``, `| | |`, `|---|---|`, - `| **Live preview** | [Open in WordPress Playground ↗](${playgroundUrl}) |`, + `| **Live preview** | Open in WordPress Playground ↗ |`, `| **Credentials** | Username: \`admin\` · Password: \`password\` |`, `| **Plugin artifact** | [Download built ZIP ↗](${artifactUrl}) *(GitHub login required · expires in 7 days)* |`, ``,