name: CI on: push: pull_request: schedule: # Daily at 03:17 UTC to keep ccache/dependency caches warm - cron: '17 3 * * *' jobs: build-test: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-24.04, macos-15, windows-latest] env: CMAKE_BUILD_TYPE: Release CCACHE_DIR: ${{ github.workspace }}/.ccache CCACHE_MAXSIZE: 1G # Enable OFX integration tests that require external plugin bundles RUN_OFX_ITEST: "1" # Enable plugin subsystem smoke tests OAK_PLUGIN_SMOKE_TEST: "1" steps: - uses: actions/checkout@v4 with: submodules: 'true' # ------------------------------------------------------------------ # Linux dependencies # ------------------------------------------------------------------ - name: Install dependencies (Linux) if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y \ ninja-build pkg-config nasm \ qt6-base-dev qt6-base-dev-tools qt6-base-private-dev qt6-tools-dev qt6-tools-dev-tools \ libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libavfilter-dev \ libopencolorio-dev libopenimageio-dev libopenexr-dev libexpat1-dev \ portaudio19-dev libgl1-mesa-dev libxkbcommon-dev ccache # ------------------------------------------------------------------ # macOS dependencies # ------------------------------------------------------------------ - name: Install dependencies (macOS) if: runner.os == 'macOS' run: | brew update brew install ninja pkg-config ccache qt@6 ffmpeg openimageio opencolorio openexr portaudio expat molten-vk vulkan-headers echo "$(brew --prefix qt@6)/bin" >> "$GITHUB_PATH" echo "CMAKE_PREFIX_PATH=$(brew --prefix qt@6)" >> "$GITHUB_ENV" # ------------------------------------------------------------------ # OpenTimelineIO (required dependency, built from source; cached) # ------------------------------------------------------------------ - name: Cache OpenTimelineIO (Unix) if: runner.os != 'Windows' id: otio-cache uses: actions/cache@v4 with: path: otio-install key: otio-0.16.0-${{ runner.os }}-v1 - name: Set OTIO location (Unix) if: runner.os != 'Windows' run: echo "OTIO_LOCATION=${PWD}/otio-install" >> "$GITHUB_ENV" - name: Build OpenTimelineIO (Unix) if: runner.os != 'Windows' && steps.otio-cache.outputs.cache-hit != 'true' run: | git clone --depth 1 --branch v0.16.0 https://github.com/PixarAnimationStudios/OpenTimelineIO.git cmake -S OpenTimelineIO -B OpenTimelineIO/build -G Ninja \ -DOTIO_SHARED_LIBS=ON \ -DOTIO_PYTHON_BINDINGS=OFF \ -DOTIO_FIND_IMATH=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX="${PWD}/otio-install" cmake --build OpenTimelineIO/build cmake --install OpenTimelineIO/build # ------------------------------------------------------------------ # Windows dependencies (MSYS2) # ------------------------------------------------------------------ - name: Setup MSYS2 if: runner.os == 'Windows' uses: msys2/setup-msys2@v2 with: msystem: UCRT64 update: true cache: true install: >- mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-qt6-base mingw-w64-ucrt-x86_64-qt6-tools mingw-w64-ucrt-x86_64-ffmpeg mingw-w64-ucrt-x86_64-openimageio mingw-w64-ucrt-x86_64-opencolorio mingw-w64-ucrt-x86_64-openexr mingw-w64-ucrt-x86_64-fmt mingw-w64-ucrt-x86_64-expat mingw-w64-ucrt-x86_64-portaudio mingw-w64-ucrt-x86_64-vulkan-headers mingw-w64-ucrt-x86_64-vulkan-loader mingw-w64-ucrt-x86_64-make mingw-w64-ucrt-x86_64-ccache # ------------------------------------------------------------------ # OpenTimelineIO (required dependency, built from source; cached). # Must come after Setup MSYS2 (uses the msys2 shell). # ------------------------------------------------------------------ - name: Cache OpenTimelineIO (Windows) if: runner.os == 'Windows' id: otio-cache-win uses: actions/cache@v4 with: path: otio-install key: otio-0.16.0-${{ runner.os }}-v1 - name: Set OTIO location (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: | echo "OTIO_LOCATION=${PWD}/otio-install" >> "$GITHUB_ENV" # No rpath on Windows: test executables need the OTIO DLLs on PATH echo "$(cygpath -w "${PWD}/otio-install/bin")" >> "$GITHUB_PATH" - name: Build OpenTimelineIO (Windows) if: runner.os == 'Windows' && steps.otio-cache-win.outputs.cache-hit != 'true' shell: msys2 {0} run: | git clone --depth 1 --branch v0.16.0 https://github.com/PixarAnimationStudios/OpenTimelineIO.git cmake -S OpenTimelineIO -B OpenTimelineIO/build -G Ninja \ -DOTIO_SHARED_LIBS=ON \ -DOTIO_PYTHON_BINDINGS=OFF \ -DOTIO_FIND_IMATH=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX="${PWD}/otio-install" cmake --build OpenTimelineIO/build cmake --install OpenTimelineIO/build # ------------------------------------------------------------------ # Compile cache (ccache) — restored before configure so the launcher # flags below pick it up on all three platforms # ------------------------------------------------------------------ - name: Restore ccache uses: actions/cache@v4 with: path: ${{ github.workspace }}/.ccache key: ccache-${{ runner.os }}-${{ github.ref_name }}-${{ github.sha }} restore-keys: | ccache-${{ runner.os }}-${{ github.ref_name }}- ccache-${{ runner.os }}- # ------------------------------------------------------------------ # Configure # ------------------------------------------------------------------ - name: Configure (Linux) if: runner.os == 'Linux' run: | cmake -S . -B build -G Ninja \ -DBUILD_TESTS=ON \ -DBUILD_QT6=ON \ -DCMAKE_DISABLE_FIND_PACKAGE_Vulkan=ON \ -DOCIO_LOCATION=/usr \ -DOTIO_LOCATION=${OTIO_LOCATION} \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - name: Configure (macOS) if: runner.os == 'macOS' run: | cmake -S . -B build -G Ninja \ -DBUILD_TESTS=ON \ -DBUILD_QT6=ON \ -DOCIO_LOCATION=$(brew --prefix opencolorio) \ -DOTIO_LOCATION=${OTIO_LOCATION} \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - name: Configure (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: | cmake -S . -B build -G Ninja \ -DBUILD_TESTS=ON \ -DBUILD_QT6=ON \ -DOTIO_LOCATION=${OTIO_LOCATION} \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} # ------------------------------------------------------------------ # Build Oak # ------------------------------------------------------------------ - name: Build if: runner.os != 'Windows' run: | cmake --build build --config ${{ env.CMAKE_BUILD_TYPE }} ccache -s - name: Build (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: | cmake --build build --config ${{ env.CMAKE_BUILD_TYPE }} ccache -s # ------------------------------------------------------------------ # Clone and build OpenFX-Misc plugins (used by OFX integration tests) # ------------------------------------------------------------------ - name: Clone OpenFX-Misc run: git clone --recursive --depth 1 https://github.com/NatronGitHub/openfx-misc.git - name: Build OpenFX-Misc plugins (Unix) if: runner.os != 'Windows' run: | cd openfx-misc make -j"$(nproc)" sudo make install PLUGIN_FILE=$(find /usr/OFX/Plugins /usr/local/OFX/Plugins . -name "*.ofx.bundle" -print -quit 2>/dev/null | head -1) if [ -n "$PLUGIN_FILE" ]; then PLUGIN_DIR=$(dirname "$PLUGIN_FILE") else PLUGIN_DIR="$PWD" fi echo "OAK_OFX_ITEST=1" >> "$GITHUB_ENV" echo "OAK_OFX_PLUGIN_PATH=$PLUGIN_DIR" >> "$GITHUB_ENV" echo "OAK_OFX_PLUGIN_ID=net.sf.openfx.ChromaKeyerPlugin" >> "$GITHUB_ENV" # ------------------------------------------------------------------ # Run all tests (including previously environment-gated OFX tests) # ------------------------------------------------------------------ - name: Test (Linux) if: runner.os == 'Linux' env: QT_QPA_PLATFORM: offscreen run: ctest --test-dir build --output-on-failure -C ${{ env.CMAKE_BUILD_TYPE }} - name: Test (macOS) if: runner.os == 'macOS' run: ctest --test-dir build --output-on-failure -C ${{ env.CMAKE_BUILD_TYPE }} - name: Test (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: ctest --test-dir build --output-on-failure -C ${{ env.CMAKE_BUILD_TYPE }} # ------------------------------------------------------------------ # Filtered gtest runs for clearer CI output # ------------------------------------------------------------------ - name: Plugin Smoke Tests (Linux) if: runner.os == 'Linux' env: QT_QPA_PLATFORM: offscreen run: ./build/tests/gtest/olive-gtest --gtest_filter="PluginSmoke*" - name: Plugin Smoke Tests (macOS) if: runner.os == 'macOS' run: ./build/tests/gtest/olive-gtest --gtest_filter="PluginSmoke*" - name: Plugin Smoke Tests (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: ./build/tests/gtest/olive-gtest --gtest_filter="PluginSmoke*" - name: OFX Integration Tests (Linux) if: runner.os == 'Linux' env: QT_QPA_PLATFORM: offscreen run: ./build/tests/gtest/olive-gtest --gtest_filter="PluginIntegration.*:PluginMisc.*" - name: OFX Integration Tests (macOS) if: runner.os == 'macOS' run: ./build/tests/gtest/olive-gtest --gtest_filter="PluginIntegration.*:PluginMisc.*" - name: Audio Smoke Tests (Linux) if: runner.os == 'Linux' env: QT_QPA_PLATFORM: offscreen run: ./build/tests/gtest/olive-gtest --gtest_filter="AudioSmoke*" - name: Audio Smoke Tests (macOS) if: runner.os == 'macOS' run: ./build/tests/gtest/olive-gtest --gtest_filter="AudioSmoke*" - name: Audio Smoke Tests (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: ./build/tests/gtest/olive-gtest --gtest_filter="AudioSmoke*" - name: Viewer Smoke Tests (Linux) if: runner.os == 'Linux' env: QT_QPA_PLATFORM: offscreen run: ./build/tests/gtest/olive-gtest --gtest_filter="ViewerSmoke*" - name: Viewer Smoke Tests (macOS) if: runner.os == 'macOS' run: ./build/tests/gtest/olive-gtest --gtest_filter="ViewerSmoke*" - name: Viewer Smoke Tests (Windows) if: runner.os == 'Windows' shell: msys2 {0} run: ./build/tests/gtest/olive-gtest --gtest_filter="ViewerSmoke*"