# Cross-platform release build. Produces installer artifacts for # Linux (.AppImage + .deb), Windows (.msi + .exe), macOS (.dmg + .app). # # Triggers: # - Manual: any branch via "Run workflow" in the GitHub Actions UI. # Use this to build a Windows binary on demand to dual-boot test. # - Tag push (v*): builds + drafts a GitHub Release with all artifacts # attached. Tag a release with `git tag v0.2.0 && git push --tags`. # # Artifacts: # - workflow_dispatch builds: uploaded as Action artifacts # (visible in the run page, downloadable for 30 days). # - tag builds: attached to a draft GitHub Release named after the tag. # Promote the draft to a release when ready. # # Signing: # - macOS: signing + notarisation activate automatically when the # APPLE_* secrets are set in the repo. Builds unsigned if absent. # See docs/release/code-signing-setup.md for the cert walkthrough. # - Windows: signing activates automatically when WINDOWS_CERTIFICATE # + WINDOWS_CERTIFICATE_PASSWORD are set. Builds unsigned if absent. # See docs/release/code-signing-setup.md for the cert walkthrough. name: build on: push: tags: ['v*'] workflow_dispatch: inputs: tag_name: description: 'Optional tag name to attach the build to (leave blank for plain artifacts)' required: false concurrency: group: build-${{ github.ref }} cancel-in-progress: false # let release builds finish even on tag re-pushes jobs: build: name: build (${{ matrix.os }}) permissions: contents: write # needed to create draft releases on tag pushes strategy: fail-fast: false matrix: include: - os: ubuntu-22.04 artifact_glob: | src-tauri/target/release/bundle/appimage/*.AppImage src-tauri/target/release/bundle/appimage/*.AppImage.sha256 src-tauri/target/release/bundle/deb/*.deb - os: windows-latest artifact_glob: | src-tauri/target/release/bundle/msi/*.msi src-tauri/target/release/bundle/nsis/*.exe - os: macos-latest artifact_glob: | src-tauri/target/release/bundle/dmg/*.dmg src-tauri/target/release/bundle/macos/*.app runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: - uses: actions/checkout@v4 # System packages — same as check.yml but locked to release-build needs. # See check.yml for the per-package rationale (bindgen → libclang, # llama-cpp-sys-2 vulkan feature → libvulkan / VULKAN_SDK). - name: Install Linux deps if: matrix.os == 'ubuntu-22.04' run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ libwebkit2gtk-4.1-dev \ libappindicator3-dev \ librsvg2-dev \ libasound2-dev \ libudev-dev \ patchelf \ cmake \ build-essential \ libclang-dev \ clang \ libvulkan-dev \ glslang-tools \ spirv-tools LIBCLANG_CANDIDATE=$(ls -d /usr/lib/llvm-*/lib 2>/dev/null | sort -V | tail -n1) if [ -z "$LIBCLANG_CANDIDATE" ]; then LIBCLANG_CANDIDATE=/usr/lib/x86_64-linux-gnu fi echo "LIBCLANG_PATH=$LIBCLANG_CANDIDATE" >> "$GITHUB_ENV" - name: Install macOS deps if: matrix.os == 'macos-latest' run: | brew list cmake >/dev/null 2>&1 || brew install cmake brew list llvm >/dev/null 2>&1 || brew install llvm brew install vulkan-headers vulkan-loader molten-vk shaderc echo "LIBCLANG_PATH=$(brew --prefix llvm)/lib" >> "$GITHUB_ENV" BREW_PREFIX=$(brew --prefix) echo "VULKAN_SDK=$BREW_PREFIX" >> "$GITHUB_ENV" echo "CMAKE_PREFIX_PATH=$BREW_PREFIX" >> "$GITHUB_ENV" - name: Install Windows deps if: matrix.os == 'windows-latest' shell: pwsh run: | cmake --version choco install -y llvm --no-progress choco install -y vulkan-sdk --no-progress $sdkRoot = Get-ChildItem -Directory "C:\VulkanSDK" | Sort-Object Name -Descending | Select-Object -First 1 if (-not $sdkRoot) { Write-Error "VulkanSDK directory not found under C:\VulkanSDK after choco install" exit 1 } echo "VULKAN_SDK=$($sdkRoot.FullName)" >> $env:GITHUB_ENV echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" >> $env:GITHUB_ENV - name: Install Node uses: actions/setup-node@v4 with: node-version: 20 cache: npm - name: Install Rust uses: dtolnay/rust-toolchain@stable # Workspace is at the repo root; target dir is ./target (not # src-tauri/target). See note in check.yml for details. - name: Cache Rust uses: Swatinem/rust-cache@v2 with: workspaces: . shared-key: magnotia-build-${{ matrix.os }} - name: Install JS deps run: npm ci # tauri-action handles `tauri build` plus, on tag pushes, attaches # artifacts to a GitHub draft release. Empty tagName disables the # release-creation behaviour for manual workflow_dispatch runs. - name: Build (release) uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # macOS code-signing + notarisation. Builds unsigned if these secrets aren't set. # Set via: gh secret set APPLE_SIGNING_IDENTITY --body "..." (etc.) # See docs/release/code-signing-setup.md for the cert procurement walkthrough. APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} # Windows code-signing. Builds unsigned if these secrets aren't set. # Set via: gh secret set WINDOWS_CERTIFICATE --body "..." (etc.) # See docs/release/code-signing-setup.md for the cert procurement walkthrough. WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} with: # If pushed as a tag, use the tag name; otherwise leave empty # so tauri-action builds artifacts but does not touch releases. tagName: ${{ github.ref_type == 'tag' && github.ref_name || (inputs.tag_name || '') }} releaseName: ${{ github.ref_type == 'tag' && github.ref_name || (inputs.tag_name || '') }} releaseDraft: true prerelease: false # Build all bundle types the OS supports. args: '' - name: Compute AppImage SHA-256 if: runner.os == 'Linux' shell: bash run: | set -euo pipefail cd src-tauri/target/release/bundle/appimage for img in *.AppImage; do sha256sum "$img" > "$img.sha256" echo "Generated: $img.sha256" cat "$img.sha256" done # Always upload as an Actions artifact too — accessible from the # workflow run page even if the release-creation step was skipped. - name: Upload artifacts if: always() uses: actions/upload-artifact@v4 with: name: magnotia-${{ matrix.os }}-${{ github.sha }} path: ${{ matrix.artifact_glob }} retention-days: 30 if-no-files-found: warn - name: Report artifact sizes if: always() shell: bash run: | if [ -d src-tauri/target/release/bundle ]; then find src-tauri/target/release/bundle -type f \ \( -name '*.AppImage' -o -name '*.deb' -o -name '*.msi' -o -name '*.exe' -o -name '*.dmg' -o -name '*.app' \) \ -exec du -h {} + | sort -h fi