Skip to content

ci(desktop): sign/notarize when secrets exist; fix deb runtime deps; refresh release docs #61

ci(desktop): sign/notarize when secrets exist; fix deb runtime deps; refresh release docs

ci(desktop): sign/notarize when secrets exist; fix deb runtime deps; refresh release docs #61

name: Desktop Release
on:
push:
tags:
- 'v*'
# Package (never sign or publish) on PRs touching desktop packaging, so a broken
# matrix leg shows up before a tag instead of silently skipping a release.
pull_request:
paths:
- 'apps/desktop/**'
- 'scripts/desktop-signing-env.sh'
- '.github/workflows/desktop-release.yml'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 0.1.0)'
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
platform: mac
arch: arm64
- os: macos-latest
platform: mac
arch: x64
- os: windows-latest
platform: win
arch: x64
- os: ubuntu-latest
platform: linux
arch: x64
runs-on: ${{ matrix.os }}
name: Build ${{ matrix.platform }}-${{ matrix.arch }}
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup pnpm
uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 22
cache: 'pnpm'
# Only the desktop app and what it depends on. A whole-workspace install
# pulls in the CLI's better-sqlite3, which has no prebuild step and falls
# back to node-gyp; on windows-latest node-gyp cannot parse the runner's
# Visual Studio 18, so win-x64 failed, the release job was skipped, and
# no GitHub Release was cut from v0.11.11 through v0.13.1. The desktop
# app never used better-sqlite3.
- name: Install dependencies
run: pnpm install --frozen-lockfile --filter "@profullstack/threatcrush-desktop..."
# Code signing and notarization switch on by themselves once their
# secrets exist and are skipped cleanly while they don't (the builds are
# then unsigned, as they have been so far). scripts/desktop-signing-env.sh
# exports only what is set; how to obtain each secret is in
# docs/DESKTOP_RELEASE_TODO.md.
#
# macOS signing (both):
# APPLE_CERTIFICATE base64 of a "Developer ID Application" .p12 (certificate + private key)
# APPLE_CERTIFICATE_PASSWORD password of that .p12
# macOS notarization (runs only on a signed app). Set ONE group; the App
# Store Connect API key is what electron-builder recommends for CI:
# APPLE_API_KEY contents of the AuthKey_<KEY_ID>.p8 file
# APPLE_API_KEY_ID its 10-character Key ID
# APPLE_API_ISSUER Issuer ID (UUID) shown on the App Store Connect keys page
# or
# APPLE_ID Apple ID email of a team member
# APPLE_APP_SPECIFIC_PASSWORD app-specific password for that Apple ID
# APPLE_TEAM_ID 10-character Team ID
# Windows signing (both):
# WINDOWS_CERTIFICATE base64 of an Authenticode code-signing .pfx
# WINDOWS_CERTIFICATE_PASSWORD password of that .pfx
- name: Configure code signing
shell: bash
env:
PLATFORM: ${{ matrix.platform }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: bash scripts/desktop-signing-env.sh
# Linux dependencies for electron-builder
- name: Install Linux dependencies
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libarchive-tools rpm
- name: Build desktop app
run: pnpm --filter @profullstack/threatcrush-desktop build
- name: Package desktop app
working-directory: apps/desktop
run: npx electron-builder --${{ matrix.platform }} --${{ matrix.arch }} --publish never
- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
name: desktop-${{ matrix.platform }}-${{ matrix.arch }}
path: |
apps/desktop/release/*.dmg
apps/desktop/release/*.zip
apps/desktop/release/*.exe
apps/desktop/release/*.AppImage
apps/desktop/release/*.deb
apps/desktop/release/*.rpm
retention-days: 7
release:
needs: build
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Get version
id: version
env:
INPUT_VERSION: ${{ github.event.inputs.version }}
REF_NAME: ${{ github.ref_name }}
run: |
if [ -n "$INPUT_VERSION" ]; then
VERSION="$INPUT_VERSION"
else
VERSION="$REF_NAME"
fi
VERSION="${VERSION#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
if [[ "$VERSION" == *"-alpha"* ]] || [[ "$VERSION" == *"-beta"* ]] || [[ "$VERSION" == *"-rc"* ]]; then
echo "prerelease=true" >> "$GITHUB_OUTPUT"
else
echo "prerelease=false" >> "$GITHUB_OUTPUT"
fi
- name: Download all artifacts
uses: actions/download-artifact@v8
with:
path: dist
pattern: desktop-*
merge-multiple: true
- name: List artifacts
run: ls -la dist/
- name: Generate checksums
run: |
cd dist
sha256sum * > SHA256SUMS.txt
cat SHA256SUMS.txt
- name: Create Release
uses: softprops/action-gh-release@v3
with:
tag_name: ${{ steps.version.outputs.tag }}
name: ThreatCrush ${{ steps.version.outputs.version }}
draft: false
prerelease: ${{ steps.version.outputs.prerelease }}
generate_release_notes: true
files: |
dist/*
env:
GITHUB_TOKEN: ${{ secrets.PKG_SUBMIT_TOKEN || secrets.GITHUB_TOKEN }}