Release Jean #54
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 }}' |