Skip to content

ci:final touches?

ci:final touches? #25

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
sign:
description: "Enable code signing"
required: false
default: false
type: boolean
jobs:
release:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: "macos-latest"
args: "--target aarch64-apple-darwin"
arch: "aarch64"
# - platform: 'macos-latest'
# args: '--target x86_64-apple-darwin'
# arch: 'x86_64'
- platform: "ubuntu-24.04"
args: ""
arch: "x86_64"
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-24.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
# Only add targets on macOS since we're cross-compiling
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: "./src-tauri -> target"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: "npm"
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Setup Python cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install frontend dependencies
run: npm install
- name: Prebuild
run: make prebuild
# macOS code signing setup
- name: Import Apple Developer Certificate (macOS)
if: matrix.platform == 'macos-latest' && (startsWith(github.ref, 'refs/tags/') || github.event.inputs.sign == 'true')
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# Check if we have the required secrets
if [ -z "$APPLE_CERTIFICATE" ] || [ -z "$APPLE_CERTIFICATE_PASSWORD" ] || [ -z "$KEYCHAIN_PASSWORD" ]; then
echo "Warning: Apple signing certificates not available. Building without code signing."
exit 0
fi
# Create the certificate from the secret
echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12
# Create a new keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security set-keychain-settings -t 3600 -u build.keychain
# Import certificate to keychain
security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
# Find and set the signing identity
CERT_INFO=$(security find-identity -v -p codesigning build.keychain | head -n 1)
SIGNING_IDENTITY=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
echo "APPLE_SIGNING_IDENTITY=$SIGNING_IDENTITY" >> $GITHUB_ENV
echo "Certificate imported successfully. Signing identity: $SIGNING_IDENTITY"
- name: Sign sidecar (macOS only)
if: matrix.platform == 'macos-latest' && (startsWith(github.ref, 'refs/tags/') || github.event.inputs.sign == 'true')
env:
APPLE_SIGNING_IDENTITY: ${{ env.APPLE_SIGNING_IDENTITY }}
run: |
if [ -z "$APPLE_SIGNING_IDENTITY" ]; then
echo "Warning: Apple signing identity not available. Skipping sidecar signing."
exit 0
fi
SIDECAR_PATH="bins/gptme-server-${{ matrix.arch }}-apple-darwin"
if [ ! -f "$SIDECAR_PATH" ]; then
echo "Error: Sidecar binary not found at $SIDECAR_PATH"
exit 1
fi
echo "Signing sidecar binary at $SIDECAR_PATH"
codesign --force -s "$APPLE_SIGNING_IDENTITY" --keychain build.keychain --deep "$SIDECAR_PATH"
echo "Sidecar binary signed successfully"
- name: Build the app (macOS)
if: matrix.platform == 'macos-latest'
env:
APPLE_SIGNING_IDENTITY: ${{ env.APPLE_SIGNING_IDENTITY }}
run: |
echo "Building macOS app with make build..."
make build
- name: Sign macOS app and create DMG
if: matrix.platform == 'macos-latest' && (startsWith(github.ref, 'refs/tags/') || github.event.inputs.sign == 'true')
env:
APPLE_SIGNING_IDENTITY: ${{ env.APPLE_SIGNING_IDENTITY }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
if [ -z "$APPLE_SIGNING_IDENTITY" ]; then
echo "Warning: Apple signing identity not available. Skipping app signing."
exit 0
fi
# Set paths for app and DMG files
APP_PATH="src-tauri/target/release/bundle/macos/gptme-tauri.app"
DMG_DIR="src-tauri/target/release/bundle/dmg"
DMG_PATH="$DMG_DIR/gptme-tauri_${{ matrix.arch }}.dmg"
ZIP_PATH="$DMG_DIR/gptme-tauri_${{ matrix.arch }}.app.zip"
mkdir -p "$DMG_DIR"
echo "Signing app bundle at $APP_PATH"
# Sign app bundle with deep signing
codesign --force -s "$APPLE_SIGNING_IDENTITY" --keychain build.keychain --deep --options runtime "$APP_PATH"
# # Verify signature
# codesign --verify --verbose "$APP_PATH"
echo "Creating DMG file"
# Create a directory for the DMG contents
mkdir -p dmg-contents
# Copy the app to a temporary location
cp -r "$APP_PATH" dmg-contents/
# Create a symlink to Applications folder
ln -s /Applications dmg-contents/
# Create the DMG using native hdiutil (more reliable than third-party tools)
hdiutil create -volname "gptme-tauri" \
-srcfolder dmg-contents \
-ov -format UDZO \
"$DMG_PATH"
# Clean up temporary directory
rm -rf dmg-contents
echo "Signing DMG file"
codesign --force -s "$APPLE_SIGNING_IDENTITY" --keychain build.keychain "$DMG_PATH"
# echo "Creating ZIP archive of .app bundle"
# # Zip the .app bundle for distribution
# ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"
# # Sign the ZIP file (optional but recommended)
# codesign --force -s "$APPLE_SIGNING_IDENTITY" --keychain build.keychain "$ZIP_PATH"
# echo "App, DMG, and ZIP archive created and signed successfully"
echo "DMG created and signed successfully"
- name: Upload macOS binaries to release
if: matrix.platform == 'macos-latest' && startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
with:
files: |
src-tauri/target/release/bundle/dmg/gptme-tauri_${{ matrix.arch }}.dmg
tag_name: ${{ github.ref_name }}
name: gptme-tauri ${{ github.ref_name }}
body: See the assets to download and install this version.
draft: true
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Use the normal Tauri action for non-macOS platforms
- name: Build and release for non-macOS platforms
if: matrix.platform != 'macos-latest'
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/') && 'gptme-tauri v__VERSION__' || '' }}
releaseBody: ${{ startsWith(github.ref, 'refs/tags/') && 'See the assets to download and install this version.' || '' }}
releaseDraft: ${{ startsWith(github.ref, 'refs/tags/') }}
prerelease: false
args: ${{ matrix.args }}