Skip to content

Post Playground link to PR #269

Post Playground link to PR

Post Playground link to PR #269

Workflow file for this run

name: Post Playground link to PR
on:
pull_request_target:
types: [labeled]
workflow_run:
workflows: ["WebAssembly"]
types: [completed]
jobs:
post-summary:
name: Post Playground link
runs-on: ubuntu-latest
permissions:
pull-requests: write
# Post a comment only if the PR status check is passed and the PR is labeled with `Playground`.
# Triggered twice: when the PR is labeled and when PR build is passed.
if: >-
${{ false
|| (true
&& github.event_name == 'pull_request_target'
&& contains(github.event.pull_request.labels.*.name, 'Playground'))
|| (true
&& github.event_name == 'workflow_run'
&& github.event.workflow_run.conclusion == 'success'
&& github.event.workflow_run.event == 'pull_request')
}}
steps:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs/promises');
const buildWorkflowPath = '.github/workflows/wasm.yml';
const findSuccessfuBuildRun = async (pr) => {
const opts = github.rest.actions.listWorkflowRunsForRepo.endpoint.merge({
owner: context.repo.owner,
repo: context.repo.repo,
status: 'success',
branch: pr.head.ref,
});
const runs = await github.paginate(opts);
const buildRun = runs.find(run => run.path == buildWorkflowPath);
return buildRun;
}
const postComment = async (body, pr) => {
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
});
const commentOpts = { owner: context.repo.owner, repo: context.repo.repo, body: comment };
const existingComment = comments.find(comment => comment.body.startsWith(magicComment));
if (existingComment) {
core.info(`Updating existing comment: ${existingComment.html_url}`);
await github.rest.issues.updateComment({
...commentOpts, comment_id: existingComment.id
});
} else {
await github.rest.issues.createComment({
...commentOpts, issue_number: pr.number
});
}
}
const derivePRNumber = async () => {
if (context.payload.pull_request) {
return context.payload.pull_request.number;
}
// Workaround for https://github.com/orgs/community/discussions/25220
const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const artifact = artifacts.find(artifact => artifact.name == 'github-pr-info');
if (!artifact) {
throw new Error('Cannot find github-pr-info.txt artifact');
}
const { data } = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
await fs.writeFile('pr-info.zip', Buffer.from(data));
await exec.exec('unzip', ['pr-info.zip']);
return await fs.readFile('github-pr-info.txt', 'utf8');
}
const prNumber = await derivePRNumber();
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
core.info(`Checking if the PR ${prNumber} is labeled with Playground...`);
if (!pr.labels.some(label => label.name == 'Playground')) {
core.info(`The PR is not labeled with Playground.`);
return;
}
core.info(`Checking if the build is successful for ${pr.head.ref} in ${pr.head.repo.owner.login}/${pr.head.repo.name}...`);
const buildRun = await findSuccessfuBuildRun(pr);
if (!buildRun) {
core.info(`No successful build run found for ${buildWorkflowPath} on ${pr.head.ref} yet.`);
return;
}
core.info(`Found a successful build run: ${buildRun.html_url}`);
const runLink = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
const magicComment = `<!-- AUTO-GENERATED-COMMENT-PR-PLAYGROUND -->`;
const comment = `${magicComment}
**Try on Playground**: https://ruby.github.io/play-ruby?run=${buildRun.id}
This is an automated comment by [\`pr-playground.yml\`](${runLink}) workflow.
`;
core.info(`Comment: ${comment}`);
await postComment(comment, pr);