mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
The linuxdeploy failure was caused by CUDA shared library references in onnxruntime-node, not by linuxdeploy itself. The CUDA stripping step added in the previous commit fixes the root cause, so AppImage bundling should work now.
493 lines
19 KiB
YAML
493 lines
19 KiB
YAML
name: Desktop Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "v*"
|
|
- "desktop-v*"
|
|
- "desktop-macos-v*"
|
|
- "desktop-linux-v*"
|
|
- "desktop-windows-v*"
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "Existing tag to build (e.g. v0.1.0)"
|
|
required: true
|
|
type: string
|
|
platform:
|
|
description: "Optional desktop platform to build."
|
|
required: false
|
|
default: "all"
|
|
type: choice
|
|
options:
|
|
- all
|
|
- macos
|
|
- linux
|
|
- windows
|
|
|
|
concurrency:
|
|
group: desktop-release-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
SOURCE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
|
|
|
|
jobs:
|
|
publish-macos:
|
|
if: ${{ (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'macos')) || (github.event_name == 'push' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'desktop-v') || startsWith(github.ref_name, 'desktop-macos-v'))) }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: macos-14
|
|
rust_target: aarch64-apple-darwin
|
|
- runner: macos-15-intel
|
|
rust_target: x86_64-apple-darwin
|
|
permissions:
|
|
contents: write
|
|
packages: read
|
|
runs-on: ${{ matrix.runner }}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref }}
|
|
|
|
- name: Resolve release metadata
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
source_tag="${SOURCE_TAG}"
|
|
release_tag="$source_tag"
|
|
for prefix in desktop-windows-v desktop-linux-v desktop-macos-v desktop-v; do
|
|
if [[ "$source_tag" == ${prefix}* ]]; then
|
|
release_tag="v${source_tag#${prefix}}"
|
|
break
|
|
fi
|
|
done
|
|
echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV"
|
|
|
|
version="${release_tag#v}"
|
|
echo "DESKTOP_VERSION=$version" >> "$GITHUB_ENV"
|
|
|
|
if [[ "$source_tag" == *gha-smoke* ]]; then
|
|
echo "IS_SMOKE_TAG=true" >> "$GITHUB_ENV"
|
|
else
|
|
echo "IS_SMOKE_TAG=false" >> "$GITHUB_ENV"
|
|
fi
|
|
|
|
- name: Set desktop version from tag
|
|
shell: bash
|
|
run: |
|
|
node <<'NODE'
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const version = process.env.DESKTOP_VERSION;
|
|
if (!version) throw new Error('DESKTOP_VERSION env var is missing');
|
|
console.log(`Setting desktop version to ${version}`);
|
|
|
|
const tauriConfPath = path.join('packages', 'desktop', 'src-tauri', 'tauri.conf.json');
|
|
const tauriConfText = fs.readFileSync(tauriConfPath, 'utf8');
|
|
const tauriRe = /("version"\s*:\s*")([^"]+)(")/;
|
|
if (!tauriRe.test(tauriConfText)) throw new Error('Failed to find version in tauri.conf.json');
|
|
fs.writeFileSync(tauriConfPath, tauriConfText.replace(tauriRe, `$1${version}$3`));
|
|
|
|
const cargoTomlPath = path.join('packages', 'desktop', 'src-tauri', 'Cargo.toml');
|
|
const lines = fs.readFileSync(cargoTomlPath, 'utf8').split(/\r?\n/);
|
|
let inPackage = false, updated = false;
|
|
const result = lines.map((line) => {
|
|
if (/^\[package\]\s*$/.test(line)) inPackage = true;
|
|
else if (inPackage && /^\[/.test(line)) inPackage = false;
|
|
if (inPackage && /^version\s*=\s*".*"\s*$/.test(line)) {
|
|
updated = true;
|
|
return `version = "${version}"`;
|
|
}
|
|
return line;
|
|
});
|
|
if (!updated) throw new Error('Failed to update Cargo.toml version');
|
|
fs.writeFileSync(cargoTomlPath, result.join('\n') + '\n');
|
|
NODE
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
cache-dependency-path: package-lock.json
|
|
registry-url: "https://npm.pkg.github.com"
|
|
scope: "@boudra"
|
|
|
|
- name: Install Rust stable
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: ${{ matrix.rust_target }}
|
|
|
|
- name: Restore Rust cache
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
shared-key: desktop-release-macos-${{ matrix.rust_target }}
|
|
workspaces: |
|
|
.
|
|
packages/desktop/src-tauri -> target
|
|
|
|
- name: Install JS dependencies
|
|
run: npm ci
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Build web app for Tauri
|
|
run: npm run build:web --workspace=@getpaseo/app
|
|
|
|
- name: Build managed runtime
|
|
run: npm run prepare:managed-runtime --workspace=@getpaseo/desktop
|
|
|
|
- name: Validate managed runtime bundle
|
|
run: npm run validate:managed-runtime --workspace=@getpaseo/desktop
|
|
|
|
- name: Import Apple code-signing certificate
|
|
uses: apple-actions/import-codesign-certs@v3
|
|
with:
|
|
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
|
|
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
|
|
- name: Sign bundled managed runtime
|
|
env:
|
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
|
run: node ./packages/desktop/scripts/sign-managed-runtime-macos.mjs
|
|
|
|
- name: Detect existing GitHub release state
|
|
if: env.IS_SMOKE_TAG != 'true'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if release_draft="$(gh release view "$RELEASE_TAG" --repo "${{ github.repository }}" --json isDraft --jq '.isDraft' 2>/dev/null)"; then
|
|
:
|
|
else
|
|
release_draft="false"
|
|
fi
|
|
echo "RELEASE_DRAFT=$release_draft" >> "$GITHUB_ENV"
|
|
|
|
- name: Build and publish macOS Tauri release
|
|
if: env.IS_SMOKE_TAG != 'true'
|
|
uses: tauri-apps/tauri-action@v0
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
|
with:
|
|
projectPath: packages/desktop
|
|
tagName: ${{ env.RELEASE_TAG }}
|
|
releaseName: Paseo ${{ env.RELEASE_TAG }}
|
|
releaseBody: See the assets to download and install this version.
|
|
releaseDraft: ${{ env.RELEASE_DRAFT }}
|
|
prerelease: false
|
|
args: --target ${{ matrix.rust_target }}
|
|
|
|
- name: Build macOS app (smoke only)
|
|
if: env.IS_SMOKE_TAG == 'true'
|
|
run: npm run tauri --workspace=@getpaseo/desktop build -- --target ${{ matrix.rust_target }} --no-bundle
|
|
|
|
publish-linux:
|
|
if: ${{ (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'linux')) || (github.event_name == 'push' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'desktop-v') || startsWith(github.ref_name, 'desktop-linux-v'))) }}
|
|
permissions:
|
|
contents: write
|
|
packages: read
|
|
runs-on: ubuntu-22.04
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref }}
|
|
|
|
- name: Resolve release metadata
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
source_tag="${SOURCE_TAG}"
|
|
release_tag="$source_tag"
|
|
for prefix in desktop-windows-v desktop-linux-v desktop-macos-v desktop-v; do
|
|
if [[ "$source_tag" == ${prefix}* ]]; then
|
|
release_tag="v${source_tag#${prefix}}"
|
|
break
|
|
fi
|
|
done
|
|
echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV"
|
|
|
|
version="${release_tag#v}"
|
|
echo "DESKTOP_VERSION=$version" >> "$GITHUB_ENV"
|
|
|
|
if [[ "$source_tag" == *gha-smoke* ]]; then
|
|
echo "IS_SMOKE_TAG=true" >> "$GITHUB_ENV"
|
|
else
|
|
echo "IS_SMOKE_TAG=false" >> "$GITHUB_ENV"
|
|
fi
|
|
|
|
- name: Set desktop version from tag
|
|
shell: bash
|
|
run: |
|
|
node <<'NODE'
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const version = process.env.DESKTOP_VERSION;
|
|
if (!version) throw new Error('DESKTOP_VERSION env var is missing');
|
|
console.log(`Setting desktop version to ${version}`);
|
|
|
|
const tauriConfPath = path.join('packages', 'desktop', 'src-tauri', 'tauri.conf.json');
|
|
const tauriConfText = fs.readFileSync(tauriConfPath, 'utf8');
|
|
const tauriRe = /("version"\s*:\s*")([^"]+)(")/;
|
|
if (!tauriRe.test(tauriConfText)) throw new Error('Failed to find version in tauri.conf.json');
|
|
fs.writeFileSync(tauriConfPath, tauriConfText.replace(tauriRe, `$1${version}$3`));
|
|
|
|
const cargoTomlPath = path.join('packages', 'desktop', 'src-tauri', 'Cargo.toml');
|
|
const lines = fs.readFileSync(cargoTomlPath, 'utf8').split(/\r?\n/);
|
|
let inPackage = false, updated = false;
|
|
const result = lines.map((line) => {
|
|
if (/^\[package\]\s*$/.test(line)) inPackage = true;
|
|
else if (inPackage && /^\[/.test(line)) inPackage = false;
|
|
if (inPackage && /^version\s*=\s*".*"\s*$/.test(line)) {
|
|
updated = true;
|
|
return `version = "${version}"`;
|
|
}
|
|
return line;
|
|
});
|
|
if (!updated) throw new Error('Failed to update Cargo.toml version');
|
|
fs.writeFileSync(cargoTomlPath, result.join('\n') + '\n');
|
|
NODE
|
|
|
|
- name: Install Linux packaging dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y libwebkit2gtk-4.1-dev libgtk-3-dev libappindicator3-dev librsvg2-dev patchelf libfuse2
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
cache-dependency-path: package-lock.json
|
|
registry-url: "https://npm.pkg.github.com"
|
|
scope: "@boudra"
|
|
|
|
- name: Install Rust stable
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Restore Rust cache
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
shared-key: desktop-release-linux
|
|
workspaces: |
|
|
.
|
|
packages/desktop/src-tauri -> target
|
|
|
|
- name: Install JS dependencies
|
|
run: npm ci
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Build web app for Tauri
|
|
run: npm run build:web --workspace=@getpaseo/app
|
|
|
|
- name: Build managed runtime
|
|
run: npm run prepare:managed-runtime --workspace=@getpaseo/desktop
|
|
|
|
- name: Validate managed runtime bundle
|
|
run: npm run validate:managed-runtime --workspace=@getpaseo/desktop
|
|
|
|
- name: Strip CUDA dependencies from onnxruntime
|
|
shell: bash
|
|
run: |
|
|
find packages/desktop/src-tauri/resources/managed-runtime -path '*/onnxruntime-node/bin/*' \( -name '*cuda*' -o -name '*tensorrt*' \) -delete || true
|
|
# Remove CUDA shared library references from onnxruntime .so files so linuxdeploy
|
|
# doesn't try to bundle them (they're optional runtime deps, not needed for CPU inference)
|
|
for f in $(find packages/desktop/src-tauri/resources/managed-runtime -path '*/onnxruntime-node/bin/*' \( -name '*.so' -o -name '*.so.*' \)); do
|
|
for lib in $(patchelf --print-needed "$f" 2>/dev/null | grep -iE 'cublas|cudnn|cudart|cufft|curand|cusolver|cusparse|nccl|nvrtc|tensorrt|nvinfer'); do
|
|
echo "Removing needed $lib from $f"
|
|
patchelf --remove-needed "$lib" "$f"
|
|
done
|
|
done
|
|
|
|
- name: Detect existing GitHub release state
|
|
if: env.IS_SMOKE_TAG != 'true'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if release_draft="$(gh release view "$RELEASE_TAG" --repo "${{ github.repository }}" --json isDraft --jq '.isDraft' 2>/dev/null)"; then
|
|
:
|
|
else
|
|
release_draft="false"
|
|
fi
|
|
echo "RELEASE_DRAFT=$release_draft" >> "$GITHUB_ENV"
|
|
|
|
- name: Build and publish Linux Tauri release
|
|
if: env.IS_SMOKE_TAG != 'true'
|
|
uses: tauri-apps/tauri-action@v0
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
|
NO_STRIP: "true"
|
|
APPIMAGE_EXTRACT_AND_RUN: "1"
|
|
with:
|
|
projectPath: packages/desktop
|
|
tagName: ${{ env.RELEASE_TAG }}
|
|
releaseName: Paseo ${{ env.RELEASE_TAG }}
|
|
releaseBody: See the assets to download and install this version.
|
|
releaseDraft: ${{ env.RELEASE_DRAFT }}
|
|
prerelease: false
|
|
args: --bundles appimage
|
|
|
|
- name: Build Linux app (smoke only)
|
|
if: env.IS_SMOKE_TAG == 'true'
|
|
run: npm run tauri --workspace=@getpaseo/desktop build -- --no-bundle
|
|
|
|
publish-windows:
|
|
if: ${{ (github.event_name == 'workflow_dispatch' && (github.event.inputs.platform == 'all' || github.event.inputs.platform == 'windows')) || (github.event_name == 'push' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'desktop-v') || startsWith(github.ref_name, 'desktop-windows-v'))) }}
|
|
permissions:
|
|
contents: write
|
|
packages: read
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref }}
|
|
|
|
- name: Resolve release metadata
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
source_tag="${SOURCE_TAG}"
|
|
release_tag="$source_tag"
|
|
for prefix in desktop-windows-v desktop-linux-v desktop-macos-v desktop-v; do
|
|
if [[ "$source_tag" == ${prefix}* ]]; then
|
|
release_tag="v${source_tag#${prefix}}"
|
|
break
|
|
fi
|
|
done
|
|
echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV"
|
|
|
|
version="${release_tag#v}"
|
|
echo "DESKTOP_VERSION=$version" >> "$GITHUB_ENV"
|
|
|
|
if [[ "$source_tag" == *gha-smoke* ]]; then
|
|
echo "IS_SMOKE_TAG=true" >> "$GITHUB_ENV"
|
|
else
|
|
echo "IS_SMOKE_TAG=false" >> "$GITHUB_ENV"
|
|
fi
|
|
|
|
- name: Set desktop version from tag
|
|
shell: bash
|
|
run: |
|
|
node <<'NODE'
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const version = process.env.DESKTOP_VERSION;
|
|
if (!version) throw new Error('DESKTOP_VERSION env var is missing');
|
|
console.log(`Setting desktop version to ${version}`);
|
|
|
|
const tauriConfPath = path.join('packages', 'desktop', 'src-tauri', 'tauri.conf.json');
|
|
const tauriConfText = fs.readFileSync(tauriConfPath, 'utf8');
|
|
const tauriRe = /("version"\s*:\s*")([^"]+)(")/;
|
|
if (!tauriRe.test(tauriConfText)) throw new Error('Failed to find version in tauri.conf.json');
|
|
fs.writeFileSync(tauriConfPath, tauriConfText.replace(tauriRe, `$1${version}$3`));
|
|
|
|
const cargoTomlPath = path.join('packages', 'desktop', 'src-tauri', 'Cargo.toml');
|
|
const lines = fs.readFileSync(cargoTomlPath, 'utf8').split(/\r?\n/);
|
|
let inPackage = false, updated = false;
|
|
const result = lines.map((line) => {
|
|
if (/^\[package\]\s*$/.test(line)) inPackage = true;
|
|
else if (inPackage && /^\[/.test(line)) inPackage = false;
|
|
if (inPackage && /^version\s*=\s*".*"\s*$/.test(line)) {
|
|
updated = true;
|
|
return `version = "${version}"`;
|
|
}
|
|
return line;
|
|
});
|
|
if (!updated) throw new Error('Failed to update Cargo.toml version');
|
|
fs.writeFileSync(cargoTomlPath, result.join('\n') + '\n');
|
|
NODE
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
cache-dependency-path: package-lock.json
|
|
registry-url: "https://npm.pkg.github.com"
|
|
scope: "@boudra"
|
|
|
|
- name: Install Rust stable
|
|
uses: dtolnay/rust-toolchain@stable
|
|
|
|
- name: Restore Rust cache
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
shared-key: desktop-release-windows
|
|
workspaces: |
|
|
.
|
|
packages/desktop/src-tauri -> target
|
|
|
|
- name: Install JS dependencies
|
|
run: npm ci
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Build web app for Tauri
|
|
run: npm run build:web --workspace=@getpaseo/app
|
|
|
|
- name: Build managed runtime
|
|
run: npm run prepare:managed-runtime --workspace=@getpaseo/desktop
|
|
|
|
- name: Validate managed runtime bundle
|
|
run: npm run validate:managed-runtime --workspace=@getpaseo/desktop
|
|
|
|
- name: Detect existing GitHub release state
|
|
if: env.IS_SMOKE_TAG != 'true'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if release_draft="$(gh release view "$RELEASE_TAG" --repo "${{ github.repository }}" --json isDraft --jq '.isDraft' 2>/dev/null)"; then
|
|
:
|
|
else
|
|
release_draft="false"
|
|
fi
|
|
echo "RELEASE_DRAFT=$release_draft" >> "$GITHUB_ENV"
|
|
|
|
- name: Build and publish Windows Tauri release
|
|
if: env.IS_SMOKE_TAG != 'true'
|
|
uses: tauri-apps/tauri-action@v0
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
|
with:
|
|
projectPath: packages/desktop
|
|
tagName: ${{ env.RELEASE_TAG }}
|
|
releaseName: Paseo ${{ env.RELEASE_TAG }}
|
|
releaseBody: See the assets to download and install this version.
|
|
releaseDraft: ${{ env.RELEASE_DRAFT }}
|
|
prerelease: false
|
|
args: --bundles nsis,msi
|
|
|
|
- name: Build Windows app (smoke only)
|
|
if: env.IS_SMOKE_TAG == 'true'
|
|
run: npm run tauri --workspace=@getpaseo/desktop build -- --no-bundle
|
|
env:
|
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|