LibreChat/.github/scripts/verify-playwright-ffmpeg.sh
Danny Avila 061e4b02a3
🎞️ ci: Fix Playwright ffmpeg Install Hang and Cache the Download (#15065)
Every Playwright job spent a flat 90s on `npx playwright install ffmpeg`,
and none of them ended up with a usable ffmpeg.

The 2.3MB download finishes in under a second; extraction then hangs until
`timeout -k 10 90` reaps it (exit 124, masked by `continue-on-error`). That
is a Node 24.16.0 readable-stream change (nodejs/node#62557) colliding with
yauzl/fd-slicer never firing `close` after EOF, which hangs extract-zip.
It leaves a truncated `ffmpeg-linux` — 5,055,201 bytes against the zip's
declared 5,101,056, segfaulting on exec — and no INSTALLATION_COMPLETE
marker, so Playwright treated ffmpeg as uninstalled. `video: 'on-first-retry'`
has therefore never worked in CI, and every first retry of a flaky test died
in browserContext.newPage: exactly the failure the step existed to prevent.

Upstream fixed it in Playwright 1.60.0 (microsoft/playwright#40747) and Node
reverted it in 24.18.0 (nodejs/node#63834). Node 24.16.0 is pinned in 17
places including the Dockerfiles, so bump Playwright instead — it is a dev
dependency, and `^1.56.1` already permitted 1.62.1; only the lockfile pinned
it. Staying at or above 1.62.1 also avoids the tsconfig-resolution
regressions in 1.62.0.

Caching alone could not have fixed this: a cold cache still hangs, and what
would have been cached is the corrupt binary. So the ffmpeg download is now
restored from cache keyed on the resolved playwright-core version, the
install is skipped outright on a hit, and the cache is only saved once the
binary is verified to actually execute — a partial extraction can never be
promoted into a cache that every later job restores.

Per job: 90s to ~0s on a hit, ~2s on a miss.
2026-08-21 01:36:09 -04:00

43 lines
1.6 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Verifies that Playwright's ffmpeg download produced a usable binary.
#
# `playwright install` is not trustworthy on its own here: under the Node 24.16.0
# yauzl/extract-zip regression (Playwright < 1.60.0) it would hang mid-extraction
# and leave a truncated `ffmpeg-linux` behind with no INSTALLATION_COMPLETE marker,
# so the exit code said nothing about whether ffmpeg actually worked.
#
# CI caches the download, so this runs before the cache is saved: checking both the
# marker and that the binary actually executes is what keeps a partial extraction
# from being promoted into a cache that every later job would restore. The install
# directory is read back from Playwright so this stays correct across version bumps
# and never lets a stale revision vouch for the one actually required.
set -uo pipefail
install_dir=$(npx playwright install --dry-run ffmpeg 2>/dev/null |
sed -n 's/^[[:space:]]*Install location:[[:space:]]*//p' | head -1)
if [ -z "${install_dir}" ]; then
echo "::warning::Could not determine Playwright's ffmpeg install location; skipping cache save."
exit 1
fi
if [ ! -f "${install_dir}/INSTALLATION_COMPLETE" ]; then
echo "::warning::${install_dir} has no INSTALLATION_COMPLETE marker; the download did not finish."
exit 1
fi
binary="${install_dir}/ffmpeg-linux"
if [ ! -x "${binary}" ]; then
echo "::warning::${binary} is missing or not executable."
exit 1
fi
if ! "${binary}" -version >/dev/null 2>&1; then
echo "::warning::${binary} is present but does not execute; treating it as a partial extraction."
exit 1
fi
echo "Verified Playwright ffmpeg at ${binary}"