mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-14 18:01:20 +08:00
d7c1050e44
## Summary Replace the trivial `hdr-pq` and `hdr-image-only` tests with two consolidated, time-windowed regression suites that exercise the full HDR pipeline. These goldens are the safety net for every other PR in this stack. ## Why The pre-existing HDR tests covered only a single full-bleed video or image with a static text label — none of the features that the HDR pipeline has to handle differently from SDR (opacity animation, z-ordered multi-layer compositing, transforms, border-radius clipping, shader transitions, multiple HDR sources, object-fit modes, mixed HDR+SDR layering, HLG transfer). This PR builds the missing safety net first so every subsequent fix can be proven correct. ## What changed - New `packages/producer/tests/hdr-regression/` (PQ, BT.2020, ~20 s, 1080p, 8 windows A–H): - A: static baseline (HDR video + DOM overlay) - B: wrapper-opacity fade - C: direct-on-`<video>` opacity tween (documents the Chunk 1 bug) - D: z-order sandwich (DOM → HDR → DOM) - E: two HDR videos side-by-side (pins PR #289) - F: rotation + scale + border-radius (documents the Chunk 4 bug) - G: `object-fit: contain` - H: shader crossfade between HDR video and HDR image - New `packages/producer/tests/hdr-hlg-regression/` (HLG, ARIB STD-B67, ~5 s, 2 windows A–B) — exercises the separate HLG LUT/OETF code path that previously had **zero** coverage. - New `scripts/generate-hdr-photo-pq.py` synthesizes `hdr-photo-pq.png` with a cICP chunk for BT.2020/PQ/full. - Removed `tests/hdr-pq/` and `tests/hdr-image-only/`. - Updated `.github/workflows/regression.yml` HDR shard to run the new pair sequentially. - All compositions follow the documented timed-element pattern (`data-start`, `data-duration`, `class="clip"` directly on each timed leaf — no wrapper inheritance). ## Test plan - [x] Goldens generated with `bun run test:update --sequential`. - [x] `ffprobe` confirms HEVC/yuv420p10le/bt2020nc/smpte2084 (PQ) and arib-std-b67 (HLG). - [x] Suite green with `maxFrameFailures` budgets that absorb the documented Chunk 1 / Chunk 4 known-fails — tightened in follow-up PRs in this stack. ## Stack Foundational PR for the HDR follow-ups stack (Chunk 0 of `plans/hdr-followups.md`). Every subsequent PR builds on this safety net.
125 lines
3.9 KiB
YAML
125 lines
3.9 KiB
YAML
name: regression
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
jobs:
|
|
changes:
|
|
name: Detect changes
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 2
|
|
outputs:
|
|
code: ${{ steps.filter.outputs.code }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: dorny/paths-filter@v3
|
|
id: filter
|
|
with:
|
|
filters: |
|
|
code:
|
|
- "packages/core/**"
|
|
- "packages/producer/**"
|
|
- "packages/engine/**"
|
|
- "Dockerfile*"
|
|
|
|
regression-shards:
|
|
needs: changes
|
|
if: needs.changes.outputs.code == 'true'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 60
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- shard: fast
|
|
args: "--sequential --exclude-tags slow,render-compat,hdr"
|
|
- shard: render-compat
|
|
args: "--sequential gsap-letters-render-compat css-spinner-render-compat raf-ball-render-compat iframe-render-compat"
|
|
- shard: hdr
|
|
args: "--sequential hdr-regression hdr-hlg-regression"
|
|
- shard: styles-a
|
|
args: "style-1-prod style-2-prod style-3-prod"
|
|
- shard: styles-b
|
|
args: "style-4-prod style-5-prod style-6-prod"
|
|
- shard: styles-c
|
|
args: "style-7-prod style-8-prod style-9-prod"
|
|
- shard: styles-d
|
|
args: "style-10-prod style-11-prod style-12-prod"
|
|
- shard: styles-e
|
|
args: "style-13-prod style-15-prod style-16-prod"
|
|
- shard: styles-f
|
|
args: "style-17-prod style-18-prod"
|
|
- shard: styles-g
|
|
args: "overlay-montage-prod"
|
|
steps:
|
|
- name: Checkout (with LFS)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
lfs: true
|
|
|
|
- name: Validate LFS files
|
|
run: |
|
|
echo "Checking golden baseline MP4s are real files (not LFS pointers)..."
|
|
for mp4 in packages/producer/tests/*/output/output.mp4; do
|
|
if [ -f "$mp4" ]; then
|
|
size=$(stat --format=%s "$mp4")
|
|
if [ "$size" -lt 1000 ]; then
|
|
echo "ERROR: $mp4 appears to be an LFS pointer ($size bytes)"
|
|
exit 1
|
|
fi
|
|
echo "OK: $mp4 ($size bytes)"
|
|
fi
|
|
done
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Build test Docker image (cached)
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: Dockerfile.test
|
|
load: true
|
|
tags: hyperframes-producer:test
|
|
cache-from: type=gha,scope=regression-test-image
|
|
cache-to: type=gha,mode=min,scope=regression-test-image
|
|
|
|
- name: "Run regression shard: ${{ matrix.shard }}"
|
|
run: |
|
|
echo "Shard: ${{ matrix.shard }}"
|
|
echo "Args: ${{ matrix.args }}"
|
|
docker run --rm \
|
|
--security-opt seccomp=unconfined \
|
|
--shm-size=4g \
|
|
-v ${{ github.workspace }}/packages/producer/tests:/app/packages/producer/tests \
|
|
hyperframes-producer:test \
|
|
${{ matrix.args }}
|
|
|
|
- name: Upload failure artifacts
|
|
if: failure()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: regression-failures-${{ matrix.shard }}
|
|
path: packages/producer/tests/*/failures/
|
|
if-no-files-found: ignore
|
|
|
|
# Summary job — matches the required check name in branch protection
|
|
regression:
|
|
runs-on: ubuntu-latest
|
|
needs: [changes, regression-shards]
|
|
if: always()
|
|
steps:
|
|
- name: Check results
|
|
run: |
|
|
if [ "${{ needs.changes.outputs.code }}" != "true" ]; then
|
|
echo "No code changes — skipping regression (auto-pass)"
|
|
exit 0
|
|
fi
|
|
if [ "${{ needs.regression-shards.result }}" != "success" ]; then
|
|
echo "One or more regression shards failed"
|
|
exit 1
|
|
fi
|