Files
oak-editor/.github/workflows/cd.yml
T
Mike-Solar 726b7d6a60 ci: invoke ocio-env.sh through bash (no exec bit needed)
The script has no executable bit (git doesn't carry one reliably), so
the bare  invocation failed with 'Permission
denied' in the Linux act runs. Every call site now uses
OCIO_RS_ENABLE_REAL=1
OCIO_RS_LINK=static instead.
2026-09-02 09:53:56 +08:00

456 lines
17 KiB
YAML

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
# ffnvcodec headers (NVDEC for the project FFmpeg build) are
# NOT in Ubuntu/Debian's apt index under a stable name
# (the old libffnvcodec-dev was dropped from noble; the
# community replacement is distro-version specific). The
# headers are distribution-free, so install them from
# source like the Fedora branch.
git clone --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git /tmp/nv-codec-headers
make -C /tmp/nv-codec-headers install PREFIX=/usr
;;
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
# ffnvcodec headers (NVDEC for the project FFmpeg build) are
# not in Fedora's base repos (RPM Fusion only); they are
# distribution-free headers, so install them from source.
git clone --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git /tmp/nv-codec-headers
make -C /tmp/nv-codec-headers install PREFIX=/usr
;;
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 \
ffnvcodec-headers
;;
esac
- name: Configure build environment
run: |
# tooling/ocio-env.sh: vendored static OCIO everywhere it
# builds (the [patch.crates-io] ocio-sys tracks shaloong/ocio-rs
# main, whose vendored sources build on GCC >= 16).
bash tooling/ocio-env.sh >> "$GITHUB_ENV"
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
# uses: Swatinem/rust-cache@v2
# with:
# shared-key: oak-${{ matrix.distro }}
# cache-on-failure: true
# TEMP: cache disabled until the Gitea instance cache is provisioned (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
# The release version lives in [workspace.package] of the root
# Cargo.toml (single source of truth; tags do not carry it).
VERSION=$(sed -n '/^\[workspace\.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)
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
# ffnvcodec headers (NVDEC for the project FFmpeg build) are
# handled by install-deps.sh (source install; the Ubuntu package
# name differs per release and `libffnvcodec-dev` is gone on
# noble) — do NOT apt-install them here.
- name: Configure build environment
run: bash tooling/ocio-env.sh >> "$GITHUB_ENV"
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
# uses: Swatinem/rust-cache@v2
# with:
# shared-key: oak-appimage
# cache-on-failure: true
# TEMP: cache disabled until the Gitea instance cache is provisioned (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: |
# Vendored static OCIO (same as every non-Windows platform via
# tooling/ocio-env.sh); no OCIO_INSTALL_DIR override.
bash tooling/ocio-env.sh >> "$GITHUB_ENV"
{
echo "CFLAGS=-I/opt/homebrew/include"
echo "LDFLAGS=-L/opt/homebrew/lib"
echo "PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig/openjpeg"
} >> "$GITHUB_ENV"
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
# uses: Swatinem/rust-cache@v2
# with:
# shared-key: oak-workspace
# cache-on-failure: true
# TEMP: cache disabled until the Gitea instance cache is provisioned (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
# Pull the Homebrew dylibs the binaries reference into
# Contents/Frameworks and rewrite install names to
# @executable_path-relative (the script ad-hoc re-signs the bundle).
- name: Bundle dylibs into the .app
run: tooling/package/bundle-dylibs-macos.sh target/release/Oak.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 \
mingw-w64-ucrt-x86_64-ffnvcodec-headers \
mingw-w64-ucrt-x86_64-pkgconf
- name: Configure build environment
run: |
# System OCIO (MSYS2, the exact 2.5.2 the bridge targets);
# tooling/ocio-env.sh links it STATICALLY when the package ships
# libOpenColorIO.a, dynamically otherwise (the DLL bundling step
# below then still applies).
bash tooling/ocio-env.sh >> "$GITHUB_ENV"
# ocio-sys is the GIT fork (Mike-Solar/ocio-rs main, pinned in
# the root manifest): its build.rs already carries the
# fork's GNU-toolchain fix, so NO crate-unpack/glob patch step
# applies here. The old code unpacked `ocio-sys-0.2.1.crate`
# from the registry cache — impossible for a git dependency
# (no .crate archive; git sources land under
# registry/src/git/<hash>), hence the
# "ls .../ocio-sys-0.2.1/build.rs: No such file" Windows CI
# failure.
echo "OCIO_RS_NO_MSVC_INCLUDES=1" >> "$GITHUB_ENV"
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
# uses: Swatinem/rust-cache@v2
# with:
# shared-key: oak-workspace
# cache-on-failure: true
# TEMP: cache disabled until the Gitea instance cache is provisioned (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
# Collect the MSYS2 runtime DLLs (libstdc++/libgcc/OpenColorIO/...)
# into target/pkg/win-dlls; the packager `resources` glob then
# installs them next to the executables.
- name: Bundle runtime DLLs
run: |
unset INCLUDE LIB
pacman -S --needed --noconfirm mingw-w64-ucrt-x86_64-ntldd
tooling/package/bundle-dylibs-windows.sh target/pkg/win-dlls \
target/release/oak-editor.exe target/release/oak-cli.exe \
target/release/oak-worker.exe
- 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/*