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: name: Linux packages (deb, AppImage, pacman) 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 # Real OpenColorIO (ocio-sys real bridge) + rsvg-convert for the # app icon (cargo-packager needs PNG/icns/ico, the repo only has # Oak_Icon.svg). sudo apt-get install -y \ libopencolorio-dev \ librsvg2-bin \ libgl1-mesa-dev libgl1-mesa-dri mesa-vulkan-drivers \ libvulkan-dev libxkbcommon-dev - name: Configure build environment run: | echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV" echo "OCIO_INSTALL_DIR=/usr" >> "$GITHUB_ENV" echo "OCIO_RS_LINK=dynamic" >> "$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 rsvg-convert -w 1024 -h 1024 Oak_Icon.svg -o icons/icon.png file icons/icon.png - name: Build (release) run: cargo build --release --locked - name: Package (deb, AppImage, pacman) run: cargo packager --release --formats deb,appimage,pacman # cargo-packager has no rpm format; convert the deb with fpm. - name: Package (rpm, via fpm) run: | sudo apt-get install -y ruby ruby-dev rpm sudo gem install --no-document fpm fpm -s deb -t rpm --name oak-editor \ --version "$(cargo pkgid | sed 's/.*#//' | cut -d@ -f2-)" \ target/release/*.deb mv ./*.rpm target/release/ - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: oak-linux path: | target/release/*.deb target/release/*.rpm target/release/*.AppImage target/release/*.tar.gz target/release/PKGBUILD if-no-files-found: error # ------------------------------------------------------------------ # macOS: Apple Silicon only. cargo-packager cannot fold liboakengine.dylib # into the bundle (no post-packaging hook; the .app is rebuilt on every # run), so we package the .app with cargo-packager, embed the dylib next # to the binaries with install_name_tool, ad-hoc re-sign, then create the # DMG with hdiutil (the same way the old C++ CD did). # ------------------------------------------------------------------ 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 opencolorio librsvg - name: Configure build environment run: | echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV" echo "OCIO_INSTALL_DIR=/opt/homebrew/opt/opencolorio" >> "$GITHUB_ENV" echo "OCIO_RS_LINK=dynamic" >> "$GITHUB_ENV" echo "CFLAGS=-I/opt/homebrew/include" >> "$GITHUB_ENV" echo "LDFLAGS=-L/opt/homebrew/lib" >> "$GITHUB_ENV" 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 rsvg-convert -w 1024 -h 1024 Oak_Icon.svg -o icons/icon.png file icons/icon.png - name: Build (release) run: cargo build --release --locked - name: Package .app bundle run: cargo packager --release --formats app - name: Embed liboakengine.dylib and re-sign run: | set -euo pipefail APP="target/release/Oak.app" MACOS="$APP/Contents/MacOS" # The dylib lands in target/release/deps/ (dependency build) or # target/release/ (workspace-member build), possibly hash-suffixed. DYLIB="$(find target/release -name 'liboakengine.dylib' | head -1)" test -n "$DYLIB" && test -f "$DYLIB" cp "$DYLIB" "$MACOS/liboakengine.dylib" install_name_tool -id "@executable_path/liboakengine.dylib" "$MACOS/liboakengine.dylib" # build.rs links the app against the dylib's absolute build path; # point every binary that references it at the bundled copy. for bin in oak-editor oak-cli oak-worker; do if otool -L "$MACOS/$bin" 2>/dev/null | grep -q "liboakengine.dylib"; then REF="$(otool -L "$MACOS/$bin" | awk '/liboakengine/ {print $1; exit}')" install_name_tool -change "$REF" "@executable_path/liboakengine.dylib" "$MACOS/$bin" fi done # install_name_tool invalidates the packager's ad-hoc signature. codesign --force --deep --sign - "$APP" codesign -dv "$APP" 2>&1 | head -3 - 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. cargo-packager downloads its own NSIS # toolchain (SHA-1 verified) — no makensis install needed. # ------------------------------------------------------------------ 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 install: >- git mingw-w64-ucrt-x86_64-gcc - name: Install system dependencies run: | bash tooling/install-deps.sh pacman -S --needed --noconfirm \ mingw-w64-ucrt-x86_64-opencolorio \ mingw-w64-ucrt-x86_64-librsvg - name: Configure build environment run: | echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV" echo "OCIO_INSTALL_DIR=/ucrt64" >> "$GITHUB_ENV" echo "OCIO_RS_LINK=dynamic" >> "$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: | 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 1024 -h 1024 Oak_Icon.svg -o icons/icon.png - name: Build (release) run: 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, macos, windows] if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest 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/*