forked from WordPress/gutenberg
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4782b48
commit c6961a6
Showing
2 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
/** | ||
* Based on: | ||
* https://github.com/Automattic/themes/blob/a0c9b91f827f46ed60c502d41ef881b2f0552f03/.github/scripts/create-preview-links.js | ||
*/ | ||
|
||
/* | ||
* This function creates the URL where to download the built & zipped plugin. | ||
* | ||
* @param {object} context - The context of the event that triggered the action. | ||
* @param {number} number - The PR number where the plugin changes are located. | ||
* @returns {string} - The URL where to download the built & zipped plugin, as an artifact of the workflow. | ||
*/ | ||
function createBlueprintUrl( context, number ) { | ||
const { repo, owner } = context; | ||
const workflow = encodeURI( 'Build Gutenberg Plugin Zip' ); | ||
const artifact = 'gutenberg-plugin-pr'; | ||
const proxy = '/plugin-proxy.php'; | ||
|
||
return `${ proxy }/?org=${ owner }&repo=${ repo }&workflow=${ workflow }&artifact=${ artifact }&pr=${ number }`; | ||
} | ||
|
||
/* | ||
* This function creates a WordPress Playground blueprint JSON string for a given PR of the Gutenberg plugin. | ||
* | ||
* @param {object} context - The context of the event that triggered the action. | ||
* @param {number} number - The PR number where the plugin changes are located. | ||
* @param {string} zipArtifactUrl - The URL where to download the built & zipped plugin, as an artifact of the workflow. | ||
* @returns {string} - A JSON string representing the steps of a blueprint. | ||
*/ | ||
function createBlueprint( context, number, zipArtifactUrl ) { | ||
const { repo, owner } = context; | ||
|
||
// TODO | ||
// Verify that the PR exists and that GitHub CI finished building it | ||
// ... | ||
|
||
const template = { | ||
landingPage: '/wp-admin/post-new.php?post_type=post', | ||
preferredVersions: { | ||
php: '8.3', | ||
wp: 'latest', | ||
}, | ||
phpExtensionBundles: [ 'kitchen-sink' ], | ||
features: { | ||
networking: true, | ||
}, | ||
steps: [ | ||
{ | ||
step: 'enableMultisite', | ||
}, | ||
{ | ||
step: 'login', | ||
username: 'admin', | ||
password: 'password', | ||
}, | ||
{ | ||
step: 'setSiteOptions', | ||
options: { | ||
blogname: `${ owner }/${ repo } PR #${ number }`, | ||
blogdescription: `Testing pull_request #${ number } with Playground`, | ||
}, | ||
}, | ||
{ | ||
step: 'mkdir', | ||
path: '/wordpress/pr', | ||
}, | ||
/* | ||
* This is the most important step. | ||
* It download the built plugin zip file exposed by GitHub CI. | ||
* | ||
* Because the zip file is not publicly accessible, we use the | ||
* plugin-proxy API endpoint to download it. The source code of | ||
* that endpoint is available at: | ||
* https://github.com/WordPress/wordpress-playground/blob/trunk/packages/playground/website/public/plugin-proxy.php | ||
*/ | ||
{ | ||
step: 'writeFile', | ||
path: '/wordpress/pr/pr.zip', | ||
data: { | ||
resource: 'url', | ||
url: zipArtifactUrl, | ||
caption: `Downloading ${ owner }/${ repo } PR #${ number }`, | ||
}, | ||
progress: { | ||
weight: 2, | ||
caption: `Applying ${ owner }/${ repo } PR #${ number }`, | ||
}, | ||
}, | ||
/** | ||
* GitHub CI artifacts are doubly zipped: | ||
* | ||
* pr.zip | ||
* gutenberg-plugin.zip | ||
* gutenberg/ | ||
* gutenberg.php | ||
* ... other files ... | ||
* | ||
* This step extracts the inner zip file so that we get | ||
* access directly to gutenberg.zip and can use it to | ||
* install the plugin. | ||
*/ | ||
{ | ||
step: 'unzip', | ||
zipPath: '/wordpress/pr/pr.zip', | ||
extractToPath: '/wordpress/pr', | ||
}, | ||
{ | ||
step: 'installPlugin', | ||
pluginZipFile: { | ||
resource: 'vfs', | ||
path: '/wordpress/pr/gutenberg-plugin.zip', | ||
}, | ||
}, | ||
], | ||
}; | ||
|
||
return JSON.stringify( template ); | ||
} | ||
|
||
/* | ||
* This function creates a comment on a PR with preview links. | ||
* | ||
* It is used by `playground-preview` workflow. | ||
* | ||
* @param {object} github - An authenticated instance of the GitHub API. | ||
* @param {object} context - The context of the event that triggered the action. | ||
*/ | ||
async function createPreviewLinksComment( github, context ) { | ||
const zipArtifactUrl = createBlueprintUrl( | ||
context.repo, | ||
context.payload.pull_request.number | ||
); | ||
const blueprint = encodeURI( | ||
createBlueprint( | ||
context.repo, | ||
context.payload.pull_request.number, | ||
zipArtifactUrl | ||
) | ||
); | ||
const prText = `for PR#${ context.payload.pull_request.number }`; | ||
const playgrounds = [ | ||
{ | ||
name: '**Normal** WordPress playground ' + prText, | ||
url: 'https://playground.wordpress.net/#', | ||
}, | ||
{ | ||
name: '**Seamless** WordPress playground ' + prText, | ||
url: 'https://playground.wordpress.net/?mode=seamless#', | ||
}, | ||
{ | ||
name: 'WordPress playground **Builder** ' + prText, | ||
url: 'https://playground.wordpress.net/builder/builder.html#', | ||
}, | ||
]; | ||
const links = playgrounds.map( ( playground ) => ( { | ||
title: playground.name, | ||
url: playground.url + blueprint, | ||
} ) ); | ||
const previewLinks = links.map( | ||
( link ) => `- [${ link.title }](${ link.url })\n` | ||
); | ||
const title = '### Preview changes with Playground'; | ||
const comment = ` | ||
You can preview the least recent changes ${ prText } by following one of the links below: | ||
${ previewLinks.join( ' ' ) } | ||
- [Download <code>.zip</code> with build changes](${ zipArtifactUrl }) | ||
**⚠️ Note:** The preview sites are created using [WordPress Playground](https://wordpress.org/playground/). You can add content, edit settings, and test the themes as you would on a real site, but please note that changes are not saved between sessions. | ||
`; | ||
|
||
const repoData = { | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
}; | ||
|
||
// Check if a comment already exists and update it if it does | ||
const { data: comments } = await github.rest.issues.listComments( { | ||
issue_number: context.payload.pull_request.number, | ||
...repoData, | ||
} ); | ||
const existingComment = comments.find( | ||
( comment ) => | ||
comment.user.login === 'github-actions[bot]' && | ||
comment.body.startsWith( title ) | ||
); | ||
const commentObject = { | ||
body: `${ title }\n${ comment }`, | ||
...repoData, | ||
}; | ||
|
||
if ( existingComment ) { | ||
// Do not update, but delete and recreate Comment to have a new one after last commit. | ||
await github.rest.issues.deleteComment( { | ||
comment_id: existingComment.id, | ||
...commentObject, | ||
} ); | ||
} | ||
|
||
// Create a new comment if one doesn't exist | ||
github.rest.issues.createComment( { | ||
issue_number: context.payload.pull_request.number, | ||
...commentObject, | ||
} ); | ||
} | ||
|
||
module.exports = createPreviewLinksComment; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# For now (!) the name here is important and should not be changed! | ||
# | ||
# The plugin-proxy.php does a check against exact this workflow name. | ||
name: Playground Preview | ||
|
||
# Inspired by, but not based on https://github.com/WordPress/gutenberg/blob/b89fb7b6eaf619bde0269e2a7fbf6245822f6cbf/.github/workflows/build-plugin-zip.yml#L153 | ||
|
||
on: | ||
# What and Why pull_request_target? | ||
# | ||
# The GitHub Actions built in environment variables and Context | ||
# of pull_request_target event are different from those of pull_request event. | ||
# | ||
# For example, the following environment variables and context are different. | ||
# | ||
# - event_name, GITHUB_EVENT_NAME | ||
# - ref, GITHUB_REF | ||
# - sha, GITHUB_SHA | ||
# - ref_name, GITHUB_REF_NAME | ||
# | ||
# @source https://dev.to/suzukishunsuke/secure-github-actions-by-pullrequesttarget-641#modify-workflows-for-pullrequesttarget | ||
|
||
pull_request_target: | ||
types: [opened, synchronize] | ||
paths: | ||
- 'lib/**' | ||
- 'packages/**' | ||
- 'patches/**' | ||
- '**.php' | ||
|
||
# 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_target' && github.head_ref || github.sha }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
zip: | ||
name: Build Gutenberg plugin & upload as zipped artifact | ||
runs-on: ubuntu-latest | ||
steps: | ||
# To checkout the merged commit with actions/checkout on pull_request_target event, | ||
# you need to get the pull request by GitHub API | ||
# and set the merge commit hash to actions/checkout input ref. | ||
# | ||
# @source https://dev.to/suzukishunsuke/secure-github-actions-by-pullrequesttarget-641#checkout-merge-commits | ||
- uses: suzuki-shunsuke/get-pr-action@v0.1.0 | ||
id: pr | ||
|
||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ steps.pr.outputs.merge_commit_sha }} | ||
show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} | ||
|
||
- name: Setup PHP | ||
uses: shivammathur/setup-php@v2 | ||
with: | ||
php-version: latest | ||
coverage: none | ||
tools: wp-cli | ||
|
||
- name: Install latest version of dist-archive-command | ||
run: wp package install wp-cli/dist-archive-command:dev-main | ||
|
||
- name: Setup Node | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version-file: '.nvmrc' | ||
# Enable built-in functionality for caching and restoring dependencies, which is disabled by default. | ||
# The actions/setup-node uses actions/cache under the hood. | ||
# https://github.com/actions/setup-node#caching-global-packages-data | ||
cache: 'npm' | ||
|
||
- name: Npm install | ||
# A "full" install is executed, since `npm ci` does not always exit | ||
# with an error status code if the lock file is inaccurate. This also | ||
# helps to catch dependencies not being installed with exact version. | ||
# | ||
# See: https://github.com/WordPress/gutenberg/issues/16157 | ||
# See: https://github.com/WordPress/gutenberg/pull/39865 | ||
run: npm install | ||
|
||
- name: Build plugin | ||
# - [Incorrect version number used when creating zip archive · Issue #92 · wp-cli/dist-archive-command](https://github.com/wp-cli/dist-archive-command/issues/92) | ||
run: | | ||
npm run build | ||
wp dist-archive . ./${{ github.event.repository.name }}.zip | ||
- name: Upload artifact | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ github.event.repository.name }}-pr | ||
path: ./${{ github.event.repository.name }}.zip | ||
|
||
comment: | ||
name: Comment with playground link | ||
needs: zip # Ensure this runs after zip job. | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Add Preview Links comment | ||
id: comment-on-pr | ||
uses: actions/github-script@v7 | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
script: | | ||
const createPreviewLinks = require('.github/scripts/create-preview-links'); | ||
createPreviewLinks(github, context); |