name: Release # Two ways in: # * push a tag `v0.1.0` → build installers and attach them to a draft # GitHub Release. # * run manually (workflow_dispatch, on any branch) → build the same # installers and upload them as **workflow artifacts** only, with no tag # and no release. This is how you test the pipeline without burning a tag. on: push: tags: ["v*"] workflow_dispatch: env: CARGO_TERM_COLOR: always jobs: release: permissions: contents: write # create the release + upload assets (tag runs only) strategy: fail-fast: false matrix: include: - platform: macos-latest rust_targets: aarch64-apple-darwin,x86_64-apple-darwin tauri_args: --target universal-apple-darwin cli_asset: tutabridge-macos-arm64 bundle_path: target/universal-apple-darwin/release/bundle - platform: ubuntu-latest rust_targets: "" tauri_args: "" cli_asset: tutabridge-linux-x86_64 bundle_path: target/release/bundle - platform: windows-latest rust_targets: "" tauri_args: "" cli_asset: tutabridge-windows-x86_64.exe bundle_path: target/release/bundle runs-on: ${{ matrix.platform }} steps: - name: Checkout (with vendored SDK submodule) uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.rust_targets }} - name: Cache cargo build uses: Swatinem/rust-cache@v2 - name: Setup Node uses: actions/setup-node@v4 with: node-version: 20 cache: npm cache-dependency-path: ui/package-lock.json # Linux: Tauri's webkit/gtk stack + our build deps (aws-lc-sys, the # keyring Secret Service backend's libdbus). - name: Install Linux deps if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install -y \ libwebkit2gtk-4.1-dev \ libgtk-3-dev \ librsvg2-dev \ libsoup-3.0-dev \ libjavascriptcoregtk-4.1-dev \ libayatana-appindicator3-dev \ cmake nasm libdbus-1-dev pkg-config # Windows: NASM for aws-lc-sys's assembly. - name: Install NASM (Windows) if: runner.os == 'Windows' uses: ilammy/setup-nasm@v1 - name: Install frontend deps working-directory: ui run: npm ci # Builds the GUI bundles (.dmg / .msi+.exe / .deb+.AppImage). On a tag it # also creates/updates a draft Release and uploads them; on a manual run # `tagName` is empty so it only builds (no release). - name: Build GUI bundles id: tauri uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tagName: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }} releaseName: ${{ startsWith(github.ref, 'refs/tags/') && format('TutaBridge {0}', github.ref_name) || '' }} releaseDraft: true prerelease: false args: ${{ matrix.tauri_args }} - name: Build CLI run: cargo build --release -p tutabridge # --- Tag run: attach the CLI binary to the draft release --- - name: Attach CLI to release if: startsWith(github.ref, 'refs/tags/') shell: bash env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | src=target/release/tutabridge [ "${{ runner.os }}" = "Windows" ] && src=target/release/tutabridge.exe cp "$src" "${{ matrix.cli_asset }}" gh release upload "${{ github.ref_name }}" "${{ matrix.cli_asset }}" --clobber # tauri-action names the GUI installers with the version (e.g. # TutaBridge_0.1.0_universal.dmg), which would break any fixed download # link on the next release. Upload version-less aliases alongside them so # `releases/latest/download/TutaBridge-macOS.dmg` (and friends) always # resolve to the current build. The CLI assets are already version-less. - name: Attach version-less GUI installer aliases if: startsWith(github.ref, 'refs/tags/') shell: bash env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | bp="${{ matrix.bundle_path }}" tag="${{ github.ref_name }}" alias() { # $1 = glob, $2 = stable name f=$(ls $1 2>/dev/null | head -n1) if [ -n "$f" ]; then cp "$f" "$2" gh release upload "$tag" "$2" --clobber else echo "::warning::no installer matched $1" fi } case "${{ runner.os }}" in macOS) alias "$bp/dmg/*.dmg" "TutaBridge-macOS.dmg" ;; Linux) alias "$bp/appimage/*.AppImage" "TutaBridge-Linux.AppImage" alias "$bp/deb/*.deb" "TutaBridge-Linux.deb" alias "$bp/rpm/*.rpm" "TutaBridge-Linux.rpm" ;; Windows) alias "$bp/nsis/*-setup.exe" "TutaBridge-Windows-setup.exe" alias "$bp/msi/*.msi" "TutaBridge-Windows.msi" ;; esac # --- Manual run: publish everything as downloadable workflow artifacts --- - name: Upload GUI bundles as artifacts if: ${{ !startsWith(github.ref, 'refs/tags/') }} uses: actions/upload-artifact@v4 with: name: gui-bundles-${{ matrix.platform }} path: ${{ matrix.bundle_path }}/** if-no-files-found: warn - name: Upload CLI as artifact if: ${{ !startsWith(github.ref, 'refs/tags/') }} uses: actions/upload-artifact@v4 with: name: ${{ matrix.cli_asset }} path: | target/release/tutabridge target/release/tutabridge.exe if-no-files-found: warn