106 lines
3.9 KiB
YAML
106 lines
3.9 KiB
YAML
name: Lintcheck summary
|
|
|
|
# The workflow_run event runs in the context of the Clippy repo giving it write
|
|
# access, needed here to create a PR comment when the PR originates from a fork
|
|
#
|
|
# The summary artifact is a JSON file that we verify in this action to prevent
|
|
# the creation of arbitrary comments
|
|
#
|
|
# This action must not checkout/run code from the originating workflow_run
|
|
# or directly interpolate ${{}} untrusted fields into code
|
|
#
|
|
# https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run
|
|
# https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections
|
|
|
|
on:
|
|
workflow_run:
|
|
workflows: [Lintcheck]
|
|
types: [completed]
|
|
|
|
# Restrict the default permission scope https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#defining-access-for-the-github_token-scopes
|
|
permissions:
|
|
pull-requests: write
|
|
|
|
jobs:
|
|
download:
|
|
runs-on: ubuntu-latest
|
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
steps:
|
|
- name: Download artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: summary
|
|
path: untrusted
|
|
run-id: ${{ github.event.workflow_run.id }}
|
|
github-token: ${{ github.token }}
|
|
|
|
- name: Format comment
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const fs = require("fs");
|
|
const assert = require("assert/strict");
|
|
|
|
function validateName(s) {
|
|
assert.match(s, /^[a-z0-9_:]+$/);
|
|
return s;
|
|
}
|
|
|
|
function validateInt(i) {
|
|
assert.ok(Number.isInteger(i));
|
|
return i;
|
|
}
|
|
|
|
function tryReadSummary() {
|
|
try {
|
|
return JSON.parse(fs.readFileSync("untrusted/summary.json"));
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const prNumber = parseInt(fs.readFileSync("untrusted/pr.txt"), 10);
|
|
core.exportVariable("PR", prNumber.toString());
|
|
|
|
const untrustedSummary = tryReadSummary();
|
|
if (!Array.isArray(untrustedSummary)) {
|
|
return;
|
|
}
|
|
|
|
let summary = `Lintcheck changes for ${context.payload.workflow_run.head_sha}
|
|
|
|
| Lint | Added | Removed | Changed |
|
|
| ---- | ----: | ------: | ------: |
|
|
`;
|
|
|
|
for (const untrustedRow of untrustedSummary) {
|
|
const name = validateName(untrustedRow.name);
|
|
|
|
const added = validateInt(untrustedRow.added);
|
|
const removed = validateInt(untrustedRow.removed);
|
|
const changed = validateInt(untrustedRow.changed);
|
|
|
|
const id = name.replace("clippy::", "user-content-").replaceAll("_", "-");
|
|
const url = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${context.payload.workflow_run.id}#${id}`;
|
|
|
|
summary += `| [\`${name}\`](${url}) | ${added} | ${removed} | ${changed} |\n`;
|
|
}
|
|
|
|
summary += "\nThis comment will be updated if you push new changes";
|
|
|
|
fs.writeFileSync("summary.md", summary);
|
|
|
|
- name: Create/update comment
|
|
run: |
|
|
if [[ -f summary.md ]]; then
|
|
gh pr comment "$PR" --body-file summary.md --edit-last --create-if-none
|
|
else
|
|
# There were no changes detected by Lintcheck
|
|
# - If a comment exists from a previous run that did detect changes, edit it (--edit-last)
|
|
# - If no comment exists do not create one, the `gh` command exits with an error which
|
|
# `|| true` ignores
|
|
gh pr comment "$PR" --body "No changes for ${{ github.event.workflow_run.head_sha }}" --edit-last || true
|
|
fi
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
GH_REPO: ${{ github.repository }}
|