Skip to content

Release Jean

Release Jean #54

Workflow file for this run

name: 'Release Jean'
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., v1.0.0)'
required: true
type: string
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
publish-tauri:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: 'macos-latest'
args: '--target universal-apple-darwin --bundles app,dmg'
- platform: 'ubuntu-22.04'
args: '--bundles deb,rpm'
- platform: 'ubuntu-22.04-arm'
args: '--bundles deb,rpm'
- platform: 'windows-latest'
args: '--bundles msi,nsis'
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: Patch version from release tag
shell: bash
run: |
TAG="${{ github.event.release.tag_name || inputs.version }}"
VERSION="${TAG#v}"
echo "Patching version to $VERSION"
node -e "const p=require('./package.json'); p.version='$VERSION'; require('fs').writeFileSync('package.json', JSON.stringify(p,null,2)+'\n')"
node -e "const c=require('./src-tauri/tauri.conf.json'); c.version='$VERSION'; require('fs').writeFileSync('src-tauri/tauri.conf.json', JSON.stringify(c,null,2)+'\n')"
sed -i.bak "s/^version = \"[^\"]*\"/version = \"$VERSION\"/" src-tauri/Cargo.toml && rm -f src-tauri/Cargo.toml.bak
- name: Install Linux dependencies
if: startsWith(matrix.platform, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils libfuse2
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install macOS universal targets
if: matrix.platform == 'macos-latest'
run: rustup target add x86_64-apple-darwin aarch64-apple-darwin
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: './src-tauri -> target'
- name: Install frontend dependencies
run: bun install --frozen-lockfile
- name: Build and release
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
with:
tauriScript: bun run tauri
tagName: ${{ github.event.release.tag_name || inputs.version }}
releaseId: ${{ github.event.release.id }}
includeUpdaterJson: true
args: ${{ matrix.args }} -vv
# Build AppImage separately with the custom AppRun script that fixes
# WebKitGTK/GLib compatibility on Ubuntu 24.04+ and rolling-release distros.
# The Tauri action builds deb/rpm above; this step handles AppImage with
# the LD_LIBRARY_PATH fix that prevents white screen crashes.
# See: https://github.com/coollabsio/jean/issues/54
- name: Build AppImage with WebKitGTK fix
if: startsWith(matrix.platform, 'ubuntu')
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: bash scripts/build-appimage.sh
- name: Upload AppImage to release
if: startsWith(matrix.platform, 'ubuntu')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.version }}
run: |
VERSION="${RELEASE_TAG#v}"
BUNDLE_DIR="src-tauri/target/release/bundle/appimage"
APPIMAGE=$(find "$BUNDLE_DIR" -name "Jean_${VERSION}_*.AppImage" ! -name "*.tar.gz" -print -quit 2>/dev/null)
if [ -n "$APPIMAGE" ] && [ -f "$APPIMAGE" ]; then
gh release upload "$RELEASE_TAG" "$APPIMAGE" --clobber
# Upload updater artifacts (.tar.gz + .sig)
[ -f "${APPIMAGE}.tar.gz" ] && gh release upload "$RELEASE_TAG" "${APPIMAGE}.tar.gz" --clobber
[ -f "${APPIMAGE}.tar.gz.sig" ] && gh release upload "$RELEASE_TAG" "${APPIMAGE}.tar.gz.sig" --clobber
fi
- name: Patch latest.json for AppImage updater
if: startsWith(matrix.platform, 'ubuntu')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.version }}
run: |
VERSION="${RELEASE_TAG#v}"
BUNDLE_DIR="src-tauri/target/release/bundle/appimage"
ARCH_LABEL="amd64"
PLATFORM_KEY="linux-x86_64"
if [ "$(uname -m)" = "aarch64" ]; then
ARCH_LABEL="arm64"
PLATFORM_KEY="linux-aarch64"
fi
APPIMAGE_TAR="Jean_${VERSION}_${ARCH_LABEL}.AppImage.tar.gz"
SIG_FILE="${BUNDLE_DIR}/${APPIMAGE_TAR}.sig"
if [ ! -f "$SIG_FILE" ]; then
echo "No signature file found at $SIG_FILE, skipping latest.json patch"
exit 0
fi
SIGNATURE=$(cat "$SIG_FILE")
URL="https://github.com/coollabsio/jean/releases/download/${RELEASE_TAG}/${APPIMAGE_TAR}"
# Download current latest.json, patch Linux platform entry, re-upload
gh release download "$RELEASE_TAG" -p "latest.json" -D /tmp --clobber
SIG_CONTENT="$SIGNATURE" node -e "
const fs = require('fs');
const data = JSON.parse(fs.readFileSync('/tmp/latest.json', 'utf8'));
data.platforms = data.platforms || {};
data.platforms['${PLATFORM_KEY}'] = {
signature: process.env.SIG_CONTENT,
url: '${URL}'
};
fs.writeFileSync('/tmp/latest.json', JSON.stringify(data, null, 2));
"
gh release upload "$RELEASE_TAG" /tmp/latest.json --clobber
echo "Patched latest.json: ${PLATFORM_KEY} -> ${URL}"
update-homebrew-tap:
name: Update Homebrew Tap
needs: publish-tauri
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'
steps:
- name: Extract version
id: version
run: echo "tag=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
- name: Wait for DMG availability
run: |
TAG="${{ steps.version.outputs.tag }}"
VERSION="${TAG#v}"
DMG_URL="https://github.com/coollabsio/jean/releases/download/$TAG/Jean_${VERSION}_universal.dmg"
echo "Waiting for DMG at: $DMG_URL"
for i in $(seq 1 30); do
if curl --output /dev/null --silent --head --fail "$DMG_URL"; then
echo "DMG is available"
exit 0
fi
echo "Attempt $i/30: waiting 10s..."
sleep 10
done
echo "Error: DMG not available after 5 minutes"
exit 1
- name: Trigger Homebrew tap update
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
gh workflow run update-cask.yml \
--repo coollabsio/homebrew-jean \
--field version='${{ steps.version.outputs.tag }}'