Skip to content

Build Lume Desktop

Build Lume Desktop #6

Workflow file for this run

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