name: CD on: push: tags: - 'v*' workflow_dispatch: permissions: contents: write jobs: # ------------------------------------------------------------------ # Linux: deb + AppImage + pacman in one job. cargo-packager does not # support rpm (its format list is deb/appimage/pacman/nsis/dmg/app/wix), # and its "pacman" format emits a PKGBUILD + source tarball rather than a # compiled pkg.tar.zst — both are upstream limitations. # ------------------------------------------------------------------ # ------------------------------------------------------------------ # Linux: one native package per distro, each built INSIDE that # distro's container so the declared dependencies always resolve to # the distro's own package names (dpkg-shlibdeps / rpmbuild # auto-requires / Arch static base list). deb: hand-rolled dpkg-deb; # rpm: rpmbuild; arch: makepkg. AppImage stays on the Ubuntu runner # (self-contained by design). # ------------------------------------------------------------------ linux: name: Linux packages (${{ matrix.distro }}) runs-on: warp-ubuntu-latest-x64-8x container: ${{ matrix.image }} strategy: fail-fast: false matrix: include: - distro: debian image: debian:12 - distro: fedora image: fedora:41 - distro: arch image: archlinux:latest steps: # git/curl must land BEFORE actions/checkout runs inside the # container. - name: Install git and fetch tools run: | case "${{ matrix.distro }}" in debian) apt-get update && apt-get install -y git curl ;; fedora) dnf install -y git curl ;; arch) pacman -Sy --noconfirm git curl ;; esac - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Install Rust (stable) uses: dtolnay/rust-toolchain@stable - name: Install system dependencies run: | case "${{ matrix.distro }}" in debian) apt-get install -y \ build-essential cmake pkg-config nasm dpkg-dev \ libpipewire-0.3-dev libspa-0.2-dev libjack-jackd2-dev \ libasound2-dev libpulse-dev libsndfile1-dev \ libgl1-mesa-dev libgl1-mesa-dri mesa-vulkan-drivers \ libvulkan-dev libxkbcommon-dev libxkbcommon-x11-dev \ librsvg2-bin ;; fedora) dnf install -y \ gcc gcc-c++ cmake pkgconf-pkg-config nasm \ pipewire-devel jack-audio-connection-kit-devel \ alsa-lib-devel pulseaudio-libs-devel libsndfile-devel \ mesa-libGL-devel mesa-vulkan-drivers \ vulkan-headers vulkan-loader-devel \ libxkbcommon-devel libxkbcommon-x11-devel \ rpm-build librsvg2-tools ;; arch) pacman -S --needed --noconfirm \ base-devel cmake pkgconf nasm \ pipewire jack2 alsa-lib libpulse libsndfile \ mesa vulkan-headers vulkan-icd-loader \ libxkbcommon libxkbcommon-x11 librsvg ;; esac - name: Configure build environment run: | # OCIO builds from the ocio-sys vendored source (static) on # Linux; the distro packages are too old for the bridge. echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV" echo "OCIO_RS_LINK=static" >> "$GITHUB_ENV" - name: Cache cargo artifacts uses: Swatinem/rust-cache@v2 with: shared-key: oak-${{ matrix.distro }} - name: Cache project FFmpeg uses: actions/cache@v4 with: path: .cache/ffmpeg key: ffmpeg-${{ matrix.distro }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }} - name: Build project FFmpeg (static, GPL + free codecs + hwaccel) run: tooling/ffmpeg/build-ffmpeg.sh - name: Build (release) run: cargo build --release --locked - name: Generate app icon (PNG from Oak_Icon.svg) run: rsvg-convert -w 512 -h 512 Oak_Icon.svg -o icons/icon.png - name: Package run: | set -euo pipefail VERSION="${GITHUB_REF_NAME#v}" if [ "$VERSION" = "$GITHUB_REF_NAME" ]; then VERSION="$(cargo pkgid | sed 's/.*#//' | cut -d@ -f2-)+git" fi case "${{ matrix.distro }}" in debian) tooling/package/build-deb.sh "$VERSION" ;; fedora) tooling/package/build-rpm.sh "$VERSION" ;; arch) tooling/package/build-pkg.sh "$VERSION" ;; esac shell: bash - name: Upload artifact uses: actions/upload-artifact@v4 with: name: oak-linux-${{ matrix.distro }} path: | target/release/*.deb target/release/*.rpm target/release/*.pkg.tar.zst if-no-files-found: error # ------------------------------------------------------------------ # AppImage (self-contained; cargo-packager on the Ubuntu runner). # ------------------------------------------------------------------ appimage: name: Linux AppImage runs-on: warp-ubuntu-latest-x64-8x steps: - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Install Rust (stable) uses: dtolnay/rust-toolchain@stable - name: Install system dependencies run: | tooling/install-deps.sh sudo apt-get install -y \ cmake librsvg2-bin \ libpipewire-0.3-dev libspa-0.2-dev libjack-jackd2-dev \ libasound2-dev libpulse-dev libsndfile1-dev \ libgl1-mesa-dev libgl1-mesa-dri mesa-vulkan-drivers \ libvulkan-dev libxkbcommon-dev libxkbcommon-x11-dev - name: Configure build environment run: | echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV" echo "OCIO_RS_LINK=static" >> "$GITHUB_ENV" - name: Cache cargo artifacts uses: Swatinem/rust-cache@v2 with: shared-key: oak-appimage - name: Cache project FFmpeg uses: actions/cache@v4 with: path: .cache/ffmpeg key: ffmpeg-appimage-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }} - name: Build project FFmpeg (static, GPL + free codecs + hwaccel) run: tooling/ffmpeg/build-ffmpeg.sh - name: Install cargo-packager run: cargo install cargo-packager --locked - name: Generate app icon (PNG from Oak_Icon.svg) run: | mkdir -p icons rsvg-convert -w 512 -h 512 Oak_Icon.svg -o icons/icon.png file icons/icon.png - name: Build (release) run: cargo build --release --locked - name: Package (AppImage) run: cargo packager --release --formats appimage - name: Upload artifact uses: actions/upload-artifact@v4 with: name: oak-linux-appimage path: target/release/*.AppImage if-no-files-found: error macos: name: macOS DMG (Apple Silicon) runs-on: warp-macos-15-arm64-6x steps: - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Install Rust (stable) uses: dtolnay/rust-toolchain@stable - name: Install system dependencies run: | tooling/install-deps.sh brew install cmake librsvg - name: Configure build environment run: | { # OCIO comes from the ocio-sys vendored source build (same on # every platform); no OCIO_INSTALL_DIR override. echo "OCIO_RS_ENABLE_REAL=1" echo "OCIO_RS_LINK=static" echo "CFLAGS=-I/opt/homebrew/include" echo "LDFLAGS=-L/opt/homebrew/lib" echo "PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig/openjpeg" } >> "$GITHUB_ENV" - name: Cache cargo artifacts uses: Swatinem/rust-cache@v2 with: shared-key: oak-workspace - name: Cache project FFmpeg uses: actions/cache@v4 with: path: .cache/ffmpeg key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }} - name: Build project FFmpeg (static, GPL + free codecs + hwaccel) run: | tooling/ffmpeg/build-ffmpeg.sh echo "FFMPEG_DIR=$PWD/.cache/ffmpeg" >> "$GITHUB_ENV" - name: Install cargo-packager run: cargo install cargo-packager --locked - name: Generate app icon (PNG from Oak_Icon.svg) run: | mkdir -p icons # cargo-packager's tauri-icns 0.1.0 maps only 512x512@1x (and # 1024x1024@2x); a plain 1024x1024 PNG aborts with "No matching # IconType", so render 512x512. rsvg-convert -w 512 -h 512 Oak_Icon.svg -o icons/icon.png file icons/icon.png # Build the packaged binaries (default members: the app, oak-cli, # oak-worker). - name: Build (release) run: cargo build --release --locked - name: Package .app bundle run: cargo packager --release --formats app - name: Create DMG run: | rm -rf dmg-staging mkdir -p dmg-staging cp -R target/release/Oak.app dmg-staging/ ln -s /Applications dmg-staging/Applications hdiutil create -volname "Oak Video Editor" \ -srcfolder dmg-staging -ov -format UDZO Oak-macOS-arm64.dmg - name: Upload artifact uses: actions/upload-artifact@v4 with: name: oak-macos path: Oak-macOS-arm64.dmg if-no-files-found: error # ------------------------------------------------------------------ # Windows: NSIS installer (restored; cargo-packager downloads its own # makensis, SHA-1 verified). The obsolete `-p oakengine` cdylib prebuild # from before M14 R4 is dropped — no packaged binary links the cdylib. # ------------------------------------------------------------------ windows: name: Windows installer (NSIS) runs-on: warp-windows-latest-x64-16x defaults: run: shell: msys2 {0} steps: - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Install Rust (stable) uses: dtolnay/rust-toolchain@stable - name: Setup MSYS2 uses: msys2/setup-msys2@v2 with: msystem: UCRT64 update: true # MSYS2's own Rust targets x86_64-pc-windows-gnu by default — # the Windows build is GNU-target (the MSVC linker rejects the # Unix-style link args the build scripts emit). install: >- git mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-rust - name: Install system dependencies run: | bash tooling/install-deps.sh pacman -S --needed --noconfirm \ mingw-w64-ucrt-x86_64-cmake \ mingw-w64-ucrt-x86_64-opencolorio \ mingw-w64-ucrt-x86_64-librsvg - name: Configure build environment run: | # Windows uses the MSYS2 OpenColorIO package (the exact 2.5.2 the # bridge targets; the vendored source needs MSVC-only constructs). # Dynamic; the DLLs are packaged next to the binaries. echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV" echo "OCIO_INSTALL_DIR=/ucrt64" >> "$GITHUB_ENV" echo "OCIO_RS_LINK=dynamic" >> "$GITHUB_ENV" # ocio-sys' build.rs force-adds the MSVC + Windows SDK include # dirs on Windows (meant for MSVC hosts); with the GNU toolchain # that drags MSVC-only headers into the g++ compile. Unpack the # crate and gate that block behind OCIO_RS_NO_MSVC_INCLUDES. echo "OCIO_RS_NO_MSVC_INCLUDES=1" >> "$GITHUB_ENV" CH=$(cygpath -u "${CARGO_HOME:-$HOME/.cargo}") cargo fetch --locked for cache in "$CH"/registry/cache/*/; do src="$CH/registry/src/$(basename "$cache")" mkdir -p "$src" [ -f "$cache/ocio-sys-0.2.1.crate" ] && tar xzf "$cache/ocio-sys-0.2.1.crate" -C "$src" done BS=$(ls "$CH"/registry/src/*/ocio-sys-0.2.1/build.rs) grep -q 'OCIO_RS_NO_MSVC_INCLUDES' "$BS" || sed -i \ 's|if cfg!(target_os = "windows") && has_real_ocio {|if cfg!(target_os = "windows") \&\& has_real_ocio \&\& std::env::var_os("OCIO_RS_NO_MSVC_INCLUDES").is_none() {|' \ "$BS" grep -q 'OCIO_RS_NO_MSVC_INCLUDES' "$BS" - name: Cache cargo artifacts uses: Swatinem/rust-cache@v2 with: shared-key: oak-workspace - name: Cache project FFmpeg uses: actions/cache@v4 with: path: .cache/ffmpeg key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }} - name: Build project FFmpeg (static, GPL + free codecs + hwaccel) run: | bash tooling/ffmpeg/build-ffmpeg.sh echo "FFMPEG_DIR=$(cygpath -m "$PWD/.cache/ffmpeg")" >> "$GITHUB_ENV" - name: Install cargo-packager run: cargo install cargo-packager --locked - name: Generate app icon (PNG from Oak_Icon.svg) run: | mkdir -p icons rsvg-convert -w 512 -h 512 Oak_Icon.svg -o icons/icon.png - name: Build (release) run: | # Clear the job-hook-injected MSVC INCLUDE/LIB before the GNU # build (they poison the MinGW compiles with MSVC SDK headers). unset INCLUDE LIB cargo build --release --locked - name: Package (NSIS) run: cargo packager --release --formats nsis - name: Upload artifact uses: actions/upload-artifact@v4 with: name: oak-windows path: target/release/*-setup.exe if-no-files-found: error # ------------------------------------------------------------------ # Publish: attach every platform package to the v* tag's GitHub release # (skipped on workflow_dispatch, which only uploads artifacts). # ------------------------------------------------------------------ release: name: Publish GitHub release needs: [linux, appimage, macos, windows] if: startsWith(github.ref, 'refs/tags/v') runs-on: warp-ubuntu-latest-x64-8x steps: - name: Download all artifacts uses: actions/download-artifact@v4 with: path: artifacts merge-multiple: true - name: Publish release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} name: ${{ github.ref_name }} draft: false files: artifacts/*