name: Build and Upload Binaries

on:
  workflow_call:
    inputs:
      ref:
        description: "Git ref (branch, tag, or SHA) to build from"
        required: false
        default: ""
        type: string
      version:
        description: "Version to apply to workspace packages (release builds)"
        required: false
        default: ""
        type: string
      tag:
        description: "Git tag to upload assets to (release builds)"
        required: false
        default: ""
        type: string
      release_name:
        description: "Release name (unused here, for context)"
        required: false
        default: ""
        type: string
      upload:
        description: "Upload built artifacts to the GitHub release"
        required: false
        default: true
        type: boolean
      set_versions:
        description: "Run npm version to set workspace versions"
        required: false
        default: true
        type: boolean

# Permissions are intentionally omitted here so callers can choose
# least-privilege (e.g. dev CI uses read-only; releases grant write).

env:
  NODE_VERSION: 20

jobs:
  build-macos:
    runs-on: macos-15-intel
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        shell: bash
        env:
          NPM_CONFIG_FETCH_RETRIES: 5
          NPM_CONFIG_FETCH_RETRY_MINTIMEOUT: 20000
          NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT: 120000
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            if npm version "${VERSION}" --workspaces --include-workspace-root --no-git-tag-version --allow-same-version; then
              exit 0
            fi
            echo "npm version failed (attempt $attempt/3); retrying..." >&2
            sleep $((attempt * 10))
          done
          exit 1

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-darwin-x64 --no-save

      - name: Build macOS binaries (Electron)
        run: npm run build:mac --workspace @neuralnomads/codenomad-electron-app

      - name: Ad-hoc sign Electron macOS app bundles (seal resources)
        shell: bash
        run: |
          set -euo pipefail

          release_root="packages/electron-app/release"
          apps=()
          while IFS= read -r -d '' app; do
            apps+=("$app")
          done < <(find "$release_root" -type d -name 'CodeNomad.app' -print0)

          if [ "${#apps[@]}" -eq 0 ]; then
            echo "No CodeNomad.app found under $release_root" >&2
            exit 1
          fi

          # GitHub macOS runners typically have no signing identity. Without any signature,
          # the shipped .app can fail Gatekeeper with:
          #   code has no resources but signature indicates they must be present
          # Ad-hoc signing seals bundle resources and makes the signature internally consistent.
          if security find-identity -p codesigning -v | grep -q "0 valid identities found"; then
            echo "No valid macOS codesigning identity found; applying ad-hoc signature"
            for app in "${apps[@]}"; do
              echo "codesign (adhoc): $app"
              codesign --force --deep --sign - "$app"
              codesign --verify --deep --strict --verbose=2 "$app"
            done
          else
            echo "macOS codesigning identity present; skipping ad-hoc signing"
          fi

      - name: Repackage Electron macOS zips (ditto)
        shell: bash
        run: |
          set -euo pipefail

          # Prefer the workflow-provided version; fall back to package.json.
          VERSION_TO_USE="${VERSION:-}"
          if [ -z "$VERSION_TO_USE" ]; then
            VERSION_TO_USE=$(node -p "require('./packages/electron-app/package.json').version")
          fi

          release_root="packages/electron-app/release"
          # macOS GitHub runners ship /bin/bash 3.2 which doesn't support `shopt -s globstar`.
          # Use find to locate built app bundles instead of ** globs.
          apps=()
          while IFS= read -r -d '' app; do
            apps+=("$app")
          done < <(find "$release_root" -type d -name 'CodeNomad.app' -print0)
          if [ "${#apps[@]}" -eq 0 ]; then
            echo "No CodeNomad.app found under $release_root" >&2
            exit 1
          fi

          for app in "${apps[@]}"; do
            bundle_dir=$(basename "$(dirname "$app")")
            arch="x64"
            if [[ "$bundle_dir" == *"arm64"* ]]; then
              arch="arm64"
            fi

            out_zip="$release_root/CodeNomad-${VERSION_TO_USE}-mac-${arch}.zip"
            rm -f "$out_zip"
            echo "ditto -ck: $app -> $out_zip"
            ditto -ck --sequesterRsrc --keepParent "$app" "$out_zip"
          done

      - name: Validate Electron macOS codesign (unzipped)
        shell: bash
        run: |
          set -euo pipefail
          shopt -s nullglob

          tmp_dir=$(mktemp -d)
          trap 'rm -rf "$tmp_dir"' EXIT

          zips=(packages/electron-app/release/CodeNomad-*-mac-*.zip)
          if [ "${#zips[@]}" -eq 0 ]; then
            echo "No Electron macOS zip artifacts found to validate" >&2
            exit 1
          fi

          for zip in "${zips[@]}"; do
            echo "Validating codesign for: $zip"
            extract_dir="$tmp_dir/$(basename "$zip" .zip)"
            mkdir -p "$extract_dir"

            # Use ditto for extraction as well to preserve bundle metadata.
            ditto -x -k "$zip" "$extract_dir"

            app_path=""
            for candidate in "$extract_dir"/*.app "$extract_dir"/*/*.app; do
              if [ -d "$candidate" ]; then
                app_path="$candidate"
                break
              fi
            done

            if [ -z "$app_path" ]; then
              echo "No .app found after extracting $zip" >&2
              exit 1
            fi

            codesign --verify --deep --strict --verbose=2 "$app_path"
          done

      - name: Upload release assets
        if: ${{ inputs.upload && inputs.tag != '' }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/electron-app/release/*.zip; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done

  build-windows:
    runs-on: windows-2025
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${{ env.VERSION }} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
        shell: bash

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-win32-x64-msvc --no-save

      - name: Build Windows binaries (Electron)
        run: npm run build:win --workspace @neuralnomads/codenomad-electron-app

      - name: Upload release assets
        if: ${{ inputs.upload && inputs.tag != '' }}
        shell: pwsh
        run: |
          Get-ChildItem -Path "packages/electron-app/release" -Filter *.zip -File | ForEach-Object {
            Write-Host "Uploading $($_.FullName)"
            gh release upload $env:TAG $_.FullName --clobber
          }

  build-linux:
    runs-on: ubuntu-24.04
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-linux-x64-gnu --no-save

      - name: Build Linux binaries (Electron)
        run: npm run build:linux --workspace @neuralnomads/codenomad-electron-app

      - name: Upload release assets
        if: ${{ inputs.upload && inputs.tag != '' }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/electron-app/release/*.zip; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done

  build-tauri-macos:
    runs-on: macos-15-intel
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Setup Rust (Tauri)
        uses: dtolnay/rust-toolchain@stable

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-darwin-x64 --no-save

      - name: Prebuild (Tauri)
        run: npm run prebuild --workspace @codenomad/tauri-app

      - name: Ensure tauri native binary
        working-directory: packages/tauri-app
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            if [ "$attempt" -gt 1 ]; then
              echo "Retrying Tauri CLI install (attempt $attempt)..."
            fi
            npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-darwin-x64@2.9.4 --no-save --no-audit --no-fund --workspaces=false
            node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
          done
          echo "Tauri CLI failed to load after retries" >&2
          exit 1

      - name: Build macOS bundle (Tauri)
        working-directory: packages/tauri-app
        run: npm exec -- tauri build

      - name: Package Tauri artifacts (macOS)
        if: ${{ inputs.upload }}
        run: |
          set -euo pipefail
          BUNDLE_ROOT="packages/tauri-app/target/release/bundle"
          ARTIFACT_DIR="packages/tauri-app/release-tauri"
          rm -rf "$ARTIFACT_DIR"
          mkdir -p "$ARTIFACT_DIR"
          if [ -d "$BUNDLE_ROOT/macos/CodeNomad.app" ]; then
            ditto -ck --sequesterRsrc --keepParent "$BUNDLE_ROOT/macos/CodeNomad.app" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-macos-x64.zip"
          fi

      - name: Upload Tauri release assets (macOS)
        if: ${{ inputs.upload && inputs.tag != '' }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/tauri-app/release-tauri/*.zip; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done

  build-tauri-macos-arm64:
    runs-on: macos-26
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Setup Rust (Tauri)
        uses: dtolnay/rust-toolchain@stable

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-darwin-arm64 --no-save

      - name: Prebuild (Tauri)
        run: npm run prebuild --workspace @codenomad/tauri-app

      - name: Ensure tauri native binary
        working-directory: packages/tauri-app
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            if [ "$attempt" -gt 1 ]; then
              echo "Retrying Tauri CLI install (attempt $attempt)..."
            fi
            npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-darwin-arm64@2.9.4 --no-save --no-audit --no-fund --workspaces=false
            node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
          done
          echo "Tauri CLI failed to load after retries" >&2
          exit 1

      - name: Build macOS bundle (Tauri, arm64)
        working-directory: packages/tauri-app
        run: npm exec -- tauri build

      - name: Package Tauri artifacts (macOS arm64)
        if: ${{ inputs.upload }}
        run: |
          set -euo pipefail
          BUNDLE_ROOT="packages/tauri-app/target/release/bundle"
          ARTIFACT_DIR="packages/tauri-app/release-tauri"
          rm -rf "$ARTIFACT_DIR"
          mkdir -p "$ARTIFACT_DIR"
          if [ -d "$BUNDLE_ROOT/macos/CodeNomad.app" ]; then
            ditto -ck --sequesterRsrc --keepParent "$BUNDLE_ROOT/macos/CodeNomad.app" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-macos-arm64.zip"
          fi

      - name: Upload Tauri release assets (macOS arm64)
        if: ${{ inputs.upload && inputs.tag != '' }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/tauri-app/release-tauri/*.zip; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done

  build-tauri-windows:
    runs-on: windows-2025
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Setup Rust (Tauri)
        uses: dtolnay/rust-toolchain@stable

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${{ env.VERSION }} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
        shell: bash

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-win32-x64-msvc --no-save

      - name: Prebuild (Tauri)
        run: npm run prebuild --workspace @codenomad/tauri-app

      - name: Ensure tauri native binary
        shell: bash
        working-directory: packages/tauri-app
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            if [ "$attempt" -gt 1 ]; then
              echo "Retrying Tauri CLI install (attempt $attempt)..."
            fi
            npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-win32-x64-msvc@2.9.4 --no-save --no-audit --no-fund --workspaces=false
            node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
          done
          echo "Tauri CLI failed to load after retries" >&2
          exit 1

      - name: Build Windows bundle (Tauri)
        shell: bash
        working-directory: packages/tauri-app
        run: npm exec -- tauri build

      - name: Package Tauri artifacts (Windows)
        if: ${{ inputs.upload }}
        shell: pwsh
        run: |
          $bundleRoot = "packages/tauri-app/target/release/bundle"
          $artifactDir = "packages/tauri-app/release-tauri"
          if (Test-Path $artifactDir) { Remove-Item $artifactDir -Recurse -Force }
          New-Item -ItemType Directory -Path $artifactDir | Out-Null
          $exe = Get-ChildItem -Path $bundleRoot -Recurse -File -Filter *.exe | Select-Object -First 1
          if ($null -ne $exe) {
            $dest = Join-Path $artifactDir ("CodeNomad-Tauri-$env:VERSION-windows-x64.zip")
            Compress-Archive -Path $exe.Directory.FullName -DestinationPath $dest -Force
          }

      - name: Upload Tauri release assets (Windows)
        if: ${{ inputs.upload && inputs.tag != '' }}
        shell: pwsh
        run: |
          if (Test-Path "packages/tauri-app/release-tauri") {
            Get-ChildItem -Path "packages/tauri-app/release-tauri" -Filter *.zip -File | ForEach-Object {
              Write-Host "Uploading $($_.FullName)"
              gh release upload $env:TAG $_.FullName --clobber
            }
          }

  build-tauri-linux:
    runs-on: ubuntu-24.04
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Setup Rust (Tauri)
        uses: dtolnay/rust-toolchain@stable

      - name: Install Linux build dependencies (Tauri)
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            build-essential \
            pkg-config \
            libgtk-3-dev \
            libglib2.0-dev \
            libwebkit2gtk-4.1-dev \
            libsoup-3.0-dev \
            libayatana-appindicator3-dev \
            librsvg2-dev

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-linux-x64-gnu --no-save

      - name: Prebuild (Tauri)
        run: npm run prebuild --workspace @codenomad/tauri-app

      - name: Ensure tauri native binary
        working-directory: packages/tauri-app
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            if [ "$attempt" -gt 1 ]; then
              echo "Retrying Tauri CLI install (attempt $attempt)..."
            fi
            npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-linux-x64-gnu@2.9.4 --no-save --no-audit --no-fund --workspaces=false
            node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
          done
          echo "Tauri CLI failed to load after retries" >&2
          exit 1

      - name: Build Linux bundle (Tauri)
        working-directory: packages/tauri-app
        run: npm exec -- tauri build

      - name: Package Tauri artifacts (Linux)
        if: ${{ inputs.upload }}
        run: |
          set -euo pipefail
          SEARCH_ROOT="packages/tauri-app/target"
          ARTIFACT_DIR="packages/tauri-app/release-tauri"
          rm -rf "$ARTIFACT_DIR"
          mkdir -p "$ARTIFACT_DIR"
          shopt -s nullglob globstar

          find_one() {
            find "$SEARCH_ROOT" -type f -iname "$1" | head -n1
          }

          appimage=$(find_one "*.AppImage")
          deb=$(find_one "*.deb")
          rpm=$(find_one "*.rpm")

          if [ -z "$appimage" ] || [ -z "$deb" ] || [ -z "$rpm" ]; then
            echo "Missing bundle(s): appimage=${appimage:-none} deb=${deb:-none} rpm=${rpm:-none}" >&2
            exit 1
          fi

          cp "$appimage" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.AppImage"
          cp "$deb" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.deb"
          cp "$rpm" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.rpm"

      - name: Upload Tauri release assets (Linux)
        if: ${{ inputs.upload && inputs.tag != '' }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/tauri-app/release-tauri/*; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done

  build-tauri-linux-arm64:
    if: ${{ false }}
    runs-on: ubuntu-24.04
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup QEMU
        uses: docker/setup-qemu-action@v3
        with:
          platforms: linux/arm64

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Setup Rust (Tauri)
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: aarch64-unknown-linux-gnu

      - name: Install Linux build dependencies (Tauri)
        run: |
          sudo dpkg --add-architecture arm64
          sudo tee /etc/apt/sources.list.d/arm64.list >/dev/null <<'EOF'
          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse
          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse
          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse
          deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports noble-backports main restricted universe multiverse
          EOF
          sudo apt-get update
          sudo apt-get install -y \
            build-essential \
            pkg-config \
            gcc-aarch64-linux-gnu \
            g++-aarch64-linux-gnu \
            libgtk-3-dev:arm64 \
            libglib2.0-dev:arm64 \
            libwebkit2gtk-4.1-dev:arm64 \
            libsoup-3.0-dev:arm64 \
            libayatana-appindicator3-dev:arm64 \
            librsvg2-dev:arm64

      - name: Set workspace versions
        run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version

      - name: Install dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-linux-arm64-gnu --no-save

      - name: Build Linux bundle (Tauri arm64)
        env:
          TAURI_BUILD_TARGET: aarch64-unknown-linux-gnu
          PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
          CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
          CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++
          AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-ar
        run: npm run build --workspace @codenomad/tauri-app

      - name: Package Tauri artifacts (Linux arm64)
        run: |
          set -euo pipefail
          SEARCH_ROOT="packages/tauri-app/target"
          ARTIFACT_DIR="packages/tauri-app/release-tauri"
          rm -rf "$ARTIFACT_DIR"
          mkdir -p "$ARTIFACT_DIR"
          shopt -s nullglob globstar
          first_artifact=$(find "$SEARCH_ROOT" -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" -o -name "*.tar.gz" \) | head -n1)
          fallback_bin="$SEARCH_ROOT/release/codenomad-tauri"
          if [ -n "$first_artifact" ]; then
            zip -j "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.zip" "$first_artifact"
          elif [ -f "$fallback_bin" ]; then
            zip -j "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.zip" "$fallback_bin"
          else
            echo "No bundled artifact found under $SEARCH_ROOT and no binary at $fallback_bin" >&2
            exit 1
          fi


      - name: Upload Tauri release assets (Linux arm64)
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/tauri-app/release-tauri/*.zip; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done


  build-linux-rpm:
    runs-on: ubuntu-24.04
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      VERSION: ${{ inputs.version }}
      TAG: ${{ inputs.tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ inputs.ref || github.ref }}

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm

      - name: Install rpm packaging dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y rpm ruby ruby-dev build-essential
          sudo gem install --no-document fpm

      - name: Set workspace versions
        if: ${{ inputs.set_versions && inputs.version != '' }}
        run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version

      - name: Install project dependencies
        run: npm ci --workspaces --include=optional

      - name: Ensure rollup native binary
        run: npm install @rollup/rollup-linux-x64-gnu --no-save

      - name: Build Linux RPM binaries
        run: npm run build:linux-rpm --workspace @neuralnomads/codenomad-electron-app

      - name: Upload RPM release assets
        if: ${{ inputs.upload && inputs.tag != '' }}
        run: |
          set -euo pipefail
          shopt -s nullglob
          for file in packages/electron-app/release/*.rpm; do
            [ -f "$file" ] || continue
            echo "Uploading $file"
            gh release upload "$TAG" "$file" --clobber
          done
