diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml index e06bcbce3..67b0af7fe 100644 --- a/.github/workflows/desktop-release.yml +++ b/.github/workflows/desktop-release.yml @@ -386,9 +386,9 @@ jobs: set -euxo pipefail appimage_dir="packages/desktop/src-tauri/target/release/bundle/appimage" appdir_path="$appimage_dir/Paseo.AppDir" + canonical_appimage="$appimage_dir/Paseo_${DESKTOP_VERSION}_amd64.AppImage" existing_appimage="$(find "$appimage_dir" -maxdepth 1 -type f -name '*.AppImage' | head -n 1)" if [ -n "$existing_appimage" ]; then - canonical_appimage="$appimage_dir/Paseo_${DESKTOP_VERSION}_amd64.AppImage" if [ "$existing_appimage" != "$canonical_appimage" ]; then mv "$existing_appimage" "$canonical_appimage" fi @@ -403,32 +403,9 @@ jobs: fi env | sort | grep -E '^(APPIMAGE|DESKTOP_VERSION|NO_STRIP|RELEASE_TAG|SOURCE_TAG|TAURI_)' || true tools_dir="$(mktemp -d)" - curl -fsSL https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20251107-1/linuxdeploy-x86_64.AppImage -o "$tools_dir/linuxdeploy-x86_64.AppImage" - curl -fsSL https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/1-alpha-20250213-1/linuxdeploy-plugin-appimage-x86_64.AppImage -o "$tools_dir/linuxdeploy-plugin-appimage-x86_64.AppImage" - curl -fsSL https://raw.githubusercontent.com/tauri-apps/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh -o "$tools_dir/linuxdeploy-plugin-gtk.sh" - curl -fsSL https://raw.githubusercontent.com/tauri-apps/linuxdeploy-plugin-gstreamer/master/linuxdeploy-plugin-gstreamer.sh -o "$tools_dir/linuxdeploy-plugin-gstreamer.sh" - chmod +x "$tools_dir"/linuxdeploy* - export PATH="$tools_dir:$PATH" - export NO_STRIP=1 - export APPIMAGE_EXTRACT_AND_RUN=1 - ( - cd "$appimage_dir" - "$tools_dir/linuxdeploy-x86_64.AppImage" \ - --verbosity 2 \ - --appdir "Paseo.AppDir" \ - --plugin gtk \ - --plugin gstreamer \ - --output appimage - ) - manual_appimage="$(find "$appimage_dir" -maxdepth 1 -type f -name '*.AppImage' | head -n 1)" - if [ -z "$manual_appimage" ]; then - echo "::error::Manual linuxdeploy run did not produce an AppImage" - exit 1 - fi - canonical_appimage="$appimage_dir/Paseo_${DESKTOP_VERSION}_amd64.AppImage" - if [ "$manual_appimage" != "$canonical_appimage" ]; then - mv "$manual_appimage" "$canonical_appimage" - fi + curl -fsSL https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -o "$tools_dir/appimagetool-x86_64.AppImage" + chmod +x "$tools_dir/appimagetool-x86_64.AppImage" + ARCH=x86_64 APPIMAGE_EXTRACT_AND_RUN=1 "$tools_dir/appimagetool-x86_64.AppImage" "$appdir_path" "$canonical_appimage" npx tauri signer sign "$canonical_appimage" - name: Fail Linux release when AppImage bundling fails diff --git a/packages/desktop/scripts/build-managed-runtime.mjs b/packages/desktop/scripts/build-managed-runtime.mjs index e699f8ef5..7ccaa50da 100644 --- a/packages/desktop/scripts/build-managed-runtime.mjs +++ b/packages/desktop/scripts/build-managed-runtime.mjs @@ -288,27 +288,23 @@ async function installPackedWorkspaces(runtimeRoot, bundledNodeRoot, tarballs) { const npmCli = process.platform === "win32" ? path.join(bundledNodeRoot, "node_modules", "npm", "bin", "npm-cli.js") : path.join(bundledNodeRoot, "lib", "node_modules", "npm", "bin", "npm-cli.js"); - const install = spawnSync( - nodeExecutable, - [ - npmCli, - "install", - "--include=optional", - "--omit=dev", - "--no-package-lock", - "--no-save", - ...tarballs, - ], - { - cwd: runtimeRoot, - stdio: "inherit", - env: { - ...process.env, - npm_config_audit: "false", - npm_config_fund: "false", - }, - } - ); + const install = spawnSync(nodeExecutable, [ + npmCli, + "install", + "--include=optional", + "--omit=dev", + "--no-package-lock", + "--no-save", + ...tarballs, + ], { + cwd: runtimeRoot, + stdio: "inherit", + env: { + ...process.env, + npm_config_audit: "false", + npm_config_fund: "false", + }, + }); if (install.status !== 0) { throw new Error( `Managed runtime dependency install failed with exit code ${install.status ?? 1}.` @@ -316,6 +312,67 @@ async function installPackedWorkspaces(runtimeRoot, bundledNodeRoot, tarballs) { } } +function resolveSherpaNativePackageName() { + const sherpaPlatformMap = { + darwin: "darwin", + linux: "linux", + win32: "win", + }; + const sherpaPlatform = sherpaPlatformMap[process.platform]; + if (!sherpaPlatform) { + throw new Error(`Managed runtime sherpa package is not implemented for ${process.platform}.`); + } + return `sherpa-onnx-${sherpaPlatform}-${process.arch}`; +} + +async function ensureSherpaNativePackage(runtimeRoot, bundledNodeRoot) { + const packageName = resolveSherpaNativePackageName(); + const packageDir = path.join(runtimeRoot, "node_modules", packageName); + if (await pathExists(packageDir)) { + return; + } + + const sherpaNodePackageJson = JSON.parse( + await fs.readFile( + path.join(runtimeRoot, "node_modules", "sherpa-onnx-node", "package.json"), + "utf8" + ) + ); + const versionRange = sherpaNodePackageJson.optionalDependencies?.[packageName]; + if (!versionRange) { + throw new Error(`Unable to resolve optional sherpa package version for ${packageName}.`); + } + + const nodeExecutable = process.platform === "win32" + ? path.join(bundledNodeRoot, "node.exe") + : path.join(bundledNodeRoot, "bin", "node"); + const npmCli = process.platform === "win32" + ? path.join(bundledNodeRoot, "node_modules", "npm", "bin", "npm-cli.js") + : path.join(bundledNodeRoot, "lib", "node_modules", "npm", "bin", "npm-cli.js"); + const install = spawnSync(nodeExecutable, [ + npmCli, + "install", + "--include=optional", + "--omit=dev", + "--no-package-lock", + "--no-save", + `${packageName}@${versionRange}`, + ], { + cwd: runtimeRoot, + stdio: "inherit", + env: { + ...process.env, + npm_config_audit: "false", + npm_config_fund: "false", + }, + }); + if (install.status !== 0) { + throw new Error( + `Managed runtime sherpa package install failed with exit code ${install.status ?? 1}.` + ); + } +} + async function writeRuntimePackageJson(runtimeRoot) { await fs.writeFile( path.join(runtimeRoot, "package.json"), @@ -529,6 +586,7 @@ async function main() { path.join(runtimeRoot, "node"), tarballs.map((entry) => entry.path) ); + await ensureSherpaNativePackage(runtimeRoot, path.join(runtimeRoot, "node")); await pruneManagedRuntime(runtimeRoot); const nodeRelativePath = process.platform === "win32"