ci(benchmarks): surface the gate table as a sticky PR comment #2
Workflow file for this run
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: benchmarks | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: {} | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| concurrency: | |
| group: benchmarks-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| jobs: | |
| bench: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: extractions/setup-just@v4 | |
| - uses: astral-sh/setup-uv@v8.2.0 | |
| # uv.lock is git-ignored (repo convention), so a clean checkout lacks it. | |
| # `just bench-report` builds the compose `application` image, whose Dockerfile | |
| # does `COPY uv.lock` + `uv sync --frozen`; regenerate the lock first. | |
| - run: uv lock | |
| - name: Run the gate and capture the markdown report | |
| shell: bash | |
| run: | | |
| # `docker compose run` leaks buildkit image-build output onto stdout in | |
| # CI, so a naive capture mixes it into the comment. The report always | |
| # begins with the `## Benchmark gate` sentinel and the container prints | |
| # it last, so slice from that heading to EOF -- independent of how | |
| # compose routes its own noise. Own the exit code manually: `set +e` | |
| # (shell: bash runs with -e) so a failing gate still lets us post the | |
| # report, then re-exit with the gate's status so the build still fails. | |
| set +e | |
| just bench-report > "$RUNNER_TEMP/raw.log" | |
| status=$? | |
| sed -n '/^## Benchmark gate/,$p' "$RUNNER_TEMP/raw.log" \ | |
| | tee "$GITHUB_STEP_SUMMARY" "$RUNNER_TEMP/bench-report.md" | |
| exit "$status" | |
| - name: Comment the report on the PR | |
| # always(): comment even when the gate failed -- that is when it matters most. | |
| # continue-on-error: fork PRs get a read-only token and cannot comment; the | |
| # gate above already decided the build, and the run Summary still has the table. | |
| if: always() && github.event_name == 'pull_request' | |
| continue-on-error: true | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh pr comment "${{ github.event.pull_request.number }}" \ | |
| --edit-last --create-if-none \ | |
| --body-file "$RUNNER_TEMP/bench-report.md" |