Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/build-plugin-zip.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Build Plugin Zip

on:
pull_request:
types: [ 'opened', 'synchronize', 'reopened', 'edited' ]

# Cancels all previous workflow runs for pull requests that have not completed.
concurrency:
# The concurrency group contains the workflow name and the branch name for pull requests
# or the commit hash for any other events.
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
cancel-in-progress: true

# Disable permissions for all available scopes by default.
# Any needed permissions should be configured at the job level.
permissions: {}

jobs:
build:
runs-on: 'ubuntu-24.04'
permissions:
contents: read
outputs:
job_status: ${{ job.status }}

steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Set up PHP and Composer
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
coverage: none
tools: composer:v2

- name: Setup Node
uses: actions/setup-node@v5
with:
node-version-file: '.nvmrc'
cache: 'npm'

- name: Install NPM dependencies
run: npm ci

- name: Install Composer dependencies
run: composer install --no-dev --no-interaction

- name: Build plugin
run: npm run build

- name: Create artifact
run: |
mv dist two-factor
zip -r two-factor.zip two-factor/

- name: Upload artifact
uses: actions/upload-artifact@v6
with:
name: two-factor-plugin-zip-pr${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}
path: two-factor.zip
if-no-files-found: error
117 changes: 117 additions & 0 deletions .github/workflows/pr-playground-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: PR Playground Preview

# Use workflow_run for privileged operations
# Runs with write permissions and access to secrets
# Operates on artifacts from the unprivileged build workflow
on:
workflow_run:
workflows: ["Build Plugin Zip"]
types:
- completed

# Disable permissions for all available scopes by default.
# Any needed permissions should be configured at the job level.
permissions: {}

jobs:

# Leaves a comment on a pull request with a link to test the changes in a WordPress Playground instance.
playground-details:
name: Comment on a pull request with Playground details
runs-on: ubuntu-24.04
# Only run if the build workflow succeeded and was triggered by a pull_request
if: >
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'success'
outputs:
artifact-url: ${{ steps.expose.outputs.artifact-url }}
artifact-name: ${{ steps.expose.outputs.artifact-name }}
permissions:
contents: write
pull-requests: write

steps:
- name: Extract PR metadata from artifact name
id: pr-metadata
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});

const artifact = artifacts.data.artifacts.find(a =>
a.name.startsWith("two-factor-plugin-zip-pr")
);

if (!artifact) {
throw new Error('Could not find plugin artifact');
}

// Parse: two-factor-plugin-zip-pr123-abc123def...
const match = artifact.name.match(/^two-factor-plugin-zip-pr(\d+)-(.+)$/);
if (!match) {
throw new Error(`Could not parse artifact name: ${artifact.name}`);
}

const [, prNumber, commitSha] = match;

core.setOutput('pr-number', prNumber);
core.setOutput('commit-sha', commitSha);
core.setOutput('artifact-name', artifact.name);

- name: Expose built artifact
id: expose
uses: WordPress/action-wp-playground-pr-preview/.github/actions/expose-artifact-on-public-url@c8607529dac8d2bf9a1e8493865fc97cd1c3c87b # v2
with:
artifact-name: ${{ steps.pr-metadata.outputs.artifact-name }}
artifact-filename: two-factor.zip
pr-number: ${{ steps.pr-metadata.outputs.pr-number }}
commit-sha: ${{ steps.pr-metadata.outputs.commit-sha }}
artifact-source-run-id: ${{ github.event.workflow_run.id }}
artifacts-to-keep: '2'

- name: Generate Playground blueprint JSON
id: blueprint
run: |
node - <<'NODE' >> "$GITHUB_OUTPUT"
const url = process.env.ARTIFACT_URL;
if (!url) {
throw new Error('ARTIFACT_URL is required');
}

const blueprint = {
landingPage: '/wp-admin/profile.php#two-factor-options',
preferredVersions: {
php: '8.2',
wp: 'latest',
},
steps: [
{
step: 'installPlugin',
pluginZipFile: {
resource: 'url',
url,
},
},
{
step: 'login',
username: 'admin',
},
],
};

console.log(`blueprint=${JSON.stringify(blueprint)}`);
NODE
env:
ARTIFACT_URL: ${{ steps.expose.outputs.artifact-url }}

- name: Post Playground preview button
uses: WordPress/action-wp-playground-pr-preview@c8607529dac8d2bf9a1e8493865fc97cd1c3c87b # v2
with:
mode: append-to-description
blueprint: ${{ steps.blueprint.outputs.blueprint }}
pr-number: ${{ steps.pr-metadata.outputs.pr-number }}
github-token: ${{ secrets.GITHUB_TOKEN }}
Loading