Skip to content

Commit 64b0daa

Browse files
committed
feat(ci): add Facebook-grade reliability improvements
- Add workflow_run trigger to replace fragile gh run list polling - Implement pre-publish smoke test (npm pack → install → verify) - Add SHA256 checksum verification for NASM, Opus, LAME downloads - Replace hardcoded DEPS_VERSION with dynamic resolution via gh release list - Gate post-publish smoke tests on tag releases only - Add explicit curl error handling before checksum verification The release pipeline now follows pack → verify → publish → smoke-test pattern, catching issues before npm publish instead of after.
1 parent c35975e commit 64b0daa

3 files changed

Lines changed: 279 additions & 51 deletions

File tree

.github/workflows/build-ffmpeg.yml

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ env:
5353
OPUS_VERSION: '1.5.2'
5454
LAME_VERSION: '3.100'
5555
FFMPEG_VERSION: 'n8.0'
56+
# SHA256 checksums for tarball downloads (hermetic build verification)
57+
# These MUST be updated when changing versions above
58+
# Sources: https://opus-codec.org/downloads/, https://sourceforge.net/projects/lame/
59+
# NASM uses GitHub source archive (more reliable than nasm.us)
60+
NASM_VERSION: '2.16.03'
61+
NASM_SHA256: 'e7f77b8247de72f3c2a2c57a9c72b2a0c847ec5e99ce6e68c1e225fa2e37c04c' # GitHub source archive
62+
OPUS_SHA256: '65c1d2f78b9f2fb20082c38cbe47c951ad5839345876e46941612ee87f9a7ce1'
63+
LAME_SHA256: 'ddfe36cab873794038ae2c1210557ad34857a4b6bdc515785d1da9e175b1da1e'
5664
# npm scope for platform packages
5765
NPM_SCOPE: '@pproenca/ffmpeg'
5866
# Bump this to invalidate all caches
@@ -287,37 +295,34 @@ jobs:
287295
rm -rf x264 x265_git libvpx aom aom_build opus-* lame-* nasm-*
288296
289297
echo "=== Building nasm ==="
290-
NASM_VERSION="2.16.03"
291-
NASM_URL="https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.bz2"
292-
NASM_GITHUB="https://github.com/netwide-assembler/nasm/archive/refs/tags/nasm-${NASM_VERSION}.tar.gz"
293-
294-
# Try primary source with retries, fallback to GitHub mirror
295-
NASM_FROM_GITHUB=false
296-
if curl -fSL --retry 3 --retry-delay 5 "$NASM_URL" -o nasm.tar.bz2; then
297-
echo "Downloaded nasm from primary source"
298-
tar xjf nasm.tar.bz2
299-
cd nasm-${NASM_VERSION}
300-
else
301-
echo "Primary nasm download failed, trying GitHub mirror..."
302-
curl -fSL --retry 3 "$NASM_GITHUB" -o nasm.tar.gz
303-
tar xzf nasm.tar.gz
304-
cd nasm-nasm-${NASM_VERSION}
305-
NASM_FROM_GITHUB=true
306-
# GitHub source archive requires autogen.sh to create configure script
307-
./autogen.sh
308-
fi
298+
# Use GitHub source archive (more reliable than nasm.us which often has connectivity issues)
299+
NASM_URL="https://github.com/netwide-assembler/nasm/archive/refs/tags/nasm-${{ env.NASM_VERSION }}.tar.gz"
300+
301+
echo "Downloading NASM from GitHub..."
302+
curl -fSL --retry 3 --retry-delay 5 "$NASM_URL" -o nasm.tar.gz || {
303+
echo "ERROR: Failed to download NASM from $NASM_URL"
304+
exit 1
305+
}
306+
307+
# SHA256 verification (hermetic build)
308+
echo "${{ env.NASM_SHA256 }} nasm.tar.gz" | shasum -a 256 -c - || {
309+
echo "ERROR: NASM checksum verification failed!"
310+
echo "Expected: ${{ env.NASM_SHA256 }}"
311+
echo "Got: $(shasum -a 256 nasm.tar.gz | cut -d' ' -f1)"
312+
exit 1
313+
}
314+
echo "NASM checksum verified"
309315
316+
tar xzf nasm.tar.gz
317+
cd nasm-nasm-${{ env.NASM_VERSION }}
318+
# GitHub source archive requires autogen.sh to create configure script
319+
./autogen.sh
310320
./configure --prefix="$TARGET"
311321
make -j$(sysctl -n hw.ncpu)
312-
313322
# GitHub source doesn't include pre-generated man pages (requires asciidoc)
314323
# Install binaries directly to avoid man page install failure
315-
if [ "$NASM_FROM_GITHUB" = true ]; then
316-
mkdir -p "$TARGET/bin"
317-
install -c nasm ndisasm "$TARGET/bin/"
318-
else
319-
make install
320-
fi
324+
mkdir -p "$TARGET/bin"
325+
install -c nasm ndisasm "$TARGET/bin/"
321326
cd ..
322327
323328
echo "=== Building x264 (GPL) ==="
@@ -415,7 +420,21 @@ jobs:
415420
cd ..
416421
417422
echo "=== Building libopus (BSD) ==="
418-
curl -sL https://downloads.xiph.org/releases/opus/opus-${{ env.OPUS_VERSION }}.tar.gz | tar xz
423+
curl -fSL --retry 3 https://downloads.xiph.org/releases/opus/opus-${{ env.OPUS_VERSION }}.tar.gz -o opus.tar.gz || {
424+
echo "ERROR: Failed to download Opus from xiph.org"
425+
exit 1
426+
}
427+
428+
# SHA256 verification (hermetic build)
429+
echo "${{ env.OPUS_SHA256 }} opus.tar.gz" | shasum -a 256 -c - || {
430+
echo "ERROR: Opus checksum verification failed!"
431+
echo "Expected: ${{ env.OPUS_SHA256 }}"
432+
echo "Got: $(shasum -a 256 opus.tar.gz | cut -d' ' -f1)"
433+
exit 1
434+
}
435+
echo "Opus checksum verified"
436+
437+
tar xzf opus.tar.gz
419438
cd opus-${{ env.OPUS_VERSION }}
420439
./configure \
421440
--prefix="$TARGET" \
@@ -428,7 +447,21 @@ jobs:
428447
cd ..
429448
430449
echo "=== Building libmp3lame (LGPL) ==="
431-
curl -sL "https://downloads.sourceforge.net/project/lame/lame/${{ env.LAME_VERSION }}/lame-${{ env.LAME_VERSION }}.tar.gz" | tar xz
450+
curl -fSL --retry 3 "https://downloads.sourceforge.net/project/lame/lame/${{ env.LAME_VERSION }}/lame-${{ env.LAME_VERSION }}.tar.gz" -o lame.tar.gz || {
451+
echo "ERROR: Failed to download LAME from SourceForge"
452+
exit 1
453+
}
454+
455+
# SHA256 verification (hermetic build)
456+
echo "${{ env.LAME_SHA256 }} lame.tar.gz" | shasum -a 256 -c - || {
457+
echo "ERROR: LAME checksum verification failed!"
458+
echo "Expected: ${{ env.LAME_SHA256 }}"
459+
echo "Got: $(shasum -a 256 lame.tar.gz | cut -d' ' -f1)"
460+
exit 1
461+
}
462+
echo "LAME checksum verified"
463+
464+
tar xzf lame.tar.gz
432465
cd lame-${{ env.LAME_VERSION }}
433466
./configure \
434467
--prefix="$TARGET" \

.github/workflows/ci.yml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,44 @@ on:
1515

1616
permissions: {}
1717

18-
env:
19-
DEPS_VERSION: v10 # Bump when running new build-ffmpeg workflow
18+
# DEPS_VERSION is resolved dynamically in the resolve-deps job
19+
# No hardcoded version here - always uses latest deps-* release
2020

2121
jobs:
22+
# ============================================================================
23+
# Resolve latest FFmpeg dependencies release
24+
# This eliminates the need to manually bump DEPS_VERSION
25+
# ============================================================================
26+
resolve-deps:
27+
name: "Resolve Dependencies"
28+
runs-on: ubuntu-24.04
29+
permissions:
30+
contents: read
31+
outputs:
32+
deps_version: ${{ steps.deps.outputs.version }}
33+
steps:
34+
- name: Find latest deps release
35+
id: deps
36+
env:
37+
GH_TOKEN: ${{ github.token }}
38+
run: |
39+
# Find the latest deps-* release tag
40+
# Use --limit 200 to ensure we find deps releases even with many other releases
41+
LATEST_TAG=$(gh release list --repo "${{ github.repository }}" --limit 200 --json tagName --jq '[.[] | select(.tagName | startswith("deps-"))][0].tagName' || echo "")
42+
43+
if [ -z "$LATEST_TAG" ]; then
44+
echo "ERROR: No deps-* release found in repository"
45+
echo "Please run the build-ffmpeg workflow first to create a deps release"
46+
exit 1
47+
fi
48+
49+
# Extract version (deps-v10 -> v10)
50+
VERSION="${LATEST_TAG#deps-}"
51+
52+
echo "Detected latest dependencies: $LATEST_TAG (version: $VERSION)"
53+
echo "version=$VERSION" >> $GITHUB_OUTPUT
54+
55+
2256
# ============================================================================
2357
# Lint - Fast fail on code quality issues
2458
# ============================================================================
@@ -44,7 +78,7 @@ jobs:
4478
contents: read
4579
id-token: write # For OIDC attestation
4680
attestations: write # For build provenance
47-
needs: [lint]
81+
needs: [lint, resolve-deps]
4882
name: "build-${{ matrix.platform }}"
4983
runs-on: ${{ matrix.os }}
5084
strategy:
@@ -93,7 +127,7 @@ jobs:
93127
uses: dsaltares/fetch-gh-release-asset@aa2ab1243d6e0d5b405b973c89fa4d06a2d0fff7 # v1.1.2
94128
with:
95129
repo: ${{ github.repository }}
96-
version: tags/deps-${{ env.DEPS_VERSION }}
130+
version: tags/deps-${{ needs.resolve-deps.outputs.deps_version }}
97131
# Use glibc variant for Linux (musl libs can't link into glibc shared objects)
98132
file: ffmpeg-${{ matrix.platform }}${{ runner.os == 'Linux' && '-glibc' || '' }}.tar.gz
99133
target: ffmpeg-${{ matrix.platform }}.tar.gz

0 commit comments

Comments
 (0)