diff --git a/.github/workflows/playground-preview.yml b/.github/workflows/playground-preview.yml new file mode 100644 index 0000000..07beaec --- /dev/null +++ b/.github/workflows/playground-preview.yml @@ -0,0 +1,175 @@ +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 + 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 + + - name: Create plugin ZIP + env: + SLUG: ${{ github.event.repository.name }} + run: | + mkdir -p /tmp/plugin/$SLUG + 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/$SLUG/ + cd /tmp/plugin + 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: ${{ 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 + 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 ↗ |`, + `| **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.` + ].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 + } + } + ] +}