Build Lume Desktop #6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Lume Desktop | |
| on: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-macos: | |
| name: Build macOS bundle | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: aarch64-apple-darwin | |
| - name: Inject PDFium (macOS) | |
| run: | | |
| curl -L -o pdfium.tgz https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-mac-arm64.tgz | |
| tar -xzf pdfium.tgz lib/libpdfium.dylib | |
| mv lib/libpdfium.dylib src-tauri/libpdfium.dylib | |
| - name: Install frontend dependencies | |
| run: npm install | |
| - name: Build macOS bundle | |
| run: npm run tauri build -- --target aarch64-apple-darwin --ci | |
| - name: Upload macOS artifacts | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: Lume-macos-aarch64 | |
| path: | | |
| src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/* | |
| src-tauri/target/aarch64-apple-darwin/release/bundle/macos/* | |
| if-no-files-found: error | |
| build-windows: | |
| name: Build Windows portable + installer | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install NSIS | |
| run: choco install nsis -y | |
| - name: Inject PDFium (Windows) | |
| shell: bash | |
| run: | | |
| curl -L -o pdfium.tgz https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-win-x64.tgz | |
| tar -xzf pdfium.tgz bin/pdfium.dll | |
| mv bin/pdfium.dll src-tauri/pdfium.dll | |
| - name: Install frontend dependencies | |
| run: npm install | |
| - name: Build portable executable | |
| run: npm run tauri build -- --no-bundle --ci | |
| - name: Package portable executable | |
| shell: pwsh | |
| run: | | |
| $portableRoot = "dist-portable/Lume" | |
| New-Item -ItemType Directory -Force -Path $portableRoot | Out-Null | |
| Copy-Item "src-tauri/target/release/Lume.exe" "$portableRoot/Lume.exe" -Force | |
| Copy-Item "src-tauri/pdfium.dll" "$portableRoot/pdfium.dll" -Force | |
| - name: Smoke test portable CLI | |
| shell: pwsh | |
| run: | | |
| $output = & "dist-portable/Lume/Lume.exe" --list-papers 2>&1 | Out-String | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "Portable CLI smoke test failed with exit code $LASTEXITCODE" | |
| } | |
| if ($output -notmatch "No saved papers found\.") { | |
| throw "Portable CLI smoke test did not produce the expected output. Actual output: $output" | |
| } | |
| Write-Host $output | |
| - name: Build installer executable (NSIS) | |
| run: npm run tauri build -- --bundles nsis --ci | |
| - name: Smoke test installed CLI | |
| shell: pwsh | |
| run: | | |
| $installer = Get-ChildItem "src-tauri/target/release/bundle/nsis/*.exe" | Select-Object -First 1 | |
| if (-not $installer) { | |
| throw "Installer artifact not found" | |
| } | |
| $installRoot = Join-Path $env:RUNNER_TEMP "LumeInstall" | |
| Remove-Item $installRoot -Recurse -Force -ErrorAction SilentlyContinue | |
| Start-Process -FilePath $installer.FullName -ArgumentList "/S", "/D=$installRoot" -Wait -NoNewWindow | |
| $installedExe = Get-ChildItem -Path $installRoot -Filter "Lume.exe" -Recurse | Select-Object -First 1 | |
| if (-not $installedExe) { | |
| throw "Installed Lume.exe not found under $installRoot" | |
| } | |
| $output = & $installedExe.FullName --list-papers 2>&1 | Out-String | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "Installed CLI smoke test failed with exit code $LASTEXITCODE" | |
| } | |
| if ($output -notmatch "No saved papers found\.") { | |
| throw "Installed CLI smoke test did not produce the expected output. Actual output: $output" | |
| } | |
| Write-Host $output | |
| - name: Upload portable artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: Lume-windows-portable | |
| path: dist-portable/Lume | |
| if-no-files-found: error | |
| - name: Upload installer artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: Lume-windows-installer | |
| path: src-tauri/target/release/bundle/nsis/*.exe | |
| if-no-files-found: error | |
| build-linux: | |
| name: Build Linux deb | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install Linux build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libjavascriptcoregtk-4.1-dev \ | |
| libgtk-3-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf \ | |
| build-essential \ | |
| pkg-config \ | |
| curl | |
| - name: Inject PDFium (Linux) | |
| run: | | |
| curl -L -o pdfium.tgz https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-x64.tgz | |
| tar -xzf pdfium.tgz lib/libpdfium.so | |
| mv lib/libpdfium.so src-tauri/libpdfium.so | |
| - name: Install frontend dependencies | |
| run: npm install | |
| - name: Build deb package | |
| run: npm run tauri build -- --bundles deb --ci | |
| - name: Smoke test installed deb CLI | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mapfile -t DEB_FILES < <(find src-tauri/target/release/bundle/deb -maxdepth 1 -type f -name '*.deb' | sort) | |
| if [ ${#DEB_FILES[@]} -eq 0 ]; then | |
| echo "No deb artifact was found." >&2 | |
| exit 1 | |
| fi | |
| DEB_PATH="${DEB_FILES[0]}" | |
| sudo dpkg -i "$DEB_PATH" | |
| BINARY_PATH=$(dpkg-deb -c "$DEB_PATH" | awk '/\.\/usr\/bin\// { sub(/^\./, "", $NF); print $NF; exit }') | |
| if [ -z "$BINARY_PATH" ]; then | |
| echo "Could not determine installed binary path from $DEB_PATH" >&2 | |
| exit 1 | |
| fi | |
| OUTPUT=$("$BINARY_PATH" --list-papers 2>&1) | |
| STATUS=$? | |
| if [ $STATUS -ne 0 ]; then | |
| echo "$OUTPUT" | |
| echo "Installed deb CLI smoke test failed with exit code $STATUS" >&2 | |
| exit $STATUS | |
| fi | |
| echo "$OUTPUT" | |
| if ! grep -Fq "No saved papers found." <<< "$OUTPUT"; then | |
| echo "Installed deb CLI smoke test did not produce the expected output." >&2 | |
| exit 1 | |
| fi | |
| - name: Upload deb artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: Lume-linux-deb | |
| path: src-tauri/target/release/bundle/deb/*.deb | |
| if-no-files-found: error | |
| create-draft-release: | |
| name: Create draft release | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build-macos | |
| - build-windows | |
| - build-linux | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: release-assets | |
| - name: Create release asset bundle | |
| id: bundle_assets | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION=$(node -p "JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version") | |
| TAG="v${VERSION}" | |
| TITLE="Lume v${VERSION}" | |
| DIST_DIR="$PWD/release-dist" | |
| mkdir -p "$DIST_DIR" | |
| echo "Downloaded release assets:" | |
| find release-assets -maxdepth 4 -type f | sort | |
| mapfile -t mac_dmg < <(find release-assets/Lume-macos-aarch64 -type f -name '*.dmg' | sort) | |
| mapfile -t windows_installer < <(find release-assets/Lume-windows-installer -type f -name '*.exe' | sort) | |
| mapfile -t linux_deb < <(find release-assets/Lume-linux-deb -type f -name '*.deb' | sort) | |
| portable_root="release-assets/Lume-windows-portable" | |
| if [ -d "$portable_root/Lume" ]; then | |
| portable_root="$portable_root/Lume" | |
| fi | |
| if [ ${#mac_dmg[@]} -eq 0 ]; then | |
| echo "No macOS DMG asset was found." >&2 | |
| exit 1 | |
| fi | |
| if [ ${#windows_installer[@]} -eq 0 ]; then | |
| echo "No Windows installer asset was found." >&2 | |
| exit 1 | |
| fi | |
| if [ ${#linux_deb[@]} -eq 0 ]; then | |
| echo "No Linux deb asset was found." >&2 | |
| exit 1 | |
| fi | |
| PORTABLE_ZIP="$DIST_DIR/Lume-windows-portable-${TAG}.zip" | |
| ( | |
| cd "$portable_root" | |
| zip -r "$PORTABLE_ZIP" . | |
| ) | |
| cp "${mac_dmg[0]}" "$DIST_DIR/" | |
| cp "${windows_installer[0]}" "$DIST_DIR/" | |
| cp "${linux_deb[0]}" "$DIST_DIR/" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "title=$TITLE" >> "$GITHUB_OUTPUT" | |
| echo "dist_dir=$DIST_DIR" >> "$GITHUB_OUTPUT" | |
| - name: Create or update draft release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RELEASE_TAG: ${{ steps.bundle_assets.outputs.tag }} | |
| RELEASE_TITLE: ${{ steps.bundle_assets.outputs.title }} | |
| RELEASE_DIST_DIR: ${{ steps.bundle_assets.outputs.dist_dir }} | |
| run: | | |
| set -euo pipefail | |
| mapfile -t ASSETS < <(find "$RELEASE_DIST_DIR" -maxdepth 1 -type f | sort) | |
| if [ ${#ASSETS[@]} -eq 0 ]; then | |
| echo "No release assets were prepared." >&2 | |
| exit 1 | |
| fi | |
| if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then | |
| gh release edit "$RELEASE_TAG" \ | |
| --title "$RELEASE_TITLE" \ | |
| --draft | |
| gh release upload "$RELEASE_TAG" "${ASSETS[@]}" --clobber | |
| else | |
| gh release create "$RELEASE_TAG" "${ASSETS[@]}" \ | |
| --title "$RELEASE_TITLE" \ | |
| --draft \ | |
| --target "$GITHUB_SHA" \ | |
| --generate-notes | |
| fi |