CI - Perf #135
This file contains hidden or 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: 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}" |