Support Shadow DOM and iframe element grabbing #964
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: Test Perf | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| test-perf: | |
| runs-on: ubuntu-latest | |
| # PR runs do the bench twice (base ref + HEAD) so the cost roughly | |
| # doubles vs. a push-to-main run. | |
| timeout-minutes: 40 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Install Playwright browsers | |
| run: pnpm --filter react-grab exec playwright install chromium --with-deps | |
| # ─── Baseline run (PR only) ──────────────────────────────────────── | |
| # Swap `packages/react-grab/src/` to the base ref so the same | |
| # bench harness measures the OLD library code. The harness itself | |
| # (`e2e/perf-*.ts`, `scripts/diff-perf-runs.mjs`) and the fixture-app | |
| # stimulus stay at HEAD so the only variable across runs is | |
| # react-grab's source. | |
| - name: Swap react-grab src to base ref | |
| id: swap-base | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| git fetch origin "${{ github.base_ref }}" --depth=1 | |
| if git cat-file -e "origin/${{ github.base_ref }}:packages/react-grab/src" 2>/dev/null; then | |
| git checkout "origin/${{ github.base_ref }}" -- packages/react-grab/src | |
| echo "swapped=true" >> "$GITHUB_OUTPUT" | |
| echo "Swapped react-grab/src to origin/${{ github.base_ref }} ($(git rev-parse "origin/${{ github.base_ref }}"))" | |
| else | |
| echo "Base ref lacks packages/react-grab/src; skipping baseline run." | |
| echo "swapped=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Run perf bench against base ref src | |
| if: github.event_name == 'pull_request' && steps.swap-base.outputs.swapped == 'true' | |
| env: | |
| PERF_LABEL: baseline | |
| # --workers=1 keeps perf measurements off the noise floor that | |
| # the sharded `test-e2e` workflow creates by running 4 workers | |
| # in parallel. Playwright's webServer auto-runs | |
| # `pnpm --filter react-grab build` so the dev server picks up | |
| # whichever src is checked out. | |
| run: pnpm --filter react-grab exec playwright test --grep @perf --workers=1 --reporter=list | |
| - name: Restore react-grab src to HEAD | |
| if: github.event_name == 'pull_request' && steps.swap-base.outputs.swapped == 'true' | |
| run: git checkout HEAD -- packages/react-grab/src | |
| # ─── HEAD run ────────────────────────────────────────────────────── | |
| - name: Run perf bench against HEAD src | |
| env: | |
| PERF_LABEL: current | |
| run: pnpm --filter react-grab exec playwright test --grep @perf --workers=1 --reporter=list | |
| # ─── Diff & surface ──────────────────────────────────────────────── | |
| - name: Compute baseline-vs-current diff | |
| if: always() && github.event_name == 'pull_request' | |
| run: | | |
| node packages/react-grab/scripts/diff-perf-runs.mjs packages/react-grab/perf/baseline packages/react-grab/perf/current | tee perf-diff.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload perf diff | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: perf-diff | |
| path: perf-diff.md | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| - name: Upload perf reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: perf-bench-${{ github.event.pull_request.number || github.sha }} | |
| path: packages/react-grab/perf/ | |
| if-no-files-found: warn | |
| retention-days: 14 | |
| # Separate job so the write-scoped token never coexists with the bench | |
| # job, which builds and executes the PR's own code. This job runs no | |
| # repo code at all — it only downloads the diff artifact and posts it. | |
| # Sticky comment: created once, updated in place on later pushes. | |
| perf-comment: | |
| needs: test-perf | |
| if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: Download perf diff | |
| uses: actions/download-artifact@v4 | |
| continue-on-error: true | |
| with: | |
| name: perf-diff | |
| - name: Post perf diff as PR comment | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { readFileSync } = require("node:fs"); | |
| const marker = "<!-- perf-diff-comment -->"; | |
| let diffBody; | |
| try { | |
| diffBody = readFileSync("perf-diff.md", "utf8").trim(); | |
| } catch { | |
| return; | |
| } | |
| if (!diffBody) return; | |
| const body = `${marker}\n${diffBody}\n\n<sub>Commit ${context.payload.pull_request.head.sha.slice(0, 7)} · full reports in the \`perf-bench-${context.payload.pull_request.number}\` artifact.</sub>`; | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| ...context.repo, | |
| issue_number: context.payload.pull_request.number, | |
| per_page: 100, | |
| }); | |
| const existingComment = comments.find((comment) => comment.body?.startsWith(marker)); | |
| if (existingComment) { | |
| await github.rest.issues.updateComment({ | |
| ...context.repo, | |
| comment_id: existingComment.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| ...context.repo, | |
| issue_number: context.payload.pull_request.number, | |
| body, | |
| }); | |
| } |