name: Release on: push: tags: - "v*" permissions: contents: write packages: write env: CARGO_TERM_COLOR: always jobs: # ── Tauri Desktop App (Windows + macOS + Linux) ─────────────────────────── # Produces: .msi, .exe (Windows) | .dmg, .app (macOS) | .AppImage, .deb (Linux) # Also generates and uploads latest.json (the auto-updater manifest) desktop: name: Desktop / ${{ matrix.platform.name }} strategy: fail-fast: false matrix: platform: - name: Linux x86_64 os: ubuntu-22.04 args: "--target x86_64-unknown-linux-gnu" rust_target: x86_64-unknown-linux-gnu - name: macOS x86_64 os: macos-latest args: "--target x86_64-apple-darwin" rust_target: x86_64-apple-darwin - name: macOS ARM64 os: macos-latest args: "--target aarch64-apple-darwin" rust_target: aarch64-apple-darwin - name: Windows x86_64 os: windows-latest args: "--target x86_64-pc-windows-msvc" rust_target: x86_64-pc-windows-msvc - name: Windows ARM64 os: windows-latest args: "--target aarch64-pc-windows-msvc" rust_target: aarch64-pc-windows-msvc runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v4 - name: Install system deps (Linux) if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y \ libwebkit2gtk-4.1-dev \ libgtk-3-dev \ libayatana-appindicator3-dev \ librsvg2-dev \ patchelf - uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.platform.rust_target }} - uses: Swatinem/rust-cache@v2 with: key: desktop-${{ matrix.platform.rust_target }} - name: Import macOS signing certificate if: runner.os == 'macOS' env: MAC_CERT_BASE64: ${{ secrets.MAC_CERT_BASE64 }} MAC_CERT_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }} run: | echo "$MAC_CERT_BASE64" | base64 --decode > $RUNNER_TEMP/certificate.p12 KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db KEYCHAIN_PASSWORD=$(openssl rand -base64 32) security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security import $RUNNER_TEMP/certificate.p12 -P "$MAC_CERT_PASSWORD" \ -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" security list-keychain -d user -s "$KEYCHAIN_PATH" security set-key-partition-list -S apple-tool:,apple:,codesign: \ -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep "Developer ID Application" | head -1 | awk -F'"' '{print $2}') echo "Using signing identity: $IDENTITY" echo "APPLE_SIGNING_IDENTITY=$IDENTITY" >> $GITHUB_ENV rm -f $RUNNER_TEMP/certificate.p12 - name: Build and bundle Tauri desktop app uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ env.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.MAC_NOTARIZE_APPLE_ID }} APPLE_PASSWORD: ${{ secrets.MAC_NOTARIZE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.MAC_NOTARIZE_TEAM_ID }} with: tagName: ${{ github.ref_name }} releaseName: "OpenFang ${{ github.ref_name }}" releaseBody: | ## What's New See the [CHANGELOG](https://github.com/RightNow-AI/openfang/blob/main/CHANGELOG.md) for full details. ## Installation **Desktop App** — Download the installer for your platform below. **CLI (Linux/macOS)**: ```bash curl -sSf https://openfang.sh | sh ``` **Docker**: ```bash docker pull ghcr.io/rightnow-ai/openfang:latest ``` **Coming from OpenClaw?** ```bash openfang migrate --from openclaw ``` releaseDraft: false prerelease: false includeUpdaterJson: true projectPath: crates/openfang-desktop args: ${{ matrix.platform.args }} # ── CLI Binary (5 platforms) ────────────────────────────────────────────── cli: name: CLI / ${{ matrix.target }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - target: x86_64-unknown-linux-gnu os: ubuntu-22.04 archive: tar.gz - target: aarch64-unknown-linux-gnu os: ubuntu-22.04 archive: tar.gz - target: x86_64-apple-darwin os: macos-latest archive: tar.gz - target: aarch64-apple-darwin os: macos-latest archive: tar.gz - target: x86_64-pc-windows-msvc os: windows-latest archive: zip - target: aarch64-pc-windows-msvc os: windows-latest archive: zip steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - name: Install build deps (Linux) if: runner.os == 'Linux' run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev - name: Install cross (Linux aarch64) if: matrix.target == 'aarch64-unknown-linux-gnu' run: cargo install cross --locked - uses: Swatinem/rust-cache@v2 with: key: cli-${{ matrix.target }} - name: Build CLI (cross) if: matrix.target == 'aarch64-unknown-linux-gnu' run: cross build --release --target ${{ matrix.target }} --bin openfang - name: Build CLI if: matrix.target != 'aarch64-unknown-linux-gnu' run: cargo build --release --target ${{ matrix.target }} --bin openfang - name: Package (Unix) if: matrix.archive == 'tar.gz' run: | cd target/${{ matrix.target }}/release tar czf ../../../openfang-${{ matrix.target }}.tar.gz openfang cd ../../.. sha256sum openfang-${{ matrix.target }}.tar.gz > openfang-${{ matrix.target }}.tar.gz.sha256 - name: Package (Windows) if: matrix.archive == 'zip' shell: pwsh run: | Compress-Archive -Path "target/${{ matrix.target }}/release/openfang.exe" -DestinationPath "openfang-${{ matrix.target }}.zip" $hash = (Get-FileHash "openfang-${{ matrix.target }}.zip" -Algorithm SHA256).Hash.ToLower() "$hash openfang-${{ matrix.target }}.zip" | Out-File -Encoding ASCII "openfang-${{ matrix.target }}.zip.sha256" - name: Upload to GitHub Release uses: softprops/action-gh-release@v2 with: files: openfang-${{ matrix.target }}.* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # ── Docker (linux/amd64 + linux/arm64) ──────────────────────────────────── docker: name: Docker Image runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up QEMU (for arm64 emulation) uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Extract version id: version run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" - name: Build and push (multi-arch) uses: docker/build-push-action@v6 with: context: . push: true platforms: linux/amd64,linux/arm64 tags: | ghcr.io/rightnow-ai/openfang:latest ghcr.io/rightnow-ai/openfang:${{ steps.version.outputs.version }} cache-from: type=gha cache-to: type=gha,mode=max