From 1eb98b669a78c45bc38e526e8917b3ab9a295241 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 25 Aug 2026 00:39:54 +0000 Subject: [PATCH] ci: add Linux ARM64 desktop release packages (#11518) --- .github/workflows/build-cli-linux.yml | 231 +++++++++++++++- .github/workflows/build-cli.yml | 1 + .github/workflows/bundle-desktop-linux.yml | 260 ------------------ .github/workflows/canary.yml | 18 +- .github/workflows/release.yml | 16 +- .../components/LinuxDesktopInstallButtons.js | 39 ++- ui/desktop/README.md | 25 +- 7 files changed, 290 insertions(+), 300 deletions(-) delete mode 100644 .github/workflows/bundle-desktop-linux.yml diff --git a/.github/workflows/build-cli-linux.yml b/.github/workflows/build-cli-linux.yml index 53e43c129..a78d2374d 100644 --- a/.github/workflows/build-cli-linux.yml +++ b/.github/workflows/build-cli-linux.yml @@ -1,5 +1,11 @@ on: workflow_dispatch: + inputs: + package_desktop: + description: 'Also package Linux desktop artifacts; CLI artifacts are always included' + required: false + default: false + type: boolean workflow_call: inputs: version: @@ -10,15 +16,20 @@ on: type: string required: false default: "" + package_desktop: + description: 'Also package Linux desktop artifacts; CLI artifacts are always included' + required: false + default: false + type: boolean -name: "Build CLI for Linux" +name: "Build CLI and optionally Desktop for Linux" permissions: contents: read jobs: build-cli-linux: - name: Build CLI + name: Build Goose (Linux, ${{ matrix.architecture }}, ${{ matrix.variant }}) runs-on: ${{ matrix.build-on }} container: ${{ matrix.container }} strategy: @@ -189,3 +200,219 @@ jobs: path: | ${{ env.ARTIFACT_BZ2 }} ${{ env.ARTIFACT_GZ }} + + - name: Prepare internal Goose binary + if: ${{ inputs.package_desktop && matrix.target-suffix == 'unknown-linux-gnu' }} + env: + TARGET: ${{ matrix.architecture }}-${{ matrix.target-suffix }} + VARIANT_SUFFIX: ${{ matrix.variant == 'vulkan' && '-vulkan' || '' }} + run: | + mkdir -p artifacts + cp "target/${TARGET}/release/goose" "artifacts/internal-goose-${TARGET}${VARIANT_SUFFIX}" + + - name: Upload internal Goose binary + if: ${{ inputs.package_desktop && matrix.target-suffix == 'unknown-linux-gnu' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: internal-goose-${{ matrix.architecture }}-${{ matrix.target-suffix }}${{ matrix.variant == 'vulkan' && '-vulkan' || '' }} + path: artifacts/internal-goose-${{ matrix.architecture }}-${{ matrix.target-suffix }}${{ matrix.variant == 'vulkan' && '-vulkan' || '' }} + if-no-files-found: error + retention-days: 1 + overwrite: true + + package-desktop-linux: + name: Package Desktop (Linux, ${{ matrix.electron_arch }}, ${{ matrix.variant }}) + if: ${{ inputs.package_desktop }} + needs: build-cli-linux + runs-on: ${{ matrix.build_on }} + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu + electron_arch: x64 + flatpak_arch: x86_64 + variant: standard + variant_suffix: '' + build_on: ubuntu-22.04 + - target: aarch64-unknown-linux-gnu + electron_arch: arm64 + flatpak_arch: aarch64 + variant: standard + variant_suffix: '' + build_on: ubuntu-22.04-arm + - target: x86_64-unknown-linux-gnu + electron_arch: x64 + flatpak_arch: x86_64 + variant: vulkan + variant_suffix: '-vulkan' + build_on: ubuntu-24.04 + - target: aarch64-unknown-linux-gnu + electron_arch: arm64 + flatpak_arch: aarch64 + variant: vulkan + variant_suffix: '-vulkan' + build_on: ubuntu-24.04-arm + + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ inputs.ref }} + + - name: Update desktop version + if: ${{ inputs.version != '' }} + env: + VERSION: ${{ inputs.version }} + run: | + source ./bin/activate-hermit + cd ui/desktop + npm pkg set "version=${VERSION}" + + - name: Debug workflow info + env: + WORKFLOW_NAME: ${{ github.workflow }} + WORKFLOW_REF: ${{ github.ref }} + EVENT_NAME: ${{ github.event_name }} + REPOSITORY: ${{ github.repository }} + TARGET: ${{ matrix.target }} + VARIANT: ${{ matrix.variant }} + run: | + echo "=== Workflow Information ===" + echo "Workflow: ${WORKFLOW_NAME}" + echo "Ref: ${WORKFLOW_REF}" + echo "Event: ${EVENT_NAME}" + echo "Repo: ${REPOSITORY}" + echo "Target: ${TARGET}" + echo "Variant: ${VARIANT}" + echo "" + echo "=== System Information ===" + uname -a + lsb_release -a || true + df -h + + - name: Install system dependencies + env: + VARIANT: ${{ matrix.variant }} + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + libnss3-dev \ + libatk-bridge2.0-dev \ + libdrm2 \ + libxcomposite1 \ + libxdamage1 \ + libxrandr2 \ + libgbm1 \ + libxss1 \ + rpm \ + fakeroot \ + dpkg-dev \ + protobuf-compiler \ + flatpak \ + flatpak-builder \ + elfutils + + if [ "${VARIANT}" = "vulkan" ]; then + sudo apt-get install -y \ + libasound2t64 \ + libvulkan-dev \ + libvulkan1 \ + glslc + else + sudo apt-get install -y libasound2 + fi + + - name: Configure RPM packaging + run: | + echo '%_build_id_links none' > ~/.rpmmacros + test "$(rpm --eval '%{_build_id_links}')" = "none" + + - name: Setup Flatpak runtimes + run: flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo + + - name: Download internal Goose binary + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: internal-goose-${{ matrix.target }}${{ matrix.variant_suffix }} + path: backend + + - name: Prepare desktop backend + env: + INTERNAL_BINARY: internal-goose-${{ matrix.target }}${{ matrix.variant_suffix }} + run: | + mkdir -p ui/desktop/src/bin + rm -f ui/desktop/src/bin/goose + mv "backend/${INTERNAL_BINARY}" ui/desktop/src/bin/goose + chmod +x ui/desktop/src/bin/goose + file ui/desktop/src/bin/goose + + - name: Cache pnpm dependencies + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ui/desktop/node_modules + .hermit/node/cache + key: linux-pnpm-cache-v1-${{ matrix.electron_arch }}-${{ matrix.variant }}-${{ runner.os }}-${{ hashFiles('ui/pnpm-lock.yaml') }} + restore-keys: | + linux-pnpm-cache-v1-${{ matrix.electron_arch }}-${{ matrix.variant }}-${{ runner.os }}- + + - name: Install pnpm dependencies + run: | + source ./bin/activate-hermit + cd ui/desktop + pnpm install --frozen-lockfile + + - name: Build Linux packages + env: + ELECTRON_ARCH: ${{ matrix.electron_arch }} + FLATPAK_ARCH: ${{ matrix.flatpak_arch }} + GOOSE_DESKTOP_LINUX_VARIANT: ${{ matrix.variant }} + run: | + source ./bin/activate-hermit + cd ui/desktop + pnpm run make --platform=linux --arch="${ELECTRON_ARCH}" + + if [ "${GOOSE_DESKTOP_LINUX_VARIANT}" = "vulkan" ]; then + for package in \ + "out/make/deb/${ELECTRON_ARCH}/"*.deb \ + "out/make/rpm/${ELECTRON_ARCH}/"*.rpm \ + "out/make/flatpak/${FLATPAK_ARCH}/"*.flatpak; do + [ -e "${package}" ] || continue + extension="${package##*.}" + base="${package%.*}" + mv "${package}" "${base}-vulkan.${extension}" + done + fi + + for package in "out/make/rpm/${ELECTRON_ARCH}/"*.rpm; do + package_contents="$(rpm -qlp "${package}")" + if grep -qE '^/usr/lib/\.build-id(/|$)' <<< "${package_contents}"; then + echo "::error file=${package}::RPM contains build-id links" + exit 1 + fi + done + + find out/ -type f \( -name "*.deb" -o -name "*.rpm" -o -name "*.flatpak" \) -exec ls -lh {} \; + + - name: Upload .deb package + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: Goose-linux-${{ matrix.electron_arch }}${{ matrix.variant_suffix }}-deb + path: ui/desktop/out/make/deb/${{ matrix.electron_arch }}/*${{ matrix.variant_suffix }}.deb + if-no-files-found: error + + - name: Upload .rpm package + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: Goose-linux-${{ matrix.electron_arch }}${{ matrix.variant_suffix }}-rpm + path: ui/desktop/out/make/rpm/${{ matrix.electron_arch }}/*${{ matrix.variant_suffix }}.rpm + if-no-files-found: error + + - name: Upload .flatpak package + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: Goose-linux-${{ matrix.electron_arch }}${{ matrix.variant_suffix }}-flatpak + path: ui/desktop/out/make/flatpak/${{ matrix.flatpak_arch }}/*${{ matrix.variant_suffix }}.flatpak + if-no-files-found: error diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 250458a37..b65db91cb 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -66,3 +66,4 @@ jobs: with: version: ${{ inputs.version }} ref: ${{ inputs.ref }} + package_desktop: false diff --git a/.github/workflows/bundle-desktop-linux.yml b/.github/workflows/bundle-desktop-linux.yml deleted file mode 100644 index 128eb996b..000000000 --- a/.github/workflows/bundle-desktop-linux.yml +++ /dev/null @@ -1,260 +0,0 @@ -# This is a **reuseable** workflow that bundles the Desktop App for Linux. -# It doesn't get triggered on its own. It gets used in multiple workflows: -# - release.yml -# - canary.yml (when added) -# - pr-comment-bundle-desktop.yml (when added) -on: - workflow_dispatch: - workflow_call: - inputs: - version: - description: 'Version to set for the build' - required: false - default: "" - type: string - ref: - type: string - required: false - default: '' - -name: "Bundle Desktop (Linux)" - -permissions: - contents: read - -jobs: - build-desktop-linux: - name: Build Desktop (Linux, ${{ matrix.variant }}) - runs-on: ${{ matrix.build-on }} - strategy: - fail-fast: false - matrix: - include: - - variant: standard - build-on: ubuntu-22.04 - - variant: vulkan - build-on: ubuntu-24.04 - - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - ref: ${{ inputs.ref }} - - - name: Update versions - if: ${{ inputs.version != '' }} - env: - VERSION: ${{ inputs.version }} - run: | - bash scripts/set-cargo-version.sh "$VERSION" - source ./bin/activate-hermit - cd ui/desktop - npm pkg set "version=${VERSION}" - - - name: Debug workflow info - env: - WORKFLOW_NAME: ${{ github.workflow }} - WORKFLOW_REF: ${{ github.ref }} - EVENT_NAME: ${{ github.event_name }} - REPOSITORY: ${{ github.repository }} - run: | - echo "=== Workflow Information ===" - echo "Workflow: ${WORKFLOW_NAME}" - echo "Ref: ${WORKFLOW_REF}" - echo "Event: ${EVENT_NAME}" - echo "Repo: ${REPOSITORY}" - echo "" - echo "=== System Information ===" - uname -a - lsb_release -a || true - df -h - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - build-essential \ - libnss3-dev \ - libatk-bridge2.0-dev \ - libdrm2 \ - libxcomposite1 \ - libxdamage1 \ - libxrandr2 \ - libgbm1 \ - libxss1 \ - rpm \ - fakeroot \ - dpkg-dev \ - protobuf-compiler \ - flatpak \ - flatpak-builder \ - elfutils - - if [ "${{ matrix.variant }}" = "vulkan" ]; then - sudo apt-get install -y \ - libasound2t64 \ - libvulkan-dev \ - libvulkan1 \ - glslc - else - sudo apt-get install -y libasound2 - fi - - - name: Configure RPM packaging - run: | - echo '%_build_id_links none' > ~/.rpmmacros - test "$(rpm --eval '%{_build_id_links}')" = "none" - - - name: Setup Flatpak Runtimes - run: | - flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo - - - name: Activate hermit and set CARGO_HOME - run: | - source bin/activate-hermit - echo "CARGO_HOME=$CARGO_HOME" >> $GITHUB_ENV - echo "RUSTUP_HOME=$RUSTUP_HOME" >> $GITHUB_ENV - - - name: Cache Rust dependencies - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - with: - key: linux-${{ matrix.build-on }}-${{ matrix.variant }} - - - name: Build desktop backend binary - env: - RUST_LOG: debug - RUST_BACKTRACE: 1 - run: | - source ./bin/activate-hermit - export TARGET="x86_64-unknown-linux-gnu" - rustup target add "${TARGET}" - FEATURE_ARGS=() - if [ "${{ matrix.variant }}" = "vulkan" ]; then - FEATURE_ARGS=(--features vulkan) - fi - - cargo build --release --target ${TARGET} -p goose-cli --bin goose "${FEATURE_ARGS[@]}" - - - name: Copy backend binary into Electron folder - run: | - echo "Copying backend binary to ui/desktop/src/bin/" - export TARGET="x86_64-unknown-linux-gnu" - mkdir -p ui/desktop/src/bin - rm -f ui/desktop/src/bin/goose - cp target/$TARGET/release/goose ui/desktop/src/bin/ - chmod +x ui/desktop/src/bin/goose - ls -la ui/desktop/src/bin/ - - - name: Free Rust build artifacts before packaging - run: | - source ./bin/activate-hermit - cargo clean - - - name: Cache pnpm dependencies - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 - with: - path: | - ui/desktop/node_modules - .hermit/node/cache - key: linux-pnpm-cache-v1-${{ runner.os }}-${{ hashFiles('ui/pnpm-lock.yaml') }} - restore-keys: | - linux-pnpm-cache-v1-${{ runner.os }}- - - - name: Install pnpm dependencies - run: | - source ./bin/activate-hermit - cd ui/desktop - pnpm install --frozen-lockfile - # Verify installation - ls -la node_modules/.bin/ | head -5 - - - name: Build Linux packages - env: - GOOSE_DESKTOP_LINUX_VARIANT: ${{ matrix.variant }} - run: | - source ./bin/activate-hermit - cd ui/desktop - echo "Building Linux packages (.deb, .rpm, and .flatpak) for ${{ matrix.variant }}..." - - # Build all configured packages - pnpm run make --platform=linux --arch=x64 - - if [ "${{ matrix.variant }}" = "vulkan" ]; then - for package in out/make/deb/x64/*.deb out/make/rpm/x64/*.rpm out/make/flatpak/x86_64/*.flatpak; do - [ -e "$package" ] || continue - extension="${package##*.}" - base="${package%.*}" - mv "$package" "${base}-vulkan.${extension}" - done - fi - - for package in out/make/rpm/x64/*.rpm; do - package_contents="$(rpm -qlp "$package")" - if grep -qE '^/usr/lib/\.build-id(/|$)' <<< "$package_contents"; then - echo "::error file=$package::RPM contains build-id links" - exit 1 - fi - done - - echo "Build completed. Checking output..." - ls -la out/ - find out/ -name "*.deb" -o -name "*.rpm" -o -name "*.flatpak" | head -10 - - - name: List generated files - run: | - echo "=== All files in out/ directory ===" - find ui/desktop/out/ -type f | head -20 - echo "" - echo "=== Package files specifically ===" - find ui/desktop/out/ -name "*.deb" -o -name "*.rpm" -o -name "*.flatpak" - echo "" - echo "=== File sizes ===" - find ui/desktop/out/ -name "*.deb" -o -name "*.rpm" -o -name "*.flatpak" -exec ls -lh {} \; - - - name: Upload .deb package - if: matrix.variant == 'standard' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Goose-linux-x64-deb - path: ui/desktop/out/make/deb/x64/*.deb - if-no-files-found: error - - - name: Upload .deb package (Vulkan) - if: matrix.variant == 'vulkan' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Goose-linux-x64-vulkan-deb - path: ui/desktop/out/make/deb/x64/*-vulkan.deb - if-no-files-found: error - - - name: Upload .rpm package - if: matrix.variant == 'standard' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Goose-linux-x64-rpm - path: ui/desktop/out/make/rpm/x64/*.rpm - if-no-files-found: error - - - name: Upload .rpm package (Vulkan) - if: matrix.variant == 'vulkan' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Goose-linux-x64-vulkan-rpm - path: ui/desktop/out/make/rpm/x64/*-vulkan.rpm - if-no-files-found: error - - - name: Upload .flatpak package - if: matrix.variant == 'standard' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Goose-linux-x64-flatpak - path: ui/desktop/out/make/flatpak/x86_64/*.flatpak - if-no-files-found: error - - - name: Upload .flatpak package (Vulkan) - if: matrix.variant == 'vulkan' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: Goose-linux-x64-vulkan-flatpak - path: ui/desktop/out/make/flatpak/x86_64/*-vulkan.flatpak - if-no-files-found: error diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index e9da0430b..1f3be2f9a 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -40,13 +40,14 @@ jobs: echo "version=$VERSION" >> $GITHUB_OUTPUT # ------------------------------------ - # 2) Build CLI targets not produced by desktop workflows + # 2) Bundle CLI and Desktop (Linux) # ------------------------------------ build-cli-linux: needs: [prepare-version] uses: ./.github/workflows/build-cli-linux.yml with: version: ${{ needs.prepare-version.outputs.version }} + package_desktop: true # ------------------------------------ # 3) Upload Install CLI Script (we only need to do this once) @@ -92,16 +93,7 @@ jobs: signing: false # ------------------------------------------------------------ - # 6) Bundle Desktop App (Linux) - # ------------------------------------------------------------ - bundle-desktop-linux: - needs: [prepare-version] - uses: ./.github/workflows/bundle-desktop-linux.yml - with: - version: ${{ needs.prepare-version.outputs.version }} - - # ------------------------------------------------------------ - # 7) Bundle CLI and Desktop (Windows) + # 6) Bundle CLI and Desktop (Windows) # ------------------------------------------------------------ bundle-windows: needs: [prepare-version] @@ -129,12 +121,12 @@ jobs: windows_variant: cuda # ------------------------------------ - # 8) Create/Update GitHub Release + # 7) Create/Update GitHub Release # ------------------------------------ release: name: Release runs-on: ubuntu-latest - needs: [build-cli-linux, install-script, bundle-macos-arm64, bundle-macos-x64, bundle-desktop-linux, bundle-windows, bundle-windows-cuda] + needs: [build-cli-linux, install-script, bundle-macos-arm64, bundle-macos-x64, bundle-windows, bundle-windows-cuda] permissions: contents: write id-token: write # Required for Sigstore OIDC signing diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c53f3b121..1e34a6d5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,10 +24,12 @@ concurrency: jobs: # ------------------------------------ - # 1) Build CLI targets not produced by desktop workflows + # 1) Bundle CLI and Desktop (Linux) # ------------------------------------ build-cli-linux: uses: ./.github/workflows/build-cli-linux.yml + with: + package_desktop: true # ------------------------------------ # 2) Upload Install CLI Script @@ -73,13 +75,7 @@ jobs: secrets: inherit # ------------------------------------------------------------ - # 5) Bundle Desktop App (Linux) - # ------------------------------------------------------------ - bundle-desktop-linux: - uses: ./.github/workflows/bundle-desktop-linux.yml - - # ------------------------------------------------------------ - # 6) Bundle CLI and Desktop (Windows) + # 5) Bundle CLI and Desktop (Windows) # ------------------------------------------------------------ bundle-windows: uses: ./.github/workflows/bundle-windows.yml @@ -107,13 +103,13 @@ jobs: secrets: inherit # ------------------------------------ - # 7) Create/Update GitHub Release + # 6) Create/Update GitHub Release # ------------------------------------ release: name: Release if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest - needs: [build-cli-linux, install-script, bundle-macos-arm64, bundle-macos-x64, bundle-desktop-linux, bundle-windows, bundle-windows-cuda] + needs: [build-cli-linux, install-script, bundle-macos-arm64, bundle-macos-x64, bundle-windows, bundle-windows-cuda] permissions: contents: write id-token: write # Required for Sigstore OIDC signing diff --git a/documentation/src/components/LinuxDesktopInstallButtons.js b/documentation/src/components/LinuxDesktopInstallButtons.js index 459ef0508..6c5db0606 100644 --- a/documentation/src/components/LinuxDesktopInstallButtons.js +++ b/documentation/src/components/LinuxDesktopInstallButtons.js @@ -6,6 +6,26 @@ const FALLBACK_URL = "https://github.com/aaif-goose/goose/releases/latest"; const isStandardLinuxAsset = (asset) => !asset.name.includes('-vulkan'); +const ARCH_ASSET_TOKENS = { + x64: { deb: 'amd64', rpm: 'x86_64', flatpak: 'x86_64' }, + arm64: { deb: 'arm64', rpm: 'arm64', flatpak: 'aarch64' }, +}; + +const detectLinuxArch = async () => { + if (typeof navigator === 'undefined') return 'x64'; + + try { + if (navigator.userAgentData?.getHighEntropyValues) { + const { architecture } = await navigator.userAgentData.getHighEntropyValues(['architecture']); + if (architecture) return /arm/i.test(architecture) ? 'arm64' : 'x64'; + } + } catch { + // Fall back to the user agent. + } + + return /aarch64|arm64/i.test(navigator.userAgent || '') ? 'arm64' : 'x64'; +}; + const LinuxDesktopInstallButtons = () => { const [downloadUrls, setDownloadUrls] = useState({ deb: FALLBACK_URL, @@ -16,9 +36,14 @@ const LinuxDesktopInstallButtons = () => { useEffect(() => { const fetchLatestRelease = async () => { try { + const arch = await detectLinuxArch(); + const tokens = ARCH_ASSET_TOKENS[arch]; + const cacheKey = `goose-release-cache-${arch}`; + const cacheTimeKey = `goose-release-cache-time-${arch}`; + // Check cache first (1 hour expiry) - const cached = localStorage.getItem('goose-release-cache'); - const cacheTime = localStorage.getItem('goose-release-cache-time'); + const cached = localStorage.getItem(cacheKey); + const cacheTime = localStorage.getItem(cacheTimeKey); const now = Date.now(); if (cached && cacheTime && (now - parseInt(cacheTime)) < 3600000) { @@ -36,13 +61,13 @@ const LinuxDesktopInstallButtons = () => { // Find DEB, RPM, and Flatpak files const debAsset = assets.find(asset => - isStandardLinuxAsset(asset) && asset.name.includes('.deb') && asset.name.includes('amd64') + isStandardLinuxAsset(asset) && asset.name.includes('.deb') && asset.name.includes(tokens.deb) ); const rpmAsset = assets.find(asset => - isStandardLinuxAsset(asset) && asset.name.includes('.rpm') && asset.name.includes('x86_64') + isStandardLinuxAsset(asset) && asset.name.includes('.rpm') && asset.name.includes(tokens.rpm) ); const flatpakAsset = assets.find(asset => - isStandardLinuxAsset(asset) && asset.name.endsWith('.flatpak') + isStandardLinuxAsset(asset) && asset.name.endsWith('.flatpak') && asset.name.includes(tokens.flatpak) ); const newUrls = { @@ -53,8 +78,8 @@ const LinuxDesktopInstallButtons = () => { // Update state and cache setDownloadUrls(newUrls); - localStorage.setItem('goose-release-cache', JSON.stringify(newUrls)); - localStorage.setItem('goose-release-cache-time', now.toString()); + localStorage.setItem(cacheKey, JSON.stringify(newUrls)); + localStorage.setItem(cacheTimeKey, now.toString()); } catch (error) { console.warn('Failed to fetch latest release, using fallback URLs:', error); // Fallback URLs are already set in initial state diff --git a/ui/desktop/README.md b/ui/desktop/README.md index 5028d91b2..0d31efd8c 100644 --- a/ui/desktop/README.md +++ b/ui/desktop/README.md @@ -71,20 +71,29 @@ cp ../../target/release/goose src/bin/ 3. Build the application: ```bash # For ZIP distribution (works on all Linux distributions) -pnpm run make --targets=@electron-forge/maker-zip +pnpm run make --targets=@electron-forge/maker-zip --arch=x64 # For DEB package (Debian/Ubuntu) -pnpm run make --targets=@electron-forge/maker-deb +pnpm run make --targets=@electron-forge/maker-deb --arch=x64 + +# For RPM package (Fedora/RHEL) +pnpm run make --targets=@electron-forge/maker-rpm --arch=x64 # For Flatpak (requires flatpak and flatpak-builder) -pnpm run make --targets=@electron-forge/maker-flatpak +pnpm run make --targets=@electron-forge/maker-flatpak --arch=x64 ``` -The built application will be available in: -- ZIP: `out/make/zip/linux/x64/goose-linux-x64-{version}.zip` -- DEB: `out/make/deb/x64/goose_{version}_amd64.deb` -- Flatpak: `out/make/flatpak/x86_64/*.flatpak` -- Executable: `out/goose-linux-x64/goose` +The `--arch` option controls the Electron architecture only; it does not rebuild the Rust `goose` binary. To create an ARM64 package, run these steps on an ARM64 Linux host so `cargo build` produces an ARM64 `goose` binary, then replace `--arch=x64` with `--arch=arm64`. Do not package an ARM64 Electron application with the x64 `goose` binary produced on an x64 host. + +Electron Forge writes packages to architecture-specific directories: + +| Package | x64 | ARM64 | +| --- | --- | --- | +| ZIP | `out/make/zip/linux/x64/*.zip` | `out/make/zip/linux/arm64/*.zip` | +| DEB | `out/make/deb/x64/*_amd64.deb` | `out/make/deb/arm64/*_arm64.deb` | +| RPM | `out/make/rpm/x64/*.x86_64.rpm` | `out/make/rpm/arm64/*.arm64.rpm` | +| Flatpak | `out/make/flatpak/x86_64/*.flatpak` | `out/make/flatpak/aarch64/*.flatpak` | +| Application | `out/Goose-linux-x64/` | `out/Goose-linux-arm64/` | ### Windows Use the existing Windows build process as documented.