chore: release v0.6.2 #68
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 | |
| 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 }} |