respect-validation/.github/workflows/ci-perf.yml
Alexandre Gomes Gaigalas ad7a74838b Allow panda.yml to request benchmark runs for PRs
This change introduces a new command to `@TheRespectPanda` bot,
allowing him to dispatch the ci-perf.yml workflow benchmarks for
a pull request.

Initially, the bot will just trigger it and return the workflow
run URL for manual inspection. Future iterations on this feature
could then grab the benchmark results and update the comment.
2026-02-24 05:12:58 +00:00

153 lines
No EOL
5.3 KiB
YAML

name: CI - Perf
# EXPERIMENTAL: This workflow is running with --tolerate-failure flag for phpbench
# This is to gather data for a future historical interleaving of performance benchmarks.
on:
# Run once per day no matter what
schedule:
- cron: '0 0 * * *'
# Run on push to main, so we get a data point every merge
push:
branches:
- main
# Allow manual triggering with rebaseline option
workflow_dispatch:
inputs:
baseline:
description: 'Baseline mode. latest: compare against latest benchmarks; rebaseline: store new baseline.'
type: choice
default: 'latest'
options:
- 'latest'
- 'rebaseline'
pull:
description: 'Pull request number to benchmark (optional)'
required: false
jobs:
pr-benchmarks:
name: PR Benchmarks
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.pull }}
runs-on: ubuntu-latest
env:
BENCHMARK_SHA: ${{ github.sha }}
permissions:
contents: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Checkout PR head
run: |
set -euo pipefail
PR=${{ github.event.inputs.pull }}
# Validate that PR is numeric to avoid injection or unexpected ref resolution
if ! printf '%s\n' "$PR" | grep -Eq '^[0-9]+$'; then
echo "Invalid pull request number: '$PR'. Expected a numeric value." >&2
exit 1
fi
# fetch the pull request head (works for forks)
git fetch origin "pull/${PR}/head:pr-${PR}" || git fetch origin "+refs/pull/${PR}/head:pr-${PR}"
git checkout "pr-${PR}"
echo "Checked out PR #${PR}"
echo "BENCHMARK_SHA=$(git rev-parse --verify HEAD)" >> "$GITHUB_ENV"
- uses: ./.github/actions/setup-action
with:
extensions: xdebug
- name: Fetch Benchmarks
run: |
git fetch origin benchmarks
mkdir -p .phpbench
git checkout origin/benchmarks -- .phpbench || echo "No previous benchmarks found"
- name: Run Benchmarks
run: |
# Baseline does not exist or rebaseline requested. Generate it.
if [ -z "$(ls -A .phpbench)" ] || [ "${{ github.event.inputs.baseline || 'latest' }}" = "rebaseline" ]; then
vendor/bin/phpbench run --report=aggregate --progress=plain --store --tag=${BENCHMARK_SHA}
# Baseline exists. Compare against it.
else
vendor/bin/phpbench run --report=aggregate --progress=plain --store --tag=${BENCHMARK_SHA} --ref=latest --tolerate-failure
fi
# Generate report for human consumption
vendor/bin/phpbench report --report=aggregate --ref=latest |
tail -n+2 | head -n-2 | tr '+' '|' > report.md
cat report.md > "$GITHUB_STEP_SUMMARY"
historical-benchmarks:
name: Historical Benchmarks
if: >-
github.event_name != 'workflow_dispatch' ||
!github.event.inputs.pull
runs-on: ubuntu-latest
env:
BENCHMARK_SHA: ${{ github.sha }}
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
persist-credentials: true
- uses: ./.github/actions/setup-action
with:
extensions: xdebug
- name: Fetch Benchmarks
run: |
git fetch origin benchmarks
mkdir -p .phpbench
git checkout origin/benchmarks -- .phpbench || echo "No previous benchmarks found"
- name: Run Benchmarks
run: |
# Baseline does not exist or rebaseline requested. Generate it.
if [ -z "$(ls -A .phpbench)" ] || [ "${{ github.event.inputs.baseline || 'latest' }}" = "rebaseline" ]; then
vendor/bin/phpbench run --report=aggregate --progress=plain --store --tag=${BENCHMARK_SHA}
# Baseline exists. Compare against it.
else
vendor/bin/phpbench run --report=aggregate --progress=plain --store --tag=${BENCHMARK_SHA} --ref=latest --tolerate-failure
fi
# Generate report for human consumption
vendor/bin/phpbench report --report=aggregate --ref=latest |
tail -n+2 | head -n-2 | tr '+' '|' > report.md
cat report.md
- name: Commit Results
# only on: main push, schedule, workflow_dispatch+rebaseline
if: >-
(github.ref == 'refs/heads/main' && github.event_name == 'push') ||
(github.event_name == 'schedule') ||
(github.event_name == 'workflow_dispatch' && github.event.inputs.baseline == 'rebaseline')
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout benchmarks
mv -f report.md latest.md
git add .phpbench latest.md
git commit -m "Store benchmark results [skip ci]" || echo "No changes to commit"
git push origin benchmarks
- name: Restore workspace
if: always()
run: |
set -euo pipefail
echo "Restoring workspace to original commit: ${GITHUB_SHA}"
git fetch origin || true
git checkout --detach "${GITHUB_SHA}"
git reset --hard "${GITHUB_SHA}"