Skip to content

feat: build and bundle libmpv from source on Linux with full audio support #198

feat: build and bundle libmpv from source on Linux with full audio support

feat: build and bundle libmpv from source on Linux with full audio support #198

Workflow file for this run

name: Build & Bundle
on:
push:
branches: [main, dev, release-*]
paths-ignore:
- "**.md"
- "LICENSE"
- ".github/workflows/release-*.yml"
- "docs/**"
- ".vscode/**"
- ".idea/**"
pull_request:
branches: [main, dev, release-*]
paths-ignore:
- "**.md"
- "LICENSE"
- ".github/workflows/release-*.yml"
- "docs/**"
- ".vscode/**"
- ".idea/**"
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
jobs:
# ── Enforce merge source for PRs targeting main ─────────────────────────
# Only dev and release automation branches may merge into main.
check-merge-source:
if: github.event_name == 'pull_request' && github.base_ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Validate source branch
run: |
HEAD="${{ github.head_ref }}"
if [[ "$HEAD" == "dev" || "$HEAD" == chore-bump-v* || "$HEAD" == chore/release-* || "$HEAD" == chore/sync-main-* ]]; then
echo "OK: '$HEAD' is allowed to merge into main."
else
echo "::error::Branch '$HEAD' is not allowed to merge into main. Only dev and release automation branches can target main."
exit 1
fi
# ── Detect which platform-specific files changed ─────────────────────────
# On PRs: uses dorny/paths-filter to check changed files.
# On push: outputs 'true' for both so builds always run.
detect-changes:
runs-on: ubuntu-latest
outputs:
linux: ${{ steps.push-all.outputs.linux || steps.filter.outputs.linux }}
macos: ${{ steps.push-all.outputs.macos || steps.filter.outputs.macos }}
steps:
- uses: actions/checkout@v4
- name: Push — always build both platforms
id: push-all
if: github.event_name == 'push'
run: |
echo "linux=true" >> "$GITHUB_OUTPUT"
echo "macos=true" >> "$GITHUB_OUTPUT"
- name: PR — detect changed paths
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
linux:
- 'crates/tauri-plugin-mpv/src/linux.rs'
- 'crates/tauri-plugin-mpv/src/renderer.rs'
- 'crates/tauri-plugin-mpv/src/commands.rs'
- 'crates/tauri-plugin-mpv/src/engine.rs'
- 'crates/tauri-plugin-mpv/src/mpv.rs'
- 'crates/tauri-plugin-mpv/src/lib.rs'
- 'crates/tauri-plugin-mpv/Cargo.toml'
- 'crates/core/**'
- 'apps/desktop/src-tauri/**'
- 'apps/desktop/src/**'
- 'apps/desktop/package.json'
- 'Cargo.toml'
- 'Cargo.lock'
- 'scripts/build-libmpv.sh'
- 'scripts/bundle-libmpv-linux.sh'
macos:
- 'crates/tauri-plugin-mpv/src/macos.rs'
- 'crates/tauri-plugin-mpv/src/renderer.rs'
- 'crates/tauri-plugin-mpv/src/commands.rs'
- 'crates/tauri-plugin-mpv/src/engine.rs'
- 'crates/tauri-plugin-mpv/src/mpv.rs'
- 'crates/tauri-plugin-mpv/src/lib.rs'
- 'crates/tauri-plugin-mpv/Cargo.toml'
- 'crates/core/**'
- 'apps/desktop/src-tauri/**'
- 'apps/desktop/src/**'
- 'apps/desktop/package.json'
- 'Cargo.toml'
- 'Cargo.lock'
- 'scripts/build-libmpv.sh'
- 'scripts/bundle-libmpv.sh'
# ── Tests (run on every push and PR) ────────────────────────────────────
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: ". -> target"
- name: Install system deps
run: sudo apt-get update && sudo apt-get install -y libssl-dev pkg-config
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install deps
run: npm ci --ignore-scripts || (rm -f package-lock.json && npm install)
- name: TypeScript type-check
working-directory: apps/desktop
run: npx tsc -b --noEmit
- name: Rust type-check (core only — avoids Tauri GTK deps on Linux)
run: cargo check -p mvp-core
- name: Run Rust tests
run: cargo test -p mvp-core -- --include-ignored
- name: Run desktop tests with coverage
working-directory: apps/desktop
run: npm run test:coverage
- name: Upload coverage artifact
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: apps/desktop/coverage/
retention-days: 1
# ── Coverage badge deploy (push to main only, needs write) ─────────────
deploy-coverage:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [test]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: coverage-report
path: coverage
- name: Generate coverage badge
uses: jaywcjlove/coverage-badges-cli@v2.1.0
with:
source: coverage/coverage-summary.json
output: coverage/badge.svg
- name: Deploy coverage to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./coverage
destination_dir: coverage
keep_files: true
# ── macOS Desktop (push, or PRs with macOS-relevant changes) ─────────────
# Skip platform builds on version-bump PRs (only version numbers change).
build-macos:
if: needs.detect-changes.outputs.macos == 'true' && !startsWith(github.head_ref, 'chore-bump-v')
needs: [test, detect-changes]
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: ". -> target"
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install frontend deps
run: npm ci
- name: Install system deps
run: |
# ffmpeg@7 required: mpv 0.40.0 uses FF_PROFILE_* macros removed in ffmpeg 8.x
brew install meson ninja pkg-config ffmpeg@7 libass libplacebo dylibbundler
# Make ffmpeg@7 visible to pkg-config (it is keg-only, not linked by default)
echo "PKG_CONFIG_PATH=$(brew --prefix ffmpeg@7)/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" >> $GITHUB_ENV
- name: Prepare libmpv for bundle
run: ./scripts/build-libmpv.sh macos
- name: Build frontend
run: npm run build:desktop
- name: Build Tauri app (macOS)
# Override createUpdaterArtifacts=false so Tauri doesn't require a signing key in CI.
# The updater artifact + signature is only needed in the release workflow.
run: cd apps/desktop && npx tauri build --config '{"bundle":{"createUpdaterArtifacts":false}}'
- name: Upload macOS artifact
uses: actions/upload-artifact@v4
with:
name: MaxVideoPlayer-macOS
path: |
target/release/bundle/dmg/*.dmg
target/release/bundle/macos/*.app
if-no-files-found: error
# ── Linux Desktop (push, or PRs with Linux-relevant changes) ────────────
build-linux:
if: needs.detect-changes.outputs.linux == 'true' && !startsWith(github.head_ref, 'chore-bump-v')
needs: [test, detect-changes]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: ". -> target"
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install system deps
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev libsoup-3.0-dev \
libayatana-appindicator3-dev \
libegl-dev libssl-dev pkg-config librsvg2-dev \
patchelf rpm \
meson ninja-build \
libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavfilter-dev \
libass-dev libpulse-dev libasound2-dev \
libplacebo-dev \
libx11-dev libxss-dev libxext-dev libxpresent-dev libxrandr-dev \
libwayland-dev
- name: Build libmpv from source
run: |
./scripts/build-libmpv.sh linux
echo "LD_LIBRARY_PATH=$(pwd)/libs/linux:${LD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
- name: Install frontend deps
run: |
npm ci || true
# npm ci can skip platform-specific optional deps (npm/cli#4828).
# Ensure the Tauri CLI native binding for Linux is present.
npm ls @tauri-apps/cli-linux-x64-gnu 2>/dev/null || npm install @tauri-apps/cli-linux-x64-gnu
- name: Rust type-check (plugin + core)
run: cargo check -p tauri-plugin-mpv -p mvp-core
- name: Build frontend
run: npm run build:desktop
- name: Build Tauri app (Linux)
run: cd apps/desktop && npx tauri build --config '{"bundle":{"createUpdaterArtifacts":false}}'
- name: Upload Linux artifacts
uses: actions/upload-artifact@v4
with:
name: MaxVideoPlayer-Linux
path: |
target/release/bundle/deb/*.deb
target/release/bundle/rpm/*.rpm
target/release/bundle/appimage/*.AppImage
if-no-files-found: warn