Skip to content

chore(release): v1.9.0 #133

chore(release): v1.9.0

chore(release): v1.9.0 #133

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: write
jobs:
release:
strategy:
fail-fast: false
matrix:
include:
- platform: windows-latest
args: ''
label: Windows x64
- platform: macos-latest
args: '--target aarch64-apple-darwin'
label: macOS Apple Silicon
- platform: ubuntu-22.04
args: ''
label: Linux x64
- platform: ubuntu-22.04-arm
args: ''
label: Linux arm64
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install system dependencies (Linux)
if: startsWith(matrix.platform, 'ubuntu-')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: src-ui/package-lock.json
- name: Install & build frontend
run: |
cd src-ui
npm ci
npm run build
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ contains(matrix.args, 'aarch64-apple-darwin') && 'aarch64-apple-darwin' || '' }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
key: ${{ matrix.label }}
# ── Windows / Linux: tauri-action handles build + DMG/installer + upload ──
- name: Build & publish (Windows / Linux)
if: matrix.platform != 'macos-latest'
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tagName: v__VERSION__
releaseName: 'Coffee CLI v__VERSION__'
releaseBody: |
## Install
**Windows**
```powershell
irm https://raw.githubusercontent.com/edison7009/Coffee-CLI/main/install/install.ps1 | iex
```
**macOS / Linux**
```bash
curl -fsSL https://raw.githubusercontent.com/edison7009/Coffee-CLI/main/install/install.sh | sh
```
Or download the installer for your platform from the assets below.
| Platform | File |
|---|---|
| Windows x64 | `Coffee.CLI_*_x64-setup.exe` |
| macOS Apple Silicon | `Coffee.CLI_*_aarch64.dmg` |
| macOS Intel | `Coffee.CLI_*_x64.dmg` |
| Linux x64 (Debian/Ubuntu) | `coffee-cli_*_amd64.deb` |
| Linux x64 (AppImage) | `Coffee.CLI_*_amd64.AppImage` |
| Linux arm64 (Debian/Ubuntu) | `coffee-cli_*_arm64.deb` |
| Linux arm64 (AppImage) | `Coffee.CLI_*_aarch64.AppImage` |
releaseDraft: false
prerelease: false
args: ${{ matrix.args }}
# ── macOS: split into build → re-sign → DMG → upload ──
# Why not tauri-action: it does build + DMG in one shot, leaving
# no hook to re-sign the .app between the two. tauri-bundler's
# default codesign for adhoc identities adds --options runtime
# (hardened runtime), which without Apple notarization causes
# Gatekeeper to silently reject the GUI launch — users see "click
# icon, nothing happens". Splitting lets us seal resources via
# codesign --deep WITHOUT runtime flag, which Gatekeeper accepts.
- name: Install Tauri CLI (macOS)
if: matrix.platform == 'macos-latest'
run: cargo install tauri-cli --version "^2.0" --locked
- name: Build .app only (macOS)
if: matrix.platform == 'macos-latest'
run: cargo tauri build --bundles app ${{ matrix.args }}
- name: Re-sign without hardened runtime (macOS)
if: matrix.platform == 'macos-latest'
run: |
APP=$(find target/aarch64-apple-darwin/release/bundle/macos -maxdepth 2 -name "*.app" | head -1)
if [ -z "$APP" ]; then
echo "::error::No .app found"
find target -name "*.app" 2>/dev/null
exit 1
fi
echo "Re-signing: $APP"
codesign --force --deep --sign - "$APP"
codesign -dv --verbose=4 "$APP" 2>&1
# Sanity assertion: no 'runtime' flag, sealed resources present.
if codesign -dv --verbose=4 "$APP" 2>&1 | grep -qE "flags=.*runtime"; then
echo "::error::runtime flag still present after re-sign"
exit 1
fi
if codesign -dv --verbose=4 "$APP" 2>&1 | grep -q "Sealed Resources=none"; then
echo "::error::Sealed Resources=none after re-sign"
exit 1
fi
- name: Build DMG from re-signed .app (macOS)
if: matrix.platform == 'macos-latest'
run: cargo tauri bundle --bundles dmg ${{ matrix.args }}
- name: Upload DMG to release (macOS)
if: matrix.platform == 'macos-latest'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${GITHUB_REF#refs/tags/}"
# If triggered by workflow_dispatch (no tag), use latest tag.
if [ "$TAG" = "$GITHUB_REF" ]; then
TAG=$(git describe --tags --abbrev=0)
fi
DMG=$(find target/aarch64-apple-darwin/release/bundle/dmg -maxdepth 1 -name "*.dmg" | head -1)
if [ -z "$DMG" ]; then
echo "::error::No .dmg produced"
find target -name "*.dmg" 2>/dev/null
exit 1
fi
echo "Uploading $DMG to release $TAG"
# Wait for the release to exist (Windows/Linux jobs in matrix
# may still be creating it). --clobber replaces if asset exists.
for i in 1 2 3 4 5 6; do
if gh release view "$TAG" --repo "${{ github.repository }}" >/dev/null 2>&1; then
break
fi
echo "Release $TAG not yet available, waiting 10s... (attempt $i/6)"
sleep 10
done
if ! gh release view "$TAG" --repo "${{ github.repository }}" >/dev/null 2>&1; then
# Release still doesn't exist — create it ourselves so we don't
# block on a parallel matrix job that may have failed.
gh release create "$TAG" --repo "${{ github.repository }}" \
--title "Coffee CLI $TAG" \
--notes "macOS-only release placeholder — see other assets if Windows/Linux jobs succeed."
fi
gh release upload "$TAG" "$DMG" --repo "${{ github.repository }}" --clobber