name: Build and Release on: push: tags: - 'v*' workflow_dispatch: jobs: build-windows: runs-on: windows-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' - run: npm ci - name: Build Windows Packages run: npx electron-builder --win --publish never - uses: actions/upload-artifact@v4 with: name: windows-builds path: | dist/*.exe dist/*.exe.blockmap dist/latest.yml # macOS ARM64 build (Apple Silicon) build-macos-arm64: runs-on: macos-14 # M1 runner for native ARM64 builds timeout-minutes: 120 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' - run: npm ci - name: Build macOS ARM64 Package env: # Code signing CSC_LINK: ${{ secrets.CSC_LINK }} CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} # Notarization APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} run: npx electron-builder --mac --arm64 --publish never - name: Rename ARM64 artifacts for clarity run: | cd dist for f in *.dmg; do [ -f "$f" ] && mv "$f" "${f%.dmg}-arm64.dmg" 2>/dev/null || true done for f in *.zip; do [ -f "$f" ] && mv "$f" "${f%.zip}-arm64.zip" 2>/dev/null || true done ls -la - uses: actions/upload-artifact@v4 with: name: macos-arm64-builds path: | dist/*.dmg dist/*.zip # macOS x64 build (Intel) build-macos-x64: runs-on: macos-13 # Intel runner for native x64 builds timeout-minutes: 120 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' - run: npm ci - name: Build macOS x64 Package env: # Code signing CSC_LINK: ${{ secrets.CSC_LINK }} CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} # Notarization APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} run: npx electron-builder --mac --x64 --publish never - name: Rename x64 artifacts for clarity run: | cd dist for f in *.dmg; do [ -f "$f" ] && mv "$f" "${f%.dmg}-x64.dmg" 2>/dev/null || true done for f in *.zip; do [ -f "$f" ] && mv "$f" "${f%.zip}-x64.zip" 2>/dev/null || true done ls -la - uses: actions/upload-artifact@v4 with: name: macos-x64-builds path: | dist/*.dmg dist/*.zip build-linux: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install build dependencies run: | sudo apt-get update sudo apt-get install -y libarchive-tools - uses: actions/setup-node@v4 with: node-version: '22' cache: 'npm' - run: npm ci - name: Build Linux Packages run: | npx electron-builder --linux AppImage deb rpm --publish never - uses: actions/upload-artifact@v4 with: name: linux-builds path: | dist/*.AppImage dist/*.AppImage.blockmap dist/*.deb dist/*.rpm dist/latest-linux.yml build-arch: runs-on: ubuntu-latest container: image: archlinux:latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install base packages run: | pacman -Syu --noconfirm pacman -S --noconfirm \ base-devel \ git \ nodejs \ npm \ rpm-tools \ libxcrypt-compat - name: Create build user run: | useradd -m builder echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers - name: Fix Permissions run: chown -R builder:builder . - name: Build Arch Package run: | sudo -u builder bash << 'EOF' set -e makepkg --printsrcinfo > .SRCINFO makepkg -s --noconfirm EOF - name: Fix permissions for upload if: always() run: | sudo chown -R $(id -u):$(id -g) . - name: Upload Arch Package uses: actions/upload-artifact@v4 with: name: arch-package path: | *.pkg.tar.zst .SRCINFO include-hidden-files: true # Create release with Windows, Linux, Arch (fast builds) release: needs: [build-windows, build-linux, build-arch] runs-on: ubuntu-latest if: | startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' permissions: contents: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Download Windows artifacts uses: actions/download-artifact@v4 with: name: windows-builds path: artifacts/windows-builds - name: Download Linux artifacts uses: actions/download-artifact@v4 with: name: linux-builds path: artifacts/linux-builds - name: Download Arch artifacts uses: actions/download-artifact@v4 with: name: arch-package path: artifacts/arch-package - name: Display structure of downloaded files run: ls -R artifacts - name: Get version from package.json id: pkg_version run: echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT - name: Create Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} files: | artifacts/arch-package/*.pkg.tar.zst artifacts/arch-package/*.src.tar.zst artifacts/arch-package/.SRCINFO artifacts/linux-builds/* artifacts/windows-builds/* generate_release_notes: true draft: true prerelease: false # Upload macOS ARM64 builds separately release-macos-arm64: needs: [build-macos-arm64, release] runs-on: ubuntu-latest if: | startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' permissions: contents: write steps: - name: Download macOS ARM64 artifacts uses: actions/download-artifact@v4 with: name: macos-arm64-builds path: artifacts/macos-arm64-builds - name: Display macOS ARM64 files run: ls -R artifacts - name: Upload macOS ARM64 to Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} files: | artifacts/macos-arm64-builds/* draft: true prerelease: false # Upload macOS x64 builds separately release-macos-x64: needs: [build-macos-x64, release] runs-on: ubuntu-latest if: | startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch' permissions: contents: write steps: - name: Download macOS x64 artifacts uses: actions/download-artifact@v4 with: name: macos-x64-builds path: artifacts/macos-x64-builds - name: Display macOS x64 files run: ls -R artifacts - name: Upload macOS x64 to Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ github.ref_name }} files: | artifacts/macos-x64-builds/* draft: true prerelease: false