name: Build-View on: workflow_dispatch: permissions: contents: write jobs: build: runs-on: ${{ matrix.os }} timeout-minutes: 120 strategy: matrix: include: - os: macos-latest arch: arm64 artifact_name: macos-arm64 - os: windows-latest arch: x64 artifact_name: windows-latest - os: ubuntu-latest arch: x64 artifact_name: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 with: clean: true # Clean node_modules on self-hosted runner to ensure fresh install - name: Clean node_modules (self-hosted) if: contains(matrix.os, 'self-hosted') run: | rm -rf node_modules rm -rf release - name: Setup Node.js if: "!contains(matrix.os, 'self-hosted')" uses: actions/setup-node@v6 with: node-version: 20 - name: Setup Python if: "!contains(matrix.os, 'self-hosted')" uses: actions/setup-python@v6 with: python-version: '3.11' - name: Install Python Dependencies run: | python3 -m pip install --upgrade pip pip3 install uv - name: Install bun run: npm install -g bun - name: Install Dependencies run: npm install # Verify Electron installation on macOS - name: Verify Electron Installation (macOS) if: runner.os == 'macOS' run: | echo "Checking Electron installation..." ls -la node_modules/electron/dist/ || echo "Electron dist not found" if [ -d "node_modules/electron/dist/Electron.app" ]; then echo "✅ Electron.app found" ls -la "node_modules/electron/dist/Electron.app/Contents/Frameworks/" | head -5 else echo "❌ Electron.app NOT found - this will cause build failure" exit 1 fi # Install libfuse2 for Linux AppImage builds - name: Install libfuse2 (Linux) if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y libfuse2 # Step for macOS builds with signing - name: Build Release Files (macOS with signing) if: runner.os == 'macOS' timeout-minutes: 90 run: | # Increase file descriptor limit to prevent EMFILE errors during signing # This is needed because electron-builder signs all files recursively, # and Python venvs contain thousands of files ulimit -n 65536 || ulimit -n 10240 echo "File descriptor limit set to: $(ulimit -n)" npm run build -- --arch ${{ matrix.arch }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CSC_LINK: ${{ secrets.CERT_P12 }} CSC_KEY_PASSWORD: ${{ secrets.CERT_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} VITE_BASE_URL: ${{ secrets.VITE_BASE_URL }} VITE_STACK_PROJECT_ID: ${{ secrets.VITE_STACK_PROJECT_ID }} VITE_STACK_PUBLISHABLE_CLIENT_KEY: ${{ secrets.VITE_STACK_PUBLISHABLE_CLIENT_KEY }} VITE_STACK_SECRET_SERVER_KEY: ${{ secrets.VITE_STACK_SECRET_SERVER_KEY }} USE_NPM_INSTALL_BUN: 'true' # Step for Windows builds without signing - name: Build Release Files (Windows without signing) if: runner.os == 'Windows' timeout-minutes: 90 run: npm run build -- --arch ${{ matrix.arch }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VITE_BASE_URL: ${{ secrets.VITE_BASE_URL }} VITE_STACK_PROJECT_ID: ${{ secrets.VITE_STACK_PROJECT_ID }} VITE_STACK_PUBLISHABLE_CLIENT_KEY: ${{ secrets.VITE_STACK_PUBLISHABLE_CLIENT_KEY }} VITE_STACK_SECRET_SERVER_KEY: ${{ secrets.VITE_STACK_SECRET_SERVER_KEY }} USE_NPM_INSTALL_BUN: 'true' # Step for Linux builds - name: Build Release Files (Linux) if: runner.os == 'Linux' timeout-minutes: 90 run: npm run build:linux env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VITE_BASE_URL: ${{ secrets.VITE_BASE_URL }} VITE_STACK_PROJECT_ID: ${{ secrets.VITE_STACK_PROJECT_ID }} VITE_STACK_PUBLISHABLE_CLIENT_KEY: ${{ secrets.VITE_STACK_PUBLISHABLE_CLIENT_KEY }} VITE_STACK_SECRET_SERVER_KEY: ${{ secrets.VITE_STACK_SECRET_SERVER_KEY }} USE_NPM_INSTALL_BUN: 'true' # Verify built app contains Electron Framework - name: Verify Built App (macOS) if: runner.os == 'macOS' run: | echo "Checking built app..." APP_PATH=$(find release -name "*.app" -type d | head -1) if [ -n "$APP_PATH" ]; then echo "Found app at: $APP_PATH" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" if [ -d "$FRAMEWORKS_PATH/Electron Framework.framework" ]; then echo "✅ Electron Framework found" ls -la "$FRAMEWORKS_PATH/" | head -10 else echo "❌ Electron Framework NOT found in built app!" echo "Contents of Frameworks directory:" ls -la "$FRAMEWORKS_PATH/" 2>/dev/null || echo "Frameworks directory does not exist" exit 1 fi else echo "No .app found in release directory" ls -la release/ fi - name: Upload Artifact (macOS - dmg only) if: runner.os == 'macOS' uses: actions/upload-artifact@v6 with: name: release-${{ matrix.artifact_name }}-${{ matrix.arch }} path: | release/*.dmg retention-days: 5 - name: Upload Artifact (Windows - exe only) if: runner.os == 'Windows' uses: actions/upload-artifact@v6 with: name: release-${{ matrix.artifact_name }}-${{ matrix.arch }} path: | release/*.exe retention-days: 5 - name: Upload Artifact (Linux - AppImage only) if: runner.os == 'Linux' uses: actions/upload-artifact@v6 with: name: release-${{ matrix.artifact_name }}-${{ matrix.arch }} path: | release/*.AppImage retention-days: 5 merge-release: needs: build runs-on: ubuntu-latest steps: - name: Create directories run: | mkdir -p release/mac-arm64 release/win-x64 release/linux-x64 - name: Download mac-arm64 artifact uses: actions/download-artifact@v7 with: name: release-macos-arm64-arm64 path: temp-mac-arm64 - name: Download win-x64 artifact uses: actions/download-artifact@v7 with: name: release-windows-latest-x64 path: temp-win-x64 - name: Download linux-x64 artifact uses: actions/download-artifact@v7 with: name: release-ubuntu-latest-x64 path: temp-linux-x64 # Move only dmg files for macOS, exe files for Windows, and AppImage for Linux - name: Move files to clean folders shell: bash run: | # mac-arm64 - only move dmg files if [ -d "temp-mac-arm64/release" ]; then find temp-mac-arm64/release -name "*.dmg" -exec mv {} release/mac-arm64/ \; || true else find temp-mac-arm64 -name "*.dmg" -exec mv {} release/mac-arm64/ \; || true fi # win-x64 - only move exe files if [ -d "temp-win-x64/release" ]; then find temp-win-x64/release -name "*.exe" -exec mv {} release/win-x64/ \; || true else find temp-win-x64 -name "*.exe" -exec mv {} release/win-x64/ \; || true fi # linux-x64 - only move AppImage files if [ -d "temp-linux-x64/release" ]; then find temp-linux-x64/release -name "*.AppImage" -exec mv {} release/linux-x64/ \; || true else find temp-linux-x64 -name "*.AppImage" -exec mv {} release/linux-x64/ \; || true fi