Skip to content

chore: release v0.6.2 #68

chore: release v0.6.2

chore: release v0.6.2 #68

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
concurrency:
group: release-${{ github.ref_name }}
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
target: universal-apple-darwin
bundles: dmg,app
- platform: windows-latest
target: x86_64-pc-windows-msvc
bundles: nsis
- platform: ubuntu-22.04
target: x86_64-unknown-linux-gnu
bundles: appimage,deb
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v5
- name: Install Linux deps
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libglib2.0-dev libgtk-3-dev libjavascriptcoregtk-4.1-dev libsoup-3.0-dev
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- name: Install frontend deps
run: npm ci
- uses: dtolnay/rust-toolchain@stable
- name: Add macOS targets
if: runner.os == 'macOS'
run: rustup target add aarch64-apple-darwin x86_64-apple-darwin
- uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri
- name: Import macOS signing certificate
if: runner.os == 'macOS'
shell: bash
env:
MACOS_SIGNING_CERTIFICATE: ${{ secrets.MACOS_SIGNING_CERTIFICATE }}
MACOS_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_SIGNING_CERTIFICATE_PASSWORD }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_API_PRIVATE_KEY: ${{ secrets.APPLE_API_PRIVATE_KEY }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
run: |
set -euo pipefail
CERT_BASE64="${MACOS_SIGNING_CERTIFICATE:-${APPLE_CERTIFICATE:-}}"
CERT_PASSWORD="${MACOS_SIGNING_CERTIFICATE_PASSWORD:-${APPLE_CERTIFICATE_PASSWORD:-}}"
if [ -z "$CERT_BASE64" ]; then
echo "No macOS signing certificate is configured; macOS app will be unsigned/ad-hoc."
exit 0
fi
if [ -z "$CERT_PASSWORD" ]; then
echo "A certificate password is required when a macOS signing certificate is configured." >&2
exit 1
fi
KEYCHAIN_PASSWORD="$(openssl rand -base64 32)"
KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain-db"
CERTIFICATE_PATH="$RUNNER_TEMP/certificate.p12"
echo "$CERT_BASE64" | base64 --decode > "$CERTIFICATE_PATH"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH"
security default-keychain -s "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security import "$CERTIFICATE_PATH" -k "$KEYCHAIN_PATH" -P "$CERT_PASSWORD" -A -T /usr/bin/codesign
CERT_PEM="$RUNNER_TEMP/signing-cert.pem"
if openssl pkcs12 -legacy -in "$CERTIFICATE_PATH" -nokeys -out "$CERT_PEM" -passin "pass:$CERT_PASSWORD" >/dev/null 2>&1 ||
openssl pkcs12 -in "$CERTIFICATE_PATH" -nokeys -out "$CERT_PEM" -passin "pass:$CERT_PASSWORD" >/dev/null 2>&1; then
sudo -n security add-trusted-cert -d -r trustRoot -p codeSign -k /Library/Keychains/System.keychain "$CERT_PEM"
fi
CERT_ID="$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | awk '/^[[:space:]]*[0-9]+\)/ { print $2; exit }')"
if [ -z "$CERT_ID" ]; then
echo "No usable macOS code signing identity found in imported certificate." >&2
security find-identity -v -p codesigning "$KEYCHAIN_PATH" >&2
exit 1
fi
echo "APPLE_SIGNING_IDENTITY=$CERT_ID" >> "$GITHUB_ENV"
echo "MACOS_SIGNING_EXPECTED=true" >> "$GITHUB_ENV"
if [ -n "${APPLE_API_PRIVATE_KEY:-}" ] && [ -n "${APPLE_API_KEY:-}" ]; then
API_KEY_PATH="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY}.p8"
printf '%s' "$APPLE_API_PRIVATE_KEY" > "$API_KEY_PATH"
echo "APPLE_API_KEY_PATH=$API_KEY_PATH" >> "$GITHUB_ENV"
fi
- name: Build Tauri app
shell: bash
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
# Without a stable macOS code signature, macOS identifies each release
# build by its binary hash, so privacy grants for protected folders do
# not survive app updates.
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
run: |
set -euo pipefail
if [ "${RUNNER_OS:-}" = "macOS" ] && [ -n "${APPLE_SIGNING_IDENTITY:-}" ]; then
SIGN_CONFIG="$(printf '{"bundle":{"macOS":{"signingIdentity":"%s"}}}' "$APPLE_SIGNING_IDENTITY")"
npx tauri build --target ${{ matrix.target }} --bundles ${{ matrix.bundles }} --config "$SIGN_CONFIG"
else
npx tauri build --target ${{ matrix.target }} --bundles ${{ matrix.bundles }}
fi
- name: Verify macOS signature identity
if: runner.os == 'macOS'
shell: bash
run: |
set -euo pipefail
APP="src-tauri/target/${{ matrix.target }}/release/bundle/macos/SessionView.app"
[ -d "$APP" ] || APP="src-tauri/target/release/bundle/macos/SessionView.app"
REQUIREMENT="$(codesign -dr - "$APP" 2>&1)"
echo "$REQUIREMENT"
if [ "${MACOS_SIGNING_EXPECTED:-}" = "true" ] && echo "$REQUIREMENT" | grep -q "cdhash"; then
echo "macOS app was expected to use certificate signing, but it is still ad-hoc." >&2
exit 1
fi
- name: Collect release assets
shell: bash
run: |
set -euo pipefail
mkdir -p release-assets
V="${GITHUB_REF_NAME}"
BD="src-tauri/target/${{ matrix.target }}/release/bundle"
[ -d "$BD" ] || BD="src-tauri/target/release/bundle"
copy() {
[ -f "$1" ] || return 0
cp "$1" "release-assets/$2"
echo "✓ $2"
[ -f "$1.sig" ] && cp "$1.sig" "release-assets/$2.sig" && echo "✓ $2.sig"
return 0
}
# macOS
for f in "$BD"/dmg/*.dmg; do copy "$f" "SessionView-$V-macOS.dmg"; done
for f in "$BD"/macos/*.tar.gz; do copy "$f" "SessionView-$V-macOS.tar.gz"; done
# Windows
for f in "$BD"/nsis/*-setup.exe; do copy "$f" "SessionView-$V-Windows.exe"; done
# Linux
for f in "$BD"/appimage/*.AppImage; do copy "$f" "SessionView-$V-Linux-x86_64.AppImage"; done
for f in "$BD"/deb/*.deb; do copy "$f" "SessionView-$V-Linux-x86_64.deb"; done
echo "--- release-assets ---"
ls -la release-assets/
- name: Upload release artifacts
uses: actions/upload-artifact@v5
with:
name: release-assets-${{ runner.os }}-${{ runner.arch }}
path: release-assets/*
if-no-files-found: error
- name: Debug bundle listing
if: failure()
shell: bash
run: find src-tauri/target -maxdepth 5 -type f \( -name "*.dmg" -o -name "*.tar.gz" -o -name "*.sig" -o -name "*.AppImage" -o -name "*.deb" -o -name "*.exe" \) 2>/dev/null || true
publish-release:
runs-on: ubuntu-22.04
needs: build
permissions:
contents: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v5
with:
pattern: release-assets-*
path: release-assets
merge-multiple: true
- name: Generate latest.json
run: |
set -euo pipefail
TAG="${GITHUB_REF_NAME}"
VERSION="${TAG#v}"
BASE_URL="https://github.com/$GITHUB_REPOSITORY/releases/download/$TAG"
mac_url="" mac_sig="" win_url="" win_sig="" linux_url="" linux_sig=""
shopt -s nullglob
for sig in release-assets/*.sig; do
base="${sig%.sig}"
fname="$(basename "$base")"
url="$BASE_URL/$fname"
content="$(cat "$sig")"
case "$fname" in
*.tar.gz) mac_url="$url"; mac_sig="$content" ;;
*-Linux-*.AppImage|*-Linux-*.appimage) linux_url="$url"; linux_sig="$content" ;;
*.exe) win_url="$url"; win_sig="$content" ;;
esac
done
jq -n \
--arg version "$VERSION" \
--arg notes "Release $TAG" \
--arg pub_date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--arg mac_url "$mac_url" --arg mac_sig "$mac_sig" \
--arg win_url "$win_url" --arg win_sig "$win_sig" \
--arg linux_url "$linux_url" --arg linux_sig "$linux_sig" \
'{
version: $version,
notes: $notes,
pub_date: $pub_date,
platforms: (
{}
| if ($mac_url | length > 0) then
. + {"darwin-aarch64": {signature: $mac_sig, url: $mac_url},
"darwin-x86_64": {signature: $mac_sig, url: $mac_url}}
else . end
| if ($win_url | length > 0) then
. + {"windows-x86_64": {signature: $win_sig, url: $win_url}}
else . end
| if ($linux_url | length > 0) then
. + {"linux-x86_64": {signature: $linux_sig, url: $linux_url}}
else . end
)
}' > release-assets/latest.json
echo "Generated latest.json:"
cat release-assets/latest.json
- name: List release assets
run: ls -la release-assets/
- name: Publish GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: SessionView ${{ github.ref_name }}
draft: true
prerelease: false
body: |
See the [changelog](https://github.com/${{ github.repository }}/blob/master/CHANGELOG.md) for details.
### Downloads
- **macOS**: `SessionView-${{ github.ref_name }}-macOS.dmg`
- **Windows**: `SessionView-${{ github.ref_name }}-Windows.exe`
- **Linux**: `SessionView-${{ github.ref_name }}-Linux-x86_64.AppImage` / `.deb`
> `.tar.gz` files are for Tauri auto-updater only.
files: release-assets/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}