From 7f544a65e6237c45b17d053c67e4daa94e00639e Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Thu, 24 Sep 2026 17:10:54 +0800 Subject: [PATCH] ci(cd): add openKylin x64/arm64 debs and label the Debian build The Linux package matrix now carries arch/triplet/runner per entry and gains two openKylin entries (x64 on a 16x runner, arm64 on a 32x runner), each building inside the openkylin container so dpkg-shlibdeps resolves against openKylin's own repo names. Deb packages are labeled by build distro: the general debian:12 package becomes oak-editor_+debian_.deb, openKylin's oak-editor_+openkylin_.deb; build-deb.sh takes the variant and stamps dpkg --print-architecture (the file name hardcoded amd64 before). Also: pin HOME for rustup in the openKylin container, create the icon directory before rendering (and degrade to the scalable icon when rsvg-convert is missing), add the Windows Defender step to the Windows packaging job, and take the bumped runner sizes (AppImage/Linux 16x, macOS 12x, Windows 32x). --- .github/workflows/cd.yml | 135 +++++++++++++++++++++++++++++------ tooling/package/build-deb.sh | 33 +++++++-- 2 files changed, 138 insertions(+), 30 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 4b64ade6d..848de7b66 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -21,15 +21,18 @@ jobs: # 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). The FFmpeg/codec libraries - # come from the vcpkg manifest (root vcpkg.json, x64-linux triplet), so - # these containers carry the build toolchain and the headless/UI - # runtime deps only. deb: hand-rolled dpkg-deb; rpm: rpmbuild; arch: - # makepkg. AppImage stays on the Ubuntu runner (self-contained by + # come from the vcpkg manifest (root vcpkg.json, the distro/arch + # triplet), so these containers carry the build toolchain and the + # headless/UI runtime deps only. deb: hand-rolled dpkg-deb, built once + # in debian:12 (the general Debian-family package, labeled "+debian") + # and once per openKylin arch (x64/arm64, labeled "+openkylin") so each + # family gets deps that resolve against its own repos; 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 + name: Linux packages (${{ matrix.distro }} ${{ matrix.arch }}) + runs-on: ${{ matrix.runner }} container: ${{ matrix.image }} strategy: @@ -38,10 +41,29 @@ jobs: include: - distro: debian image: debian:12 + arch: x64 + runner: warp-ubuntu-latest-x64-16x + triplet: x64-linux - distro: fedora image: fedora:41 + arch: x64 + runner: warp-ubuntu-latest-x64-16x + triplet: x64-linux - distro: arch image: archlinux:latest + arch: x64 + runner: warp-ubuntu-latest-x64-16x + triplet: x64-linux + - distro: openkylin + image: openkylin/openkylin:latest + arch: x64 + runner: warp-ubuntu-latest-x64-16x + triplet: x64-linux + - distro: openkylin + image: openkylin/openkylin:latest + arch: arm64 + runner: warp-ubuntu-latest-arm64-32x + triplet: arm64-linux steps: # git/curl must land BEFORE actions/checkout runs inside the @@ -49,7 +71,7 @@ jobs: - name: Install git and fetch tools run: | case "${{ matrix.distro }}" in - debian) apt-get update && apt-get install -y git curl ;; + debian|openkylin) apt-get update && apt-get install -y git curl ;; fedora) dnf install -y git curl ;; arch) pacman -Sy --noconfirm git curl ;; esac @@ -59,6 +81,19 @@ jobs: with: submodules: true + # The openKylin image runs as root with HOME=/github/home; rustup + # refuses the euid mismatch and installs a toolchain the later steps + # cannot find. Pin the whole job to root's home (same as the CI + # openKylin jobs). + - name: Pin HOME for rustup (openKylin) + if: matrix.distro == 'openkylin' + run: | + { + echo "HOME=/root" + echo "CARGO_HOME=/root/.cargo" + echo "RUSTUP_HOME=/root/.rustup" + } >> "$GITHUB_ENV" + - name: Install Rust (stable) uses: dtolnay/rust-toolchain@stable @@ -95,6 +130,20 @@ jobs: mesa vulkan-headers vulkan-icd-loader \ libxkbcommon libxkbcommon-x11 librsvg libdrm autoconf autoconf-archive automake libtool ;; + openkylin) + # The CI openKylin build set plus dpkg-dev (dpkg-shlibdeps + # computes the runtime deps) and librsvg2-bin (app icon). + apt-get update + apt-get install -y \ + build-essential clang libclang-dev cmake pkg-config nasm \ + git curl zip unzip tar python3 patch xz-utils 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 \ + libdrm-dev file librsvg2-bin \ + autoconf autoconf-archive automake libtool + ;; esac # ------------------------------------------------------------------ @@ -113,16 +162,17 @@ jobs: path: | vcpkg_installed ~/.cache/vcpkg/archives - # The distro prefix matters: the same Ubuntu-runner cache scope - # backs three different container distros. - key: vcpkg-${{ matrix.distro }}-x64-linux-${{ hashFiles('vcpkg.json') }}-${{ github.run_id }}-${{ github.run_attempt }} + # The distro and triplet prefixes matter: one Ubuntu-runner + # cache scope backs several containers, and the openKylin arm64 + # build must never restore the x64 binaries. + key: vcpkg-${{ matrix.distro }}-${{ matrix.triplet }}-${{ hashFiles('vcpkg.json') }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - vcpkg-${{ matrix.distro }}-x64-linux-${{ hashFiles('vcpkg.json') }}- - vcpkg-${{ matrix.distro }}-x64-linux- + vcpkg-${{ matrix.distro }}-${{ matrix.triplet }}-${{ hashFiles('vcpkg.json') }}- + vcpkg-${{ matrix.distro }}-${{ matrix.triplet }}- save-always: true - name: Install dependencies (vcpkg manifest) - run: vcpkg install --triplet x64-linux + run: vcpkg install --triplet ${{ matrix.triplet }} - name: Configure build environment run: | @@ -134,7 +184,7 @@ jobs: # 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" - prefix="$PWD/vcpkg_installed/x64-linux" + prefix="$PWD/vcpkg_installed/${{ matrix.triplet }}" echo "FFMPEG_DIR=$prefix" >> "$GITHUB_ENV" echo "PKG_CONFIG_PATH=$prefix/lib/pkgconfig" >> "$GITHUB_ENV" echo "$prefix/tools/pkgconf" >> "$GITHUB_PATH" @@ -142,14 +192,22 @@ jobs: - name: Cache cargo artifacts uses: Swatinem/rust-cache@v2 with: - shared-key: oak-${{ matrix.distro }} + shared-key: oak-${{ matrix.distro }}-${{ matrix.arch }} cache-on-failure: true - 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 + run: | + mkdir -p icons + if command -v rsvg-convert >/dev/null 2>&1; then + rsvg-convert -w 512 -h 512 Oak_Icon.svg -o icons/icon.png + else + # Defensive: some containers (openKylin) may not carry + # librsvg2-bin; the scalable icon still installs. + echo "::warning::rsvg-convert is unavailable; packaging the scalable icon only" + fi - name: Package run: | @@ -158,16 +216,17 @@ jobs: # 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" ;; + debian) tooling/package/build-deb.sh "$VERSION" debian ;; + openkylin) tooling/package/build-deb.sh "$VERSION" openkylin ;; + fedora) tooling/package/build-rpm.sh "$VERSION" ;; + arch) tooling/package/build-pkg.sh "$VERSION" ;; esac shell: bash - name: Upload artifact uses: actions/upload-artifact@v7 with: - name: oak-linux-${{ matrix.distro }} + name: oak-linux-${{ matrix.distro }}-${{ matrix.arch }} path: | target/release/*.deb target/release/*.rpm @@ -179,7 +238,7 @@ jobs: # ------------------------------------------------------------------ appimage: name: Linux AppImage - runs-on: warp-ubuntu-latest-x64-8x + runs-on: warp-ubuntu-latest-x64-16x steps: - name: Checkout @@ -269,7 +328,7 @@ jobs: macos: name: macOS DMG (Apple Silicon) - runs-on: warp-macos-26-arm64-6x + runs-on: warp-macos-26-arm64-12x steps: - name: Checkout @@ -378,7 +437,7 @@ jobs: # ------------------------------------------------------------------ windows: name: Windows installer (NSIS) - runs-on: warp-windows-2025-vs2026-x64-16x + runs-on: warp-windows-2025-vs2026-x64-32x steps: - name: Checkout @@ -386,6 +445,36 @@ jobs: with: submodules: true + # Defender's real-time scanning slows the MSVC/vcpkg build down + # badly; disable it for the job and keep exclusions as the fallback + # when policy blocks the change (same step as the CI Windows job). + - name: Disable Windows Defender scanning + shell: pwsh + run: | + try { + Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction Stop + Set-MpPreference -DisableScriptScanning $true -ErrorAction SilentlyContinue + Set-MpPreference -DisableArchiveScanning $true -ErrorAction SilentlyContinue + Write-Host "Windows Defender real-time scanning disabled for this job" + } catch { + Write-Host "Windows Defender could not be disabled (non-fatal, falling back to exclusions): $_" + } + foreach ($path in @( + $env:GITHUB_WORKSPACE, + "$env:USERPROFILE\.cargo", + "$env:USERPROFILE\.rustup", + "$env:LOCALAPPDATA\vcpkg" + )) { + Add-MpPreference -ExclusionPath $path -ErrorAction SilentlyContinue + } + try { + Get-MpPreference | + Select-Object DisableRealtimeMonitoring, DisableScriptScanning, ExclusionPath | + Format-List + } catch { + Write-Host "Defender status unavailable: $_" + } + - name: Install Rust (stable, MSVC) uses: dtolnay/rust-toolchain@stable with: diff --git a/tooling/package/build-deb.sh b/tooling/package/build-deb.sh index eaf75c4dd..cbbc8ad5f 100755 --- a/tooling/package/build-deb.sh +++ b/tooling/package/build-deb.sh @@ -18,10 +18,23 @@ # Build the .deb by hand: stage the release binaries + resources, compute # the FULL runtime dependency set with dpkg-shlibdeps (Debian-family names # of the build distro), and pack with dpkg-deb. Run from the repo root -# after `cargo build --release`. Usage: tooling/package/build-deb.sh +# after `cargo build --release`. +# +# Usage: tooling/package/build-deb.sh [] +# marks the build distro in the package version and file name: +# CD passes "debian" for the general build and "openkylin" for the +# openKylin builds. The "+" suffix is valid Debian version syntax and +# sorts above the plain version. set -euo pipefail -VERSION="${1:?usage: build-deb.sh }" +VERSION="${1:?usage: build-deb.sh []}" +VARIANT="${2:-}" +if [ -n "$VARIANT" ]; then + DEB_VERSION="${VERSION}+${VARIANT}" +else + DEB_VERSION="$VERSION" +fi +ARCH="$(dpkg --print-architecture)" STAGING=target/pkg/deb rm -rf "$STAGING" mkdir -p "$STAGING/usr/bin" "$STAGING/usr/share/applications" \ @@ -31,7 +44,13 @@ mkdir -p "$STAGING/usr/bin" "$STAGING/usr/share/applications" \ install -m755 target/release/oak-editor target/release/oak-cli target/release/oak-worker \ "$STAGING/usr/bin/" install -m644 packaging/oak.desktop "$STAGING/usr/share/applications/oak.desktop" -install -m644 icons/icon.png "$STAGING/usr/share/icons/hicolor/512x512/apps/oak.png" +if [ -f icons/icon.png ]; then + install -m644 icons/icon.png "$STAGING/usr/share/icons/hicolor/512x512/apps/oak.png" +else + # The icon step warns and skips when rsvg-convert is unavailable; + # the scalable icon still installs. + echo "warning: icons/icon.png missing; shipping the scalable icon only" +fi install -m644 Oak_Icon.svg "$STAGING/usr/share/icons/hicolor/scalable/apps/oak.svg" install -m644 assets/i18n/*.yaml "$STAGING/usr/share/oak/i18n/" @@ -44,10 +63,10 @@ echo "declared deps: $DEPS" cat > "$STAGING/DEBIAN/control" <