name: CI
on:
pull_request:
branches:
- "**"
types: [opened, synchronize, reopened]
env:
CARGO_TERM_COLOR: always
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
if: ${{ !contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.body, '[skip ci]') }}
name: Test (Linux) (${{ matrix.toolchain }})
runs-on: ubuntu-latest
env:
VCPKG_ROOT: ${{ github.workspace }}/target/vcpkg
permissions:
contents: read
actions: write
strategy:
max-parallel: 1
matrix:
toolchain:
- stable
- beta
- nightly
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
components: rustfmt, clippy
- name: Install cargo-audit
if: matrix.toolchain == 'stable'
uses: taiki-e/install-action@v2
with:
tool: cargo-audit
- name: Set up sccache
id: sccache-setup
uses: mozilla-actions/sccache-action@v0.0.5
continue-on-error: true
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get --assume-yes install ffmpeg nasm autoconf autoconf-archive automake libtool
- name: Set job-level RUSTC_WRAPPER
if: steps.sccache-setup.outcome == 'success'
run: echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
- if: steps.sccache-setup.outcome == 'failure'
run: echo "RUSTC_WRAPPER=" >> $GITHUB_ENV
- name: Cache cargo-vcpkg binary
id: cargo-vcpkg-cache
uses: actions/cache@v4
with:
path: ~/.cargo/bin/cargo-vcpkg
key: cargo-vcpkg-linux-v1
- name: Install cargo-vcpkg
if: steps.cargo-vcpkg-cache.outputs.cache-hit != 'true'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: cargo install cargo-vcpkg --locked
- name: Cache cargo build artifacts
uses: Swatinem/rust-cache@v2
with:
prefix-key: linux-vcpkg-v3-ffmpeg8
- name: Cache OCR models
uses: actions/cache@v4
with:
path: target/ocr-models
key: ocr-models-linux-v1
- name: Cache vcpkg workspace (cross-branch)
id: vcpkg-root-cache
uses: actions/cache@v4
with:
path: |
target/vcpkg/.vcpkg-root
target/vcpkg/.git
target/vcpkg/downloads
target/vcpkg/installed
target/vcpkg/packages
target/vcpkg/ports
target/vcpkg/scripts
target/vcpkg/triplets
target/vcpkg/vcpkg
key: vcpkg-root-linux-v2-${{ hashFiles('Cargo.toml') }}
restore-keys: |
vcpkg-root-linux-v2-
- name: Validate vcpkg cache origin
run: |
cache_invalid=0
expected_rev="$(grep -E '^rev = "' Cargo.toml | head -n1 | awk -F'"' '{print $2}')"
if [ -e "target/vcpkg" ] && [ ! -e "target/vcpkg/.git" ]; then
echo "vcpkg root missing .git; clearing cache entry"
rm -rf target/vcpkg
cache_invalid=1
fi
for dir in target/vcpkg target/vcpkg/.vcpkg-root target/vcpkg/vcpkg; do
if [ -e "$dir/.git" ]; then
origin=$(git -C "$dir" remote get-url origin 2>/dev/null || true)
if [ -z "$origin" ]; then
echo "Failed to read vcpkg origin in $dir; clearing cache entry"
rm -rf "$dir"
cache_invalid=1
continue
fi
if [ "$origin" != "https://github.com/microsoft/vcpkg.git" ] && [ "$origin" != "https://github.com/microsoft/vcpkg" ]; then
echo "Unexpected vcpkg origin in : $origin"
rm -rf "$dir"
cache_invalid=1
continue
fi
if [ -n "$expected_rev" ]; then
if ! git -C "$dir" cat-file -e "${expected_rev}^{tree}" 2>/dev/null; then
echo "Missing vcpkg rev $expected_rev in $dir; clearing cache entry"
rm -rf "$dir"
cache_invalid=1
fi
fi
fi
done
if [ "$cache_invalid" -eq 1 ]; then
echo "VCPKG_CACHE_INVALID=1" >> "$GITHUB_ENV"
fi
- name: Use cached vcpkg workspace
if: steps.vcpkg-root-cache.outputs.cache-hit == 'true' && env.VCPKG_CACHE_INVALID != '1'
run: echo "vcpkg workspace cache hit; skipping dependency rebuild."
- name: Build vcpkg dependencies
if: steps.vcpkg-root-cache.outputs.cache-hit != 'true' || env.VCPKG_CACHE_INVALID == '1'
env:
VCPKG_BUILD_TYPE: release
VCPKG_FEATURE_FLAGS: manifests,binarycaching
VCPKG_BINARY_SOURCES: clear;x-gha,readwrite
VCPKG_CMAKE_CONFIGURE_OPTIONS: -Wno-dev -DCMAKE_POLICY_DEFAULT_CMP0174=NEW
VCPKG_MAX_CONCURRENCY: 2
CMAKE_BUILD_PARALLEL_LEVEL: 2
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: cargo vcpkg --verbose build
- name: Force regenerate rusty_ffmpeg bindings
run: cargo clean -p rusty_ffmpeg
- name: Rust format check
if: matrix.toolchain == 'stable'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: cargo fmt --all -- --check
- name: Clippy strict
if: matrix.toolchain == 'stable'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Rustdoc strict
if: matrix.toolchain == 'stable'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
RUSTDOCFLAGS: -D warnings
run: cargo doc --no-deps --document-private-items
- name: Cargo audit
if: matrix.toolchain == 'stable'
run: cargo audit
- name: Upload vcpkg logs on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: vcpkg-logs
path: |
target/vcpkg/buildtrees/**/*.log
target/vcpkg/buildtrees/**/*.txt
retention-days: 7
- name: Run concurrent tests
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
DPN_OCR_GOLDEN: "1"
DPN_OCR_AI_E2E: "1"
DPN_OCR_MODEL_DIR: ${{ github.workspace }}/target/ocr-models
run: |
start=$(date +%s)
./scripts/test-concurrent.sh
end=$(date +%s)
echo "### Linux test runtime" >> "$GITHUB_STEP_SUMMARY"
echo "- Toolchain: ${{ matrix.toolchain }}" >> "$GITHUB_STEP_SUMMARY"
echo "- vcpkg cache hit: ${{ steps.vcpkg-root-cache.outputs.cache-hit }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Test command: ./scripts/test-concurrent.sh" >> "$GITHUB_STEP_SUMMARY"
echo "- Includes ffmpeg-cli-tests runtime execution: yes" >> "$GITHUB_STEP_SUMMARY"
echo "- Duration: $((end-start))s" >> "$GITHUB_STEP_SUMMARY"
- name: Run ffmpeg regression tests (Linux stable)
if: matrix.toolchain == 'stable'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
run: |
cargo test -q --features ffmpeg-cli-tests cli_fails_fast_on_corrupted_hevc_input
cargo test -q --features ffmpeg-cli-tests sonarr_download_failure_restores_original_and_cleans_temp_files
- name: Run OCR fixture accuracy probe (Linux stable)
if: matrix.toolchain == 'stable'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
DPN_OCR_MODEL_DIR: ${{ github.workspace }}/target/ocr-models
run: |
mkdir -p benchmark_artifacts/ocr_fixture_eval
probe_log="benchmark_artifacts/ocr_fixture_eval/probe.log"
if [[ ! -x target/debug/direct_play_nice ]]; then
cargo build --bin direct_play_nice
fi
set +e
./scripts/ocr-tools/run_ocr_fixture_eval.sh \
--bin target/debug/direct_play_nice \
--fixtures tests/golden_subs/multilang \
--run-dir benchmark_artifacts/ocr_fixture_eval \
--ocr-engine pp-ocr-v3 2>&1 | tee "$probe_log"
probe_status=${PIPESTATUS[0]}
set -e
if [[ "$probe_status" -ne 0 ]]; then
if grep -Eqi 'load the ONNX Runtime binary|libonnxruntime\.so|onnxruntime\.dll|cannot open shared object file|The specified module could not be found' "$probe_log"; then
echo "::warning title=Skipping OCR fixture probe::ONNX Runtime shared library is unavailable on this runner."
{
echo "### OCR fixture eval (Linux stable)"
echo "- Status: skipped (missing ONNX Runtime shared library on runner)"
} >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
echo "::error title=OCR fixture probe failed::See benchmark_artifacts/ocr_fixture_eval/probe.log"
exit "$probe_status"
fi
{
echo "### OCR fixture eval (Linux stable)"
sed -n '1,120p' benchmark_artifacts/ocr_fixture_eval/fixture_eval.md
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload OCR fixture eval artifacts (Linux stable)
if: matrix.toolchain == 'stable'
uses: actions/upload-artifact@v4
with:
name: ocr-fixture-eval-linux-stable
path: benchmark_artifacts/ocr_fixture_eval
retention-days: 7
- name: Upload cargo timings
if: matrix.toolchain == 'stable'
uses: actions/upload-artifact@v4
with:
name: cargo-timings-linux-stable
path: target/cargo-timings
retention-days: 7
- name: sccache stats
if: ${{ env.RUSTC_WRAPPER == 'sccache' }}
run: sccache --show-stats || true
windows-test:
name: Test (Windows MSVC)
if: ${{ github.event_name != 'pull_request' || (!contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.body, '[skip ci]')) }}
runs-on: windows-latest
permissions:
contents: read
actions: write
env:
CARGO_TERM_COLOR: always
VCPKG_ROOT: ${{ github.workspace }}/target/vcpkg
VCPKGRS_TRIPLET: x64-windows-static
RUSTFLAGS: >-
-C target-feature=+crt-static
-C link-arg=Mfplat.lib
-C link-arg=Strmiids.lib
-C link-arg=Mfuuid.lib
-C link-arg=Bcrypt.lib
-C link-arg=Ncrypt.lib
-C link-arg=Crypt32.lib
-C link-arg=Secur32.lib
-C link-arg=Ole32.lib
-C link-arg=User32.lib
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Set up sccache
id: sccache-setup
uses: mozilla-actions/sccache-action@v0.0.5
continue-on-error: true
- name: Set job-level RUSTC_WRAPPER
if: steps.sccache-setup.outcome == 'success'
shell: pwsh
run: Add-Content -Path $env:GITHUB_ENV -Value "RUSTC_WRAPPER=sccache"
- name: Clear RUSTC_WRAPPER on sccache failure
if: steps.sccache-setup.outcome == 'failure'
shell: pwsh
run: Add-Content -Path $env:GITHUB_ENV -Value "RUSTC_WRAPPER="
- name: Install dependencies
shell: pwsh
run: choco install ffmpeg nasm strawberryperl -y
- name: Cache cargo-vcpkg binary
id: cargo-vcpkg-cache-win
uses: actions/cache@v4
with:
path: ~/.cargo/bin/cargo-vcpkg.exe
key: cargo-vcpkg-windows-v1
- name: Install cargo-vcpkg
if: steps.cargo-vcpkg-cache-win.outputs.cache-hit != 'true'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: cargo install cargo-vcpkg --locked
- name: Cache cargo build artifacts
uses: Swatinem/rust-cache@v2
with:
prefix-key: windows-vcpkg-v3-ffmpeg8
- name: Cache OCR models
uses: actions/cache@v4
with:
path: target/ocr-models
key: ocr-models-windows-v1
- name: Restore vcpkg workspace (cross-branch)
id: vcpkg-root-cache-win
uses: actions/cache/restore@v4
with:
path: |
target/vcpkg/.vcpkg-root
target/vcpkg/.git
target/vcpkg/downloads
target/vcpkg/installed
target/vcpkg/packages
target/vcpkg/ports
target/vcpkg/scripts
target/vcpkg/triplets
target/vcpkg/vcpkg
target/vcpkg/vcpkg.exe
key: vcpkg-root-windows-v3-${{ hashFiles('Cargo.toml') }}
restore-keys: |
vcpkg-root-windows-v3-
- name: Validate vcpkg cache origin
shell: pwsh
run: |
$ErrorActionPreference = 'Continue'
$cacheInvalid = $false
$expectedRev = $null
$revLine = Select-String -Path Cargo.toml -Pattern '^rev = "' | Select-Object -First 1
if ($revLine) {
$expectedRev = $revLine.Line -replace '^rev = "' -replace '"$',''
}
if ((Test-Path "target/vcpkg") -and -not (Test-Path "target/vcpkg/.git")) {
Write-Host "vcpkg root missing .git; clearing cache entry"
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "target/vcpkg"
$cacheInvalid = $true
}
$dirs = @("target/vcpkg", "target/vcpkg/.vcpkg-root")
foreach ($dir in $dirs) {
try {
if (Test-Path "$dir/.git") {
$origin = git -C $dir remote get-url origin 2>$null
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($origin)) {
Write-Host "Failed to read vcpkg origin in $dir; clearing cache entry"
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $dir
$cacheInvalid = $true
continue
}
if ($origin -ne "https://github.com/microsoft/vcpkg.git" -and $origin -ne "https://github.com/microsoft/vcpkg") {
Write-Host "Unexpected vcpkg origin in : $origin"
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $dir
$cacheInvalid = $true
continue
}
if ($expectedRev) {
git -C $dir cat-file -e "$expectedRev^{tree}" 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Host "Missing vcpkg rev $expectedRev in $dir; clearing cache entry"
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $dir
$cacheInvalid = $true
}
}
}
} catch {
Write-Host "Failed to validate vcpkg origin in : $($_.Exception.Message)"
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $dir
$cacheInvalid = $true
}
}
if ($cacheInvalid) {
Add-Content $env:GITHUB_ENV "VCPKG_CACHE_INVALID=1"
}
exit 0
- name: Use cached vcpkg workspace
if: steps.vcpkg-root-cache-win.outputs.cache-hit == 'true' && env.VCPKG_CACHE_INVALID != '1'
shell: pwsh
run: Write-Host "vcpkg workspace cache hit; skipping dependency rebuild."
- name: Build vcpkg dependencies
if: steps.vcpkg-root-cache-win.outputs.cache-hit != 'true' || env.VCPKG_CACHE_INVALID == '1'
shell: pwsh
env:
VCPKG_FEATURE_FLAGS: manifests
VCPKG_CMAKE_CONFIGURE_OPTIONS: -Wno-dev -DCMAKE_POLICY_DEFAULT_CMP0174=NEW
VCPKG_MAX_CONCURRENCY: 2
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: |
$maxAttempts = 3
if (-not (Test-Path "target/vcpkg")) {
New-Item -ItemType Directory -Path "target/vcpkg" | Out-Null
}
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
Write-Host "vcpkg build attempt $attempt/$maxAttempts"
cargo vcpkg --verbose build
if ($LASTEXITCODE -eq 0) {
Write-Host "vcpkg build succeeded"
break
}
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue "target/vcpkg"
New-Item -ItemType Directory -Path "target/vcpkg" | Out-Null
if ($attempt -eq $maxAttempts) {
Write-Host "vcpkg build failed after $maxAttempts attempts"
exit $LASTEXITCODE
}
$sleepSeconds = 30 * $attempt
Write-Host "vcpkg build failed (exit $LASTEXITCODE). Retrying in $sleepSeconds seconds..."
Start-Sleep -Seconds $sleepSeconds
}
- name: Save vcpkg workspace cache
if: (steps.vcpkg-root-cache-win.outputs.cache-hit != 'true' || env.VCPKG_CACHE_INVALID == '1') && success()
uses: actions/cache/save@v4
with:
path: |
target/vcpkg/.vcpkg-root
target/vcpkg/.git
target/vcpkg/downloads
target/vcpkg/installed
target/vcpkg/packages
target/vcpkg/ports
target/vcpkg/scripts
target/vcpkg/triplets
target/vcpkg/vcpkg
target/vcpkg/vcpkg.exe
key: vcpkg-root-windows-v3-${{ hashFiles('Cargo.toml') }}
- name: Force regenerate rusty_ffmpeg bindings
run: cargo clean -p rusty_ffmpeg
- name: Upload vcpkg logs on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: vcpkg-logs-windows
path: |
target/vcpkg/buildtrees/**/*.log
target/vcpkg/buildtrees/**/*.txt
retention-days: 7
- name: Run tests
shell: pwsh
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
RUSTFLAGS: ${{ env.RUSTFLAGS }}
RUSTDOCFLAGS: >-
-C target-feature=+crt-static
-C link-arg=Mfplat.lib
-C link-arg=Strmiids.lib
-C link-arg=Mfuuid.lib
-C link-arg=Bcrypt.lib
-C link-arg=Ncrypt.lib
-C link-arg=Crypt32.lib
-C link-arg=Secur32.lib
-C link-arg=Ole32.lib
-C link-arg=User32.lib
DPN_OCR_GOLDEN: "1"
DPN_OCR_AI_E2E: "1"
DPN_OCR_MODEL_DIR: ${{ github.workspace }}\\target\\ocr-models
run: |
$start = Get-Date
$threads = [Math]::Max(1, [int]$env:NUMBER_OF_PROCESSORS)
cargo test -q --lib --bins --tests -- --test-threads $threads
cargo test --features ffmpeg-cli-tests -- --test-threads $threads
$elapsed = (Get-Date) - $start
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "### Windows runtime"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Toolchain: stable"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- vcpkg cache hit: ${{ steps.vcpkg-root-cache-win.outputs.cache-hit }}"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Test command: cargo test --lib --bins --tests"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value "- Includes ffmpeg-cli-tests runtime execution: yes"
Add-Content -Path $env:GITHUB_STEP_SUMMARY -Value ("- Duration: {0}s" -f [int]$elapsed.TotalSeconds)
- name: sccache stats
if: ${{ env.RUSTC_WRAPPER == 'sccache' }}
shell: pwsh
run: sccache --show-stats; if ($LASTEXITCODE -ne 0) { exit 0 }
macos-test:
name: Test (macOS ${{ matrix.name }})
if: ${{ github.event_name != 'pull_request' || (!contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.body, '[skip ci]')) }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
actions: write
strategy:
fail-fast: false
matrix:
include:
- name: Intel
runner: macos-15-intel
cache_suffix: macos-intel
- name: Apple Silicon
runner: macos-15
cache_suffix: macos-arm64
env:
CARGO_TERM_COLOR: always
VCPKG_ROOT: ${{ github.workspace }}/target/vcpkg
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Set up sccache
id: sccache-setup
uses: mozilla-actions/sccache-action@v0.0.5
continue-on-error: true
- name: Set job-level RUSTC_WRAPPER
if: steps.sccache-setup.outcome == 'success'
run: echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV"
- name: Clear RUSTC_WRAPPER on sccache failure
if: steps.sccache-setup.outcome == 'failure'
run: echo "RUSTC_WRAPPER=" >> "$GITHUB_ENV"
- name: Install dependencies
run: |
brew install nasm autoconf autoconf-archive automake libtool pkg-config
- name: Cache cargo-vcpkg binary
id: cargo-vcpkg-cache-macos
uses: actions/cache@v4
with:
path: ~/.cargo/bin/cargo-vcpkg
key: cargo-vcpkg-${{ matrix.cache_suffix }}-v1
- name: Install cargo-vcpkg
if: steps.cargo-vcpkg-cache-macos.outputs.cache-hit != 'true'
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: cargo install cargo-vcpkg --locked
- name: Cache cargo build artifacts
uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.cache_suffix }}-vcpkg-v1-ffmpeg8
- name: Restore vcpkg workspace (cross-branch)
id: vcpkg-root-cache-macos
uses: actions/cache/restore@v4
with:
path: |
target/vcpkg/.vcpkg-root
target/vcpkg/.git
target/vcpkg/downloads
target/vcpkg/installed
target/vcpkg/packages
target/vcpkg/ports
target/vcpkg/scripts
target/vcpkg/triplets
target/vcpkg/vcpkg
key: vcpkg-root-${{ matrix.cache_suffix }}-v1-${{ hashFiles('Cargo.toml') }}
restore-keys: |
vcpkg-root-${{ matrix.cache_suffix }}-v1-
- name: Validate vcpkg cache origin
run: |
cache_invalid=0
expected_rev="$(grep -E '^rev = "' Cargo.toml | head -n1 | awk -F'"' '{print $2}')"
if [ -e "target/vcpkg" ] && [ ! -e "target/vcpkg/.git" ]; then
echo "vcpkg root missing .git; clearing cache entry"
rm -rf target/vcpkg
cache_invalid=1
fi
for dir in target/vcpkg target/vcpkg/.vcpkg-root target/vcpkg/vcpkg; do
if [ -e "$dir/.git" ]; then
origin=$(git -C "$dir" remote get-url origin 2>/dev/null || true)
if [ -z "$origin" ]; then
echo "Failed to read vcpkg origin in $dir; clearing cache entry"
rm -rf "$dir"
cache_invalid=1
continue
fi
if [ "$origin" != "https://github.com/microsoft/vcpkg.git" ] && [ "$origin" != "https://github.com/microsoft/vcpkg" ]; then
echo "Unexpected vcpkg origin in $dir: $origin"
rm -rf "$dir"
cache_invalid=1
continue
fi
if [ -n "$expected_rev" ]; then
if ! git -C "$dir" cat-file -e "${expected_rev}^{tree}" 2>/dev/null; then
echo "Missing vcpkg rev $expected_rev in $dir; clearing cache entry"
rm -rf "$dir"
cache_invalid=1
fi
fi
fi
done
if [ "$cache_invalid" -eq 1 ]; then
echo "VCPKG_CACHE_INVALID=1" >> "$GITHUB_ENV"
fi
- name: Use cached vcpkg workspace
if: steps.vcpkg-root-cache-macos.outputs.cache-hit == 'true' && env.VCPKG_CACHE_INVALID != '1'
run: echo "vcpkg workspace cache hit; skipping dependency rebuild."
- name: Build vcpkg dependencies
if: steps.vcpkg-root-cache-macos.outputs.cache-hit != 'true' || env.VCPKG_CACHE_INVALID == '1'
env:
VCPKG_BUILD_TYPE: release
VCPKG_FEATURE_FLAGS: manifests,binarycaching
VCPKG_BINARY_SOURCES: clear;x-gha,readwrite
VCPKG_CMAKE_CONFIGURE_OPTIONS: -Wno-dev -DCMAKE_POLICY_DEFAULT_CMP0174=NEW
VCPKG_MAX_CONCURRENCY: 2
CMAKE_BUILD_PARALLEL_LEVEL: 2
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
run: cargo vcpkg --verbose build
- name: Save vcpkg workspace cache
if: (steps.vcpkg-root-cache-macos.outputs.cache-hit != 'true' || env.VCPKG_CACHE_INVALID == '1') && success()
uses: actions/cache/save@v4
with:
path: |
target/vcpkg/.vcpkg-root
target/vcpkg/.git
target/vcpkg/downloads
target/vcpkg/installed
target/vcpkg/packages
target/vcpkg/ports
target/vcpkg/scripts
target/vcpkg/triplets
target/vcpkg/vcpkg
key: vcpkg-root-${{ matrix.cache_suffix }}-v1-${{ hashFiles('Cargo.toml') }}
- name: Force regenerate rusty_ffmpeg bindings
run: cargo clean -p rusty_ffmpeg
- name: Upload vcpkg logs on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: vcpkg-logs-${{ matrix.cache_suffix }}
path: |
target/vcpkg/buildtrees/**/*.log
target/vcpkg/buildtrees/**/*.txt
retention-days: 7
- name: Run tests
env:
RUSTC_WRAPPER: ${{ env.RUSTC_WRAPPER }}
VCPKG_ROOT: ${{ env.VCPKG_ROOT }}
DPN_OCR_GOLDEN: "1"
run: |
start=$(date +%s)
cargo test -q --lib --bins --tests
cargo test -q --features ffmpeg-cli-tests --no-run
end=$(date +%s)
echo "### macOS test runtime" >> "$GITHUB_STEP_SUMMARY"
echo "- Toolchain: stable" >> "$GITHUB_STEP_SUMMARY"
echo "- Runner: ${{ matrix.runner }}" >> "$GITHUB_STEP_SUMMARY"
echo "- vcpkg cache hit: ${{ steps.vcpkg-root-cache-macos.outputs.cache-hit }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Test command: cargo test --lib --bins --tests" >> "$GITHUB_STEP_SUMMARY"
echo "- Integration compile check: cargo test --features ffmpeg-cli-tests --no-run" >> "$GITHUB_STEP_SUMMARY"
echo "- Duration: $((end-start))s" >> "$GITHUB_STEP_SUMMARY"
- name: sccache stats
if: ${{ env.RUSTC_WRAPPER == 'sccache' }}
run: sccache --show-stats || true
ocr-gpu-self-hosted:
name: OCR GPU (Self-Hosted)
if: ${{ vars.ENABLE_GPU_CI == '1' && (github.event_name != 'pull_request' || (!contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.body, '[skip ci]'))) }}
runs-on: [self-hosted, linux, x64, gpu]
timeout-minutes: 90
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
VCPKG_ROOT: ${{ github.workspace }}/target/vcpkg
DPN_OCR_REQUIRE_GPU: "1"
DPN_OCR_GPU_E2E: "1"
DPN_OCR_AI_E2E: "1"
DPN_OCR_GOLDEN: "1"
DPN_OCR_MODEL_DIR: ${{ github.workspace }}/target/ocr-models
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get --assume-yes install nasm ffmpeg autoconf autoconf-archive automake libtool
- name: Install cargo-vcpkg
run: cargo install cargo-vcpkg --locked
- name: Build vcpkg dependencies
env:
VCPKG_BUILD_TYPE: release
VCPKG_FEATURE_FLAGS: manifests,binarycaching
VCPKG_CMAKE_CONFIGURE_OPTIONS: -Wno-dev -DCMAKE_POLICY_DEFAULT_CMP0174=NEW
VCPKG_MAX_CONCURRENCY: 2
CMAKE_BUILD_PARALLEL_LEVEL: 2
run: cargo vcpkg --verbose build
- name: Run GPU OCR smoke tests
run: |
cargo test -q --lib --bins test_gpu_requirement_env_gate -- --nocapture
cargo test -q --features ffmpeg-cli-tests --test cli_bitmap_subs cli_ai_ocr_gpu_processes_all_bitmap_subtitle_streams -- --nocapture