Comment build results #1
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
name: Comment build results | |
# We are not using using a single workflow on `pull_request_target`, and have two workflows on `pull_request` -> `workflow_run`: | |
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ | |
on: | |
workflow_run: | |
workflows: | |
- Build types | |
types: | |
- completed | |
jobs: | |
check-current-build: | |
runs-on: ubuntu-latest | |
permissions: | |
actions: read # to list the workflow runs | |
if: >- | |
${{ | |
github.event.workflow_run.event == 'pull_request' && | |
github.event.workflow_run.conclusion == 'success' | |
}} | |
outputs: | |
run-id: ${{ fromJSON(steps.current-workflow-run.outputs.result).id }} | |
steps: | |
- name: Check current types build workflow run | |
id: current-workflow-run | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const { data: { workflow_runs: [workflowRun] } } = await github.rest.actions.listWorkflowRuns({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
branch: 'dev', // TODO: Get the PR target branch to support branches other than dev | |
workflow_id: 'build-types.yml', | |
event: 'push', | |
status: 'success', | |
}); | |
return { | |
id: workflowRun?.id || -1, | |
} | |
comment-build-results: | |
runs-on: ubuntu-latest | |
permissions: | |
actions: read # to download artifacts | |
pull-requests: write # to comment to the PR | |
needs: check-current-build | |
if: ${{ needs.check-current-build.outputs.run-id != -1 }} | |
steps: | |
- name: Download the current types build | |
uses: actions/github-script@v7 | |
env: | |
CURRENT_RUN_ID: ${{ needs.check-current-build.outputs.run-id }} | |
with: | |
script: | | |
const { writeFile, unlink } = require('node:fs/promises'); | |
const { resolve } = require('node:path'); | |
const __dirname = process.env.GITHUB_WORKSPACE; | |
const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
run_id: process.env.CURRENT_RUN_ID, | |
}); | |
const artifact = artifacts.find(({ name }) => name === 'types-build'); | |
const { data: artifactData } = await github.rest.actions.downloadArtifact({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
artifact_id: artifact.id, | |
archive_format: 'zip', | |
}); | |
const zipPath = resolve(__dirname, './current-build.zip'); | |
await writeFile(zipPath, Buffer.from(artifactData)); | |
await exec.exec('unzip', [zipPath, '-d', './current-build']); | |
await unlink(zipPath); | |
- name: Download the PR information artifact | |
id: pr-info | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const { readFile, writeFile, unlink } = require('node:fs/promises'); | |
const { resolve } = require('node:path'); | |
const __dirname = process.env.GITHUB_WORKSPACE; | |
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(({ name }) => name === 'types-build'); | |
const { data: artifactData } = await github.rest.actions.downloadArtifact({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
artifact_id: artifact.id, | |
archive_format: 'zip', | |
}); | |
const zipPath = resolve(__dirname, './pr-info.zip'); | |
await writeFile(zipPath, Buffer.from(artifactData)); | |
await exec.exec('unzip', [zipPath, '-d', './pr-build']); | |
await unlink(zipPath); | |
const prNumberPath = resolve(__dirname, './pr-build/.pr-number'); | |
const prNumberString = await readFile(prNumberPath, { encoding: 'utf-8' }) | |
await unlink(prNumberPath); | |
return { | |
number: Number(prNumberString) | |
} | |
- name: Prepare build results | |
run: | | |
echo "# Build Results" >> build-results.md | |
echo "" >> build-results.md | |
echo "## JSON API" >> build-results.md | |
echo "" >> build-results.md | |
# git diff exits with 1 if there is no diff, which evaluates to true | |
if $(git diff --no-index ./current-build/api ./pr-build/api > ./api.diff); then | |
echo "📜 No changes detected." >> build-results.md | |
else | |
echo "📜 Changes detected:" >> build-results.md | |
echo '```diff' >> build-results.md | |
cat ./api.diff >> build-results.md | |
echo '```' >> build-results.md | |
fi | |
echo "" >> build-results.md | |
echo "## Types" >> build-results.md | |
echo "" >> build-results.md | |
# git diff exits with 1 if there is no diff, which evaluates to true | |
if $(git diff --no-index ./current-build/types ./pr-build/types > ./types.diff); then | |
echo "📜 No changes detected." >> build-results.md | |
else | |
echo "📜 Changes detected:" >> build-results.md | |
echo '```diff' >> build-results.md | |
cat ./types.diff >> build-results.md | |
echo '```' >> build-results.md | |
fi | |
echo "" >> build-results.md | |
- uses: marocchino/sticky-pull-request-comment@v2 | |
with: | |
number: ${{ fromJSON(steps.pr-info.outputs.result).number }} | |
hide_and_recreate: true | |
hide_classify: 'OUTDATED' | |
path: build-results.md | |
- run: cat build-results.md >> $GITHUB_STEP_SUMMARY |