feat(debugger): Add event tracing and runtime diagnostics #409
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: Benchmark | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'Picea.Abies/**' | |
| - 'Picea.Abies.UI/**' | |
| - 'Picea.Abies.Benchmark.Wasm/**' | |
| - 'Picea.Abies.Benchmarks/**' | |
| - 'scripts/extract-allocations.py' | |
| - 'scripts/merge-benchmark-results.py' | |
| - 'scripts/compare-benchmarks.py' | |
| - 'scripts/compare-benchmark.py' | |
| - '.github/workflows/benchmark.yml' | |
| pull_request: | |
| branches: [main] | |
| # No path filter for PRs - let the job-level conditions decide | |
| # E2E runs on perf PRs, micro runs on Picea.Abies/** changes | |
| workflow_dispatch: | |
| inputs: | |
| run_e2e_benchmark: | |
| description: 'Run E2E js-framework-benchmark' | |
| required: false | |
| default: true | |
| type: boolean | |
| permissions: | |
| contents: write | |
| deployments: write | |
| pull-requests: write | |
| # ============================================================================== | |
| # BENCHMARKING STRATEGY (see docs/investigations/benchmarking-strategy.md) | |
| # ============================================================================== | |
| # This workflow uses js-framework-benchmark as the SINGLE SOURCE OF TRUTH. | |
| # | |
| # Why E2E only (no micro-benchmarks in PR builds): | |
| # - Historical evidence: PatchType enum optimization showed 11-20% improvement | |
| # in BenchmarkDotNet but caused 2-5% REGRESSION in E2E benchmarks | |
| # - Micro-benchmarks miss: JS interop overhead, browser rendering, GC pressure | |
| # - E2E measures real user-perceived latency (EventDispatch → Paint) | |
| # | |
| # BenchmarkDotNet micro-benchmarks: | |
| # - ONLY run on push to main for historical tracking | |
| # - NOT run on PRs (removed to avoid misleading results) | |
| # - For local development: dotnet run --project Picea.Abies.Benchmarks -c Release | |
| # - Good for algorithm comparison and allocation tracking locally | |
| # | |
| # E2E benchmarks auto-trigger on: | |
| # - PRs with title starting with 'perf:' or 'perf(' | |
| # - PRs with 'performance' label | |
| # - PRs with 'ui' label | |
| # - PRs that modify benchmark workflow or scripts | |
| # - Pushes to main (baseline tracking) | |
| # - Manual workflow_dispatch | |
| # | |
| # Benchmarks included: | |
| # - CPU (01-09): Create, replace, update, select, swap, remove, clear rows | |
| # - Memory (21-25): Ready memory, run memory, clear memory | |
| # ============================================================================== | |
| jobs: | |
| # ============================================================================ | |
| # PATH DETECTION - Determine which jobs should run | |
| # ============================================================================ | |
| changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| e2e-scripts: ${{ steps.filter.outputs.e2e-scripts }} | |
| perf-pr: ${{ steps.check-perf.outputs.is-perf }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dorny/paths-filter@v3 | |
| id: filter | |
| with: | |
| filters: | | |
| e2e-scripts: | |
| - 'Picea.Abies/**' | |
| - 'Picea.Abies.UI/**' | |
| - 'Picea.Abies.Benchmark.Wasm/**' | |
| - '.github/workflows/benchmark.yml' | |
| - 'scripts/compare-benchmark.py' | |
| - 'scripts/convert-e2e-results.py' | |
| - 'scripts/run-benchmarks.sh' | |
| - name: Check if performance PR | |
| id: check-perf | |
| run: | | |
| if [[ "${{ github.event_name }}" == "pull_request" ]]; then | |
| TITLE="${{ github.event.pull_request.title }}" | |
| if [[ "$TITLE" == perf:* ]] || [[ "$TITLE" == perf\(* ]]; then | |
| echo "is-perf=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "is-perf=false" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "is-perf=false" >> $GITHUB_OUTPUT | |
| fi | |
| # ============================================================================ | |
| # MICRO-BENCHMARKS (BenchmarkDotNet) - Historical Tracking Only | |
| # ============================================================================ | |
| # ONLY runs on push to main for historical tracking. | |
| # NOT run on PRs - micro-benchmarks have historically been misleading. | |
| # For local development: dotnet run --project Picea.Abies.Benchmarks -c Release | |
| # ============================================================================ | |
| benchmark: | |
| name: Micro-Benchmarks (main only) | |
| runs-on: ubuntu-latest | |
| needs: changes | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Restore dependencies | |
| run: dotnet restore Picea.Abies.Benchmarks/Picea.Abies.Benchmarks.csproj | |
| - name: Build benchmarks | |
| run: dotnet build Picea.Abies.Benchmarks/Picea.Abies.Benchmarks.csproj -c Release --no-restore | |
| - name: Run DOM Diffing benchmarks | |
| run: > | |
| dotnet run --project Picea.Abies.Benchmarks -c Release --no-build -- | |
| --filter '*DomDiffingBenchmarks*' | |
| --exporters json | |
| --artifacts ./benchmark-results/diffing | |
| - name: Run Rendering benchmarks | |
| run: > | |
| dotnet run --project Picea.Abies.Benchmarks -c Release --no-build -- | |
| --filter '*RenderingBenchmarks*' | |
| --exporters json | |
| --artifacts ./benchmark-results/rendering | |
| - name: Run Event Handler benchmarks | |
| run: > | |
| dotnet run --project Picea.Abies.Benchmarks -c Release --no-build -- | |
| --filter '*EventHandlerBenchmarks*' | |
| --exporters json | |
| --artifacts ./benchmark-results/handlers | |
| - name: Merge benchmark results | |
| run: python3 scripts/merge-benchmark-results.py ./benchmark-results | |
| # ============================================ | |
| # HISTORICAL TRACKING (gh-pages) | |
| # ============================================ | |
| - name: Check if gh-pages exists | |
| id: gh-pages-check | |
| run: | | |
| if git ls-remote --exit-code --heads origin gh-pages > /dev/null 2>&1; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Store throughput baseline | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| with: | |
| name: "2. Micro-Benchmarks: Throughput (BenchmarkDotNet)" | |
| tool: benchmarkdotnet | |
| output-file-path: ./benchmark-results/merged/throughput.json | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| auto-push: true | |
| save-data-file: true | |
| skip-fetch-gh-pages: ${{ steps.gh-pages-check.outputs.exists != 'true' }} | |
| alert-threshold: '105%' | |
| comment-on-alert: true | |
| fail-on-alert: false | |
| summary-always: true | |
| alert-comment-cc-users: '@MCGPPeters' | |
| - name: Store allocation baseline | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| with: | |
| name: "2. Micro-Benchmarks: Allocations (BenchmarkDotNet)" | |
| tool: customSmallerIsBetter | |
| output-file-path: ./benchmark-results/merged/allocations.json | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| auto-push: true | |
| save-data-file: true | |
| skip-fetch-gh-pages: false | |
| alert-threshold: '110%' | |
| comment-on-alert: true | |
| fail-on-alert: false | |
| summary-always: true | |
| alert-comment-cc-users: '@MCGPPeters' | |
| - name: Upload benchmark artifacts | |
| uses: actions/upload-artifact@v6 | |
| if: always() | |
| with: | |
| name: micro-benchmark-results | |
| path: ./benchmark-results/ | |
| retention-days: 30 | |
| # ============================================================================ | |
| # E2E BENCHMARKS (js-framework-benchmark) - Source of Truth | |
| # REQUIRED STATUS CHECK - Fails on >5% performance regression | |
| # ============================================================================ | |
| # Clones the upstream js-framework-benchmark for benchmark infrastructure | |
| # (server, webdriver-ts, CSS) and builds Picea.Abies.Benchmark.Wasm from | |
| # the repo for the framework-under-test. | |
| # ============================================================================ | |
| benchmark-check: | |
| name: Benchmark (js-framework-benchmark) | |
| # NOTE: This job provides the "Benchmark (js-framework-benchmark)" status check | |
| # required for merging PRs. It fails if perf regressions >5% are detected. | |
| runs-on: ubuntu-latest | |
| needs: changes | |
| if: > | |
| github.event_name == 'workflow_dispatch' || | |
| github.event_name == 'pull_request' || | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Decide whether to run benchmarks | |
| id: should-run | |
| run: | | |
| if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| echo "run=true" >> "$GITHUB_OUTPUT" | |
| elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| if [[ "${{ inputs.run_e2e_benchmark }}" == "true" ]]; then | |
| echo "run=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "run=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| elif [[ "${{ needs.changes.outputs.perf-pr }}" == "true" || "${{ needs.changes.outputs.e2e-scripts }}" == "true" || "${{ contains(github.event.pull_request.labels.*.name, 'performance') }}" == "true" || "${{ contains(github.event.pull_request.labels.*.name, 'ui') }}" == "true" ]]; then | |
| echo "run=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "run=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Skip benchmark execution | |
| if: steps.should-run.outputs.run != 'true' | |
| run: | | |
| echo "No benchmark run needed for this PR; required check passes." | |
| - name: Clone js-framework-benchmark | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| # Remove uninitialized submodule placeholder directory | |
| rm -rf js-framework-benchmark | |
| # Clone upstream benchmark infrastructure (shallow for speed) | |
| git clone --depth 1 https://github.com/krausest/js-framework-benchmark.git js-framework-benchmark | |
| - name: Setup .NET | |
| if: steps.should-run.outputs.run == 'true' | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Install WASM workloads | |
| if: steps.should-run.outputs.run == 'true' | |
| run: dotnet workload install wasm-experimental wasm-tools | |
| - name: Setup Node.js | |
| if: steps.should-run.outputs.run == 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| # Build the benchmark WASM app from the repo's own project | |
| - name: Build Abies benchmark WASM app | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| dotnet publish Picea.Abies.Benchmark.Wasm/Picea.Abies.Benchmark.Wasm.csproj -c Release | |
| # Set up the framework entry in the js-framework-benchmark directory. | |
| # The upstream server's isFrameworkDir() requires BOTH package.json AND | |
| # package-lock.json to exist for framework discovery via the /ls endpoint. | |
| - name: Setup Abies framework in benchmark | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| # Ensure framework directory structure exists | |
| mkdir -p js-framework-benchmark/frameworks/keyed/abies/bundled-dist/wwwroot | |
| # Write package.json for framework registration with the benchmark server | |
| cat > js-framework-benchmark/frameworks/keyed/abies/package.json << 'PACKAGE_EOF' | |
| { | |
| "name": "js-framework-benchmark-abies", | |
| "version": "1.0.0", | |
| "js-framework-benchmark": { | |
| "frameworkVersionFromPackage": "", | |
| "frameworkVersion": "2.0.0", | |
| "customURL": "/bundled-dist/wwwroot/", | |
| "frameworkHomeURL": "https://github.com/picea/abies" | |
| } | |
| } | |
| PACKAGE_EOF | |
| # Write package-lock.json (required by upstream isFrameworkDir() check). | |
| # The server checks fs.existsSync(package-lock.json) before including a | |
| # framework in the /ls response. Since we use frameworkVersion (not | |
| # frameworkVersionFromPackage), the lock file contents are not read — | |
| # only its existence matters. | |
| cat > js-framework-benchmark/frameworks/keyed/abies/package-lock.json << 'LOCKFILE_EOF' | |
| { | |
| "name": "js-framework-benchmark-abies", | |
| "version": "1.0.0", | |
| "lockfileVersion": 3, | |
| "packages": {} | |
| } | |
| LOCKFILE_EOF | |
| # Find the AppBundle output directory (location varies by .NET SDK version) | |
| APPBUNDLE=$(find Picea.Abies.Benchmark.Wasm/bin -path "*/AppBundle" -type d | head -1) | |
| if [ -z "$APPBUNDLE" ]; then | |
| echo "Error: AppBundle directory not found after publish" | |
| find Picea.Abies.Benchmark.Wasm/bin -type d | head -20 | |
| exit 1 | |
| fi | |
| echo "Found AppBundle at: $APPBUNDLE" | |
| # Copy published WASM output to benchmark framework directory | |
| cp -r "$APPBUNDLE"/* js-framework-benchmark/frameworks/keyed/abies/bundled-dist/wwwroot/ | |
| # Fix base href for benchmark server context | |
| sed -i 's|<head>|<head>\n <base href="/frameworks/keyed/abies/bundled-dist/wwwroot/">|' \ | |
| js-framework-benchmark/frameworks/keyed/abies/bundled-dist/wwwroot/index.html | |
| # Verify the framework files are in place | |
| echo "=== Framework directory contents ===" | |
| ls -la js-framework-benchmark/frameworks/keyed/abies/ | |
| echo "=== Bundled dist contents ===" | |
| ls -la js-framework-benchmark/frameworks/keyed/abies/bundled-dist/wwwroot/ | head -20 | |
| # Cache npm dependencies | |
| - name: Cache npm dependencies | |
| if: steps.should-run.outputs.run == 'true' | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.npm | |
| key: npm-js-framework-benchmark-${{ runner.os }}-v1 | |
| restore-keys: | | |
| npm-js-framework-benchmark-${{ runner.os }}- | |
| # Cache Chrome browser for Selenium | |
| - name: Cache Chrome for Testing | |
| if: steps.should-run.outputs.run == 'true' | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/selenium | |
| key: selenium-chrome-${{ runner.os }}-v1 | |
| restore-keys: | | |
| selenium-chrome-${{ runner.os }}- | |
| - name: Install benchmark dependencies | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| cd js-framework-benchmark | |
| npm ci | |
| cd webdriver-ts | |
| npm ci | |
| # Compile TypeScript to dist/ folder | |
| npm run compile | |
| - name: Start benchmark server | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| cd js-framework-benchmark | |
| npm start & | |
| # Wait for server to be ready (up to 30 seconds) | |
| echo "Waiting for benchmark server to start..." | |
| for i in {1..30}; do | |
| if curl -s http://localhost:8080 > /dev/null 2>&1; then | |
| echo "Server is ready!" | |
| break | |
| fi | |
| if [ $i -eq 30 ]; then | |
| echo "Error: Server failed to start within 30 seconds" | |
| exit 1 | |
| fi | |
| sleep 1 | |
| done | |
| # Verify the server discovered our framework via the /ls endpoint. | |
| # Without this check, a missing package-lock.json or misconfigured | |
| # package.json causes zero frameworks to match silently (exit 0, | |
| # no results, compare script fails). | |
| - name: Verify framework discovery | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| echo "=== Checking /ls endpoint for framework discovery ===" | |
| LS_RESPONSE=$(curl -s http://localhost:8080/ls) | |
| echo "$LS_RESPONSE" | python3 -m json.tool | head -30 | |
| if echo "$LS_RESPONSE" | grep -q '"abies"'; then | |
| echo "✅ Framework 'abies' discovered by benchmark server" | |
| else | |
| echo "❌ Framework 'abies' NOT found in /ls response!" | |
| echo "Full /ls response:" | |
| echo "$LS_RESPONSE" | python3 -m json.tool | |
| echo "" | |
| echo "Checking framework directory:" | |
| ls -la js-framework-benchmark/frameworks/keyed/abies/ | |
| exit 1 | |
| fi | |
| - name: Run E2E benchmarks (all CPU benchmarks) | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| cd js-framework-benchmark/webdriver-ts | |
| npm run bench -- --headless --framework keyed/abies --benchmark 01_run1k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 02_replace1k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 03_update10th1k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 04_select1k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 05_swap1k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 06_remove-one-1k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 07_create10k | |
| npm run bench -- --headless --framework keyed/abies --benchmark 08_create1k-after1k_x2 | |
| npm run bench -- --headless --framework keyed/abies --benchmark 09_clear1k | |
| - name: Run Memory benchmarks | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| cd js-framework-benchmark/webdriver-ts | |
| npm run bench -- --headless --framework keyed/abies --benchmark 21_ready-memory | |
| npm run bench -- --headless --framework keyed/abies --benchmark 22_run-memory | |
| npm run bench -- --headless --framework keyed/abies --benchmark 25_clear-memory | |
| - name: Refresh baseline from gh-pages | |
| if: steps.should-run.outputs.run == 'true' | |
| continue-on-error: true | |
| run: | | |
| # Try to refresh baseline from gh-pages branch. | |
| # If unavailable, keep the repo baseline as fallback. | |
| mkdir -p benchmark-results | |
| if git show origin/gh-pages:data/e2e-baseline.json > /tmp/e2e-baseline.json 2>/dev/null; then | |
| mv /tmp/e2e-baseline.json benchmark-results/baseline.json | |
| echo "✅ Refreshed baseline from gh-pages" | |
| else | |
| if [ -f benchmark-results/baseline.json ]; then | |
| echo "⚠️ Could not refresh from gh-pages, using repo baseline" | |
| else | |
| echo "⚠️ No baseline found in gh-pages or repo - first run will create one" | |
| fi | |
| fi | |
| - name: Compare against baseline | |
| if: steps.should-run.outputs.run == 'true' | |
| id: regression-check | |
| continue-on-error: true | |
| run: | | |
| mkdir -p benchmark-results | |
| set +e | |
| python3 scripts/compare-benchmark.py \ | |
| --results-dir js-framework-benchmark/webdriver-ts/results \ | |
| --baseline benchmark-results/baseline.json \ | |
| --threshold 5.0 \ | |
| --framework abies | tee benchmark-results/e2e-compare.log | |
| EXIT_CODE=${PIPESTATUS[0]} | |
| echo "exit_code=${EXIT_CODE}" >> "$GITHUB_OUTPUT" | |
| exit ${EXIT_CODE} | |
| - name: Publish benchmark comparison summary | |
| if: always() && steps.should-run.outputs.run == 'true' | |
| run: | | |
| echo "## js-framework-benchmark comparison" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| if [ -f benchmark-results/e2e-compare.log ]; then | |
| echo "Comparison command exit code: ${{ steps.regression-check.outputs.exit_code }}" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo '```text' >> "$GITHUB_STEP_SUMMARY" | |
| tail -n 120 benchmark-results/e2e-compare.log >> "$GITHUB_STEP_SUMMARY" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| else | |
| echo "No comparison log generated." >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| - name: Report benchmark status | |
| if: always() && steps.should-run.outputs.run == 'true' | |
| run: | | |
| if [[ "${{ steps.regression-check.outcome }}" == "failure" ]]; then | |
| echo "❌ Performance regression detected (>5%)" | |
| exit 1 | |
| else | |
| echo "✅ Benchmark check passed" | |
| fi | |
| - name: Convert E2E results to benchmark format | |
| if: steps.should-run.outputs.run == 'true' | |
| run: | | |
| python3 scripts/convert-e2e-results.py \ | |
| --results-dir js-framework-benchmark/webdriver-ts/results \ | |
| --output ./e2e-benchmark-results.json \ | |
| --output-memory ./e2e-benchmark-memory.json \ | |
| --framework abies | |
| - name: Check if gh-pages exists | |
| id: gh-pages-check | |
| if: steps.should-run.outputs.run == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: | | |
| if git ls-remote --exit-code --heads origin gh-pages > /dev/null 2>&1; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Store E2E benchmark trends to gh-pages (main only) | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| if: steps.should-run.outputs.run == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.gh-pages-check.outputs.exists == 'true' | |
| with: | |
| name: "1. E2E Benchmark (js-framework-benchmark)" | |
| tool: customSmallerIsBetter | |
| output-file-path: ./e2e-benchmark-results.json | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| auto-push: true | |
| save-data-file: true | |
| alert-threshold: '110%' | |
| comment-on-alert: true | |
| fail-on-alert: false | |
| summary-always: true | |
| alert-comment-cc-users: '@MCGPPeters' | |
| - name: Store E2E memory benchmark trends to gh-pages (main only) | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| if: steps.should-run.outputs.run == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.gh-pages-check.outputs.exists == 'true' | |
| with: | |
| name: "1. E2E Benchmark: Memory (js-framework-benchmark)" | |
| tool: customSmallerIsBetter | |
| output-file-path: ./e2e-benchmark-memory.json | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| auto-push: true | |
| save-data-file: true | |
| alert-threshold: '120%' | |
| comment-on-alert: true | |
| fail-on-alert: false | |
| summary-always: true | |
| alert-comment-cc-users: '@MCGPPeters' | |
| # ============================================================================ | |
| # AUTO-UPDATE README BENCHMARK TABLES (main only) | |
| # ============================================================================ | |
| # After benchmarks complete on main, regenerate the Duration and Memory | |
| # tables in README.md using the latest results and the static Blazor baseline. | |
| # Opens a PR instead of pushing directly to main to avoid triggering other | |
| # on:push workflows (CD, E2E, etc.). | |
| # ============================================================================ | |
| - name: Update README benchmark tables (main only) | |
| if: steps.should-run.outputs.run == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: | | |
| python3 scripts/update-readme-benchmarks.py \ | |
| --results-dir js-framework-benchmark/webdriver-ts/results \ | |
| --blazor-baseline benchmark-results/blazor-baseline.json \ | |
| --readme README.md \ | |
| --framework abies | |
| - name: Create PR for README benchmark updates (main only) | |
| if: steps.should-run.outputs.run == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: peter-evans/create-pull-request@v6 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| commit-message: "docs: update benchmark results in README" | |
| title: "docs: update benchmark results in README" | |
| body: | | |
| Automated update of benchmark tables in README.md based on the latest js-framework-benchmark results. | |
| This PR was created by the Benchmark workflow after running on `main`. | |
| branch: benchmark/readme-auto-update | |
| base: main | |
| add-paths: | | |
| README.md | |
| - name: Copy results to workspace for upload | |
| if: always() && steps.should-run.outputs.run == 'true' | |
| run: | | |
| mkdir -p ./e2e-results | |
| cp -r js-framework-benchmark/webdriver-ts/results/* ./e2e-results/ 2>/dev/null || true | |
| cp ./e2e-benchmark-results.json ./e2e-results/ 2>/dev/null || true | |
| cp ./e2e-benchmark-memory.json ./e2e-results/ 2>/dev/null || true | |
| cp benchmark-results/e2e-compare.log ./e2e-results/ 2>/dev/null || true | |
| - name: Upload E2E benchmark results | |
| uses: actions/upload-artifact@v6 | |
| if: always() && steps.should-run.outputs.run == 'true' | |
| with: | |
| name: e2e-benchmark-results | |
| path: ./e2e-results/ | |
| retention-days: 30 |