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 upload_actions_artifacts: description: "Upload built artifacts to GitHub Actions run artifacts" required: false default: false type: boolean actions_artifacts_retention_days: description: "Retention (days) for GitHub Actions artifacts" required: false default: 7 type: number actions_artifacts_name_prefix: description: "Optional prefix for Actions artifact names" required: false default: "" type: string 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 - name: Upload Actions artifacts (Electron macOS) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}electron-macos path: packages/electron-app/release/*.zip retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: error 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 } - name: Upload Actions artifacts (Electron Windows) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}electron-windows path: packages/electron-app/release/*.zip retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: error 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 - name: Upload Actions artifacts (Electron Linux) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}electron-linux path: packages/electron-app/release/*.zip retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: error 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 || inputs.upload_actions_artifacts }} 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 Actions artifacts (Tauri macOS) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}tauri-macos path: packages/tauri-app/release-tauri/*.zip retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: warn - 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 || inputs.upload_actions_artifacts }} 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 Actions artifacts (Tauri macOS arm64) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}tauri-macos-arm64 path: packages/tauri-app/release-tauri/*.zip retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: warn - 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 || inputs.upload_actions_artifacts }} 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 Actions artifacts (Tauri Windows) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}tauri-windows path: packages/tauri-app/release-tauri/*.zip retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: warn - 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 || inputs.upload_actions_artifacts }} 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 Actions artifacts (Tauri Linux) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}tauri-linux path: packages/tauri-app/release-tauri/* retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: warn - 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 - name: Upload Actions artifacts (Electron Linux RPM) if: ${{ inputs.upload_actions_artifacts }} uses: actions/upload-artifact@v4 with: name: ${{ inputs.actions_artifacts_name_prefix }}electron-linux-rpm path: packages/electron-app/release/*.rpm retention-days: ${{ inputs.actions_artifacts_retention_days }} if-no-files-found: error