Repository navigation
fix(parsers): find ffmpeg installed after a long-running preview star… #26193
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: Player perf | |
| permissions: | |
| contents: read | |
| # Suppress hyperframes CLI telemetry from HeyGen's own CI runs. | |
| # External users' CI continues to emit telemetry unless they set this themselves. | |
| env: | |
| HYPERFRAMES_NO_TELEMETRY: "1" | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| concurrency: | |
| group: player-perf-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| changes: | |
| name: Detect changes | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 2 | |
| outputs: | |
| perf: ${{ steps.filter.outputs.perf }} | |
| steps: | |
| # Force git-based change detection instead of the pull_request REST API. | |
| # The API path can fail the perf workflow on transient listFiles timeouts. | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| fetch-depth: 0 | |
| # HEAD is the PR merge ref; its first parent is the current base tip, unlike the payload's | |
| # base.sha, which goes stale and would count the base's newer commits as the PR's changes. | |
| - name: Find the pull request's current base | |
| id: base | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| git rev-parse --verify -q HEAD^2 > /dev/null || { echo "::error::HEAD is not the pull request merge commit"; exit 1; } | |
| sha="$(git rev-parse --verify HEAD^1)" | |
| echo "sha=$sha" >> "$GITHUB_OUTPUT" | |
| - uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4 | |
| id: filter | |
| with: | |
| token: "" | |
| base: ${{ steps.base.outputs.sha }} | |
| filters: | | |
| perf: | |
| - "packages/player/**" | |
| - "packages/core/**" | |
| - "package.json" | |
| - "bun.lock" | |
| - ".github/workflows/player-perf.yml" | |
| preflight: | |
| name: Preflight (lint + format) | |
| needs: changes | |
| if: needs.changes.outputs.perf == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| - uses: ./.github/actions/preflight | |
| perf-shards: | |
| name: "Perf: ${{ matrix.shard }}" | |
| needs: [changes, preflight] | |
| if: needs.changes.outputs.perf == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: true | |
| matrix: | |
| include: | |
| - shard: load | |
| scenarios: load | |
| runs: "5" | |
| - shard: fps | |
| scenarios: fps | |
| runs: "3" | |
| - shard: scrub | |
| scenarios: scrub | |
| runs: "3" | |
| - shard: drift | |
| scenarios: drift | |
| runs: "3" | |
| - shard: parity | |
| scenarios: parity | |
| runs: "3" | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: 22 | |
| - run: bun install --frozen-lockfile | |
| # Player perf loads packages/player/dist/hyperframes-player.global.js | |
| # and packages/core/dist/hyperframe.runtime.iife.js, so a full build is required. | |
| - run: bun run build | |
| - name: Set up Chrome (headless shell) | |
| id: setup-chrome | |
| uses: browser-actions/setup-chrome@c785b87e244131f27c9f19c1a33e2ead956ab7ce # v1 | |
| with: | |
| chrome-version: stable | |
| # The parity scenario shells out to `ffmpeg -lavfi ssim` to score the | |
| # live-playback frame against the sync-seek reference frame. ffmpeg is | |
| # not on the default ubuntu-latest runner image, and a missing binary | |
| # surfaces as ENOENT inside computeSsim() — informative, but cheaper | |
| # to just install it here so the shard never trips on infra. | |
| - name: Install ffmpeg (parity shard only) | |
| if: matrix.shard == 'parity' | |
| uses: ./.github/actions/install-ffmpeg-linux | |
| - name: Verify sandbox origin boundary (load shard only) | |
| if: matrix.shard == 'load' | |
| working-directory: packages/player | |
| env: | |
| PUPPETEER_EXECUTABLE_PATH: ${{ steps.setup-chrome.outputs.chrome-path }} | |
| run: bun run test:browser-security | |
| - name: Verify the preview rasters at its shown size (load shard only) | |
| if: matrix.shard == 'load' | |
| working-directory: packages/player | |
| env: | |
| PUPPETEER_EXECUTABLE_PATH: ${{ steps.setup-chrome.outputs.chrome-path }} | |
| run: bun run test:browser-raster | |
| - name: Run player perf — ${{ matrix.shard }} (measure mode) | |
| working-directory: packages/player | |
| env: | |
| PUPPETEER_EXECUTABLE_PATH: ${{ steps.setup-chrome.outputs.chrome-path }} | |
| run: | | |
| bun run perf \ | |
| --mode=measure \ | |
| --scenarios=${{ matrix.scenarios }} \ | |
| --runs=${{ matrix.runs }} | |
| - name: Upload perf results | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: player-perf-${{ matrix.shard }} | |
| path: packages/player/tests/perf/results/ | |
| if-no-files-found: warn | |
| retention-days: 30 | |
| # Summary job — matches the required check name in branch protection. | |
| # Logs an explicit "skipped" / "passed" / "failed" line both to stdout and to | |
| # $GITHUB_STEP_SUMMARY so a false skip is obvious in the Checks UI without | |
| # having to dig into the changes-job logs. | |
| player-perf: | |
| runs-on: ubuntu-latest | |
| needs: [changes, perf-shards] | |
| if: always() | |
| steps: | |
| - name: Check results | |
| env: | |
| PERF_FILTER_RESULT: ${{ needs.changes.outputs.perf }} | |
| PERF_SHARDS_RESULT: ${{ needs.perf-shards.result }} | |
| run: | | |
| { | |
| echo "## Player perf gate" | |
| echo "" | |
| echo "- paths-filter \`perf\` matched: \`${PERF_FILTER_RESULT}\`" | |
| echo "- perf-shards result: \`${PERF_SHARDS_RESULT}\`" | |
| echo "" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| if [ "${PERF_FILTER_RESULT}" != "true" ]; then | |
| echo "::notice title=Player perf::SKIPPED — no changes under packages/player/**, packages/core/**, package.json, bun.lock, or .github/workflows/player-perf.yml. Auto-pass." | |
| echo "**Status:** SKIPPED (no player/core changes — auto-pass)" >> "$GITHUB_STEP_SUMMARY" | |
| exit 0 | |
| fi | |
| if [ "${PERF_SHARDS_RESULT}" != "success" ]; then | |
| echo "::error title=Player perf::FAILED — perf-shards result was '${PERF_SHARDS_RESULT}'. See the per-shard logs above." | |
| echo "**Status:** FAILED (perf-shards result: \`${PERF_SHARDS_RESULT}\`)" >> "$GITHUB_STEP_SUMMARY" | |
| exit 1 | |
| fi | |
| echo "::notice title=Player perf::PASSED — all perf shards completed successfully." | |
| echo "**Status:** PASSED" >> "$GITHUB_STEP_SUMMARY" |