Skip to content

Performance Comment #303

Performance Comment

Performance Comment #303

name: Performance Comment
# Posts the perf comparison as a sticky PR comment.
#
# This runs in the *base* repository's context via `workflow_run`, which
# means it has a writable `GITHUB_TOKEN` even for pull requests opened from
# forks. The Performance workflow itself runs in the (potentially untrusted)
# PR context and only produces an artifact — no PR write permissions there.
#
# Security model:
# * The artifact from the PR-context workflow is treated as untrusted
# input. We only consume the JSON benchmark outputs (`base.json` /
# `pr.json`) and the PR number, and we regenerate `report.md` here
# using the base repository's checked-out `perf.compare` so the
# markdown posted under the writable token is never attacker-supplied.
# * The PR number is validated as a positive integer before being used.
on:
workflow_run:
workflows: ["Performance"]
types:
- completed
permissions:
contents: read
pull-requests: write
actions: read
jobs:
comment:
name: Post sticky PR comment
runs-on: ubuntu-latest
if: github.event.workflow_run.event == 'pull_request'
steps:
- name: Check out base repository (trusted)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download perf-results artifact
id: download
# Don't fail this job if the upstream Performance run was cancelled
# or failed before producing the artifact — we just skip posting.
continue-on-error: true
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: perf-results
path: perf-results
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Resolve PR number
id: pr
if: steps.download.outcome == 'success'
run: |
set -euo pipefail
pr=""
if [ -f perf-results/pr-number.txt ]; then
pr="$(tr -d '[:space:]' < perf-results/pr-number.txt)"
fi
if ! [[ "$pr" =~ ^[1-9][0-9]*$ ]]; then
echo "pr-number.txt missing or not a positive integer (got: '${pr}'); skipping comment." >&2
echo "number=" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "number=$pr" >> "$GITHUB_OUTPUT"
- name: Set up Python
if: steps.pr.outputs.number != ''
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Regenerate report from JSON (trusted code)
id: report
if: steps.pr.outputs.number != ''
run: |
set -euo pipefail
if [ ! -s perf-results/base.json ] || [ ! -s perf-results/pr.json ]; then
echo "base.json or pr.json missing from artifact; skipping comment." >&2
echo "found=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Use the base repo's perf.compare (trusted) to render the markdown
# from the PR-supplied JSON data, so we never post attacker-supplied
# markdown under the base repo's writable token.
python -m perf.compare \
--baseline perf-results/base.json \
--candidate perf-results/pr.json \
--threshold "${PERF_REGRESSION_THRESHOLD:-15}" \
--output report.md \
|| true
if [ -s report.md ]; then
echo "found=true" >> "$GITHUB_OUTPUT"
else
echo "found=false" >> "$GITHUB_OUTPUT"
echo "report.md was not produced; skipping comment." >&2
fi
- name: Post sticky PR comment
if: steps.pr.outputs.number != '' && steps.report.outputs.found == 'true'
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
with:
header: perf-comparison
number: ${{ steps.pr.outputs.number }}
path: report.md