ci: build unsigned desktop artifacts without signing secrets (#1530)

This commit is contained in:
Carlos Florêncio
2026-06-29 11:02:38 +01:00
committed by GitHub
parent 831a15a9b7
commit 7a43a5bfbe
13 changed files with 221 additions and 86 deletions
+58 -53
View File
@@ -24,8 +24,10 @@ name: release
# Each package (kandev + 5 @kdlbs/runtime-* packages) must have this workflow
# configured as its trusted publisher on npmjs.com (Settings → Publishing access).
#
# Required secrets:
# Required secrets for public releases:
# HOMEBREW_TAP_DEPLOY_KEY — SSH private key for kdlbs/homebrew-kandev deploy key
# Optional secrets for signed desktop artifacts. If these are incomplete, the
# workflow still builds unsigned desktop artifacts and warns in release notes.
# APPLE_CERTIFICATE / APPLE_CERTIFICATE_PASSWORD / KEYCHAIN_PASSWORD — macOS Developer ID signing
# APPLE_ID / APPLE_PASSWORD / APPLE_TEAM_ID or APPLE_API_KEY / APPLE_API_ISSUER / APPLE_API_KEY_P8 — macOS notarization
# WINDOWS_CERTIFICATE / WINDOWS_CERTIFICATE_PASSWORD — Windows installer signing
@@ -46,10 +48,6 @@ on:
description: "Dry run (no PR, tag, npm publish, or tap update)"
type: boolean
default: false
allow_unsigned_desktop:
description: "Allow unsigned macOS/Windows desktop artifacts; still publishes unless validation-only is checked"
type: boolean
default: false
desktop_validation_only:
description: "Build desktop artifacts only (no PR, tag, publish, npm, or tap update)"
type: boolean
@@ -279,10 +277,9 @@ jobs:
NEXT: ${{ steps.compute.outputs.version }}
TAG: ${{ steps.compute.outputs.tag }}
REF: ${{ steps.compute.outputs.ref }}
ALLOW_UNSIGNED_DESKTOP: ${{ inputs.allow_unsigned_desktop }}
run: |
echo "Desktop validation for $TAG / $NEXT."
echo "Unsigned desktop artifacts allowed: $ALLOW_UNSIGNED_DESKTOP."
echo "Desktop signing is automatic: complete signing inputs produce signed artifacts; otherwise artifacts are unsigned."
echo "No release PR, tag, GitHub release, public container tags, npm publish, or Homebrew update will be created."
echo "Build jobs will check out $REF."
@@ -536,7 +533,6 @@ jobs:
- name: Configure macOS signing and notarization
if: startsWith(matrix.platform, 'macos-')
env:
ALLOW_UNSIGNED_DESKTOP: ${{ inputs.allow_unsigned_desktop }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
@@ -550,37 +546,12 @@ jobs:
run: |
set -euo pipefail
if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then
echo "::notice::Unsigned desktop artifacts requested; skipping macOS signing and notarization setup."
if ! bash scripts/release/desktop-signing-ready.sh macos >/dev/null 2>&1; then
echo "MACOS_SIGNING_ENABLED=false" >> "$GITHUB_ENV"
echo "::notice::macOS signing/notarization inputs are incomplete; building unsigned desktop artifact."
exit 0
fi
missing=()
for key in APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD KEYCHAIN_PASSWORD; do
if [ -z "${!key:-}" ]; then
missing+=("$key")
fi
done
apple_id_notarization=0
if [ -n "${APPLE_ID:-}" ] && [ -n "${APPLE_PASSWORD:-}" ] && [ -n "${APPLE_TEAM_ID:-}" ]; then
apple_id_notarization=1
fi
api_key_notarization=0
if [ -n "${APPLE_API_KEY:-}" ] && [ -n "${APPLE_API_ISSUER:-}" ] && [ -n "${APPLE_API_KEY_P8:-}" ]; then
api_key_notarization=1
fi
if [ "$apple_id_notarization" -eq 0 ] && [ "$api_key_notarization" -eq 0 ]; then
missing+=("APPLE_ID/APPLE_PASSWORD/APPLE_TEAM_ID or APPLE_API_KEY/APPLE_API_ISSUER/APPLE_API_KEY_P8")
fi
if [ "${#missing[@]}" -gt 0 ]; then
echo "::error::Public macOS desktop releases require signing and notarization inputs: ${missing[*]}" >&2
exit 1
fi
certificate_path="$RUNNER_TEMP/kandev-developer-id.p12"
python3 - <<'PY'
import base64
@@ -609,8 +580,9 @@ jobs:
fi
cert_id="$(echo "$cert_info" | awk -F'"' '{print $2}')"
echo "APPLE_SIGNING_IDENTITY=$cert_id" >> "$GITHUB_ENV"
echo "MACOS_SIGNING_ENABLED=true" >> "$GITHUB_ENV"
if [ "$api_key_notarization" -eq 1 ]; then
if [ -n "${APPLE_API_KEY:-}" ] && [ -n "${APPLE_API_ISSUER:-}" ] && [ -n "${APPLE_API_KEY_P8:-}" ]; then
private_keys_dir="$RUNNER_TEMP/private_keys"
mkdir -p "$private_keys_dir"
printf '%s\n' "$APPLE_API_KEY_P8" > "$private_keys_dir/AuthKey_${APPLE_API_KEY}.p8"
@@ -618,7 +590,7 @@ jobs:
fi
- name: Sign macOS desktop runtime binaries
if: startsWith(matrix.platform, 'macos-') && !inputs.allow_unsigned_desktop
if: startsWith(matrix.platform, 'macos-') && env.MACOS_SIGNING_ENABLED == 'true'
run: |
set -euo pipefail
runtime_bin="apps/desktop/src-tauri/resources/kandev/bin"
@@ -632,8 +604,22 @@ jobs:
codesign --verify --strict --verbose=2 "$path"
done
- name: Detect Windows signing inputs
if: matrix.platform == 'windows-x64'
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
set -euo pipefail
if bash scripts/release/desktop-signing-ready.sh windows >/dev/null 2>&1; then
echo "WINDOWS_SIGNING_ENABLED=true" >> "$GITHUB_ENV"
else
echo "WINDOWS_SIGNING_ENABLED=false" >> "$GITHUB_ENV"
echo "::notice::Windows signing inputs are incomplete; building unsigned desktop artifact."
fi
- name: Sign Windows desktop runtime binaries
if: matrix.platform == 'windows-x64' && !inputs.allow_unsigned_desktop
if: matrix.platform == 'windows-x64' && env.WINDOWS_SIGNING_ENABLED == 'true'
shell: pwsh
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -662,14 +648,13 @@ jobs:
APPLE_PROVIDER_SHORT_NAME: ${{ secrets.APPLE_PROVIDER_SHORT_NAME }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
ALLOW_UNSIGNED_DESKTOP: ${{ inputs.allow_unsigned_desktop }}
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
WINDOWS_TIMESTAMP_URL: ${{ secrets.WINDOWS_TIMESTAMP_URL }}
WINDOWS_SIGNTOOL_PATH: ${{ secrets.WINDOWS_SIGNTOOL_PATH }}
run: |
set -euo pipefail
if [ "$ALLOW_UNSIGNED_DESKTOP" = "true" ]; then
if [ "${MACOS_SIGNING_ENABLED:-false}" != "true" ]; then
unset APPLE_CERTIFICATE
unset APPLE_CERTIFICATE_PASSWORD
unset APPLE_ID
@@ -680,6 +665,8 @@ jobs:
unset APPLE_API_ISSUER
unset APPLE_API_KEY_PATH
unset APPLE_SIGNING_IDENTITY
fi
if [ "${WINDOWS_SIGNING_ENABLED:-false}" != "true" ]; then
unset WINDOWS_CERTIFICATE
unset WINDOWS_CERTIFICATE_PASSWORD
unset WINDOWS_TIMESTAMP_URL
@@ -693,7 +680,7 @@ jobs:
--bundles "${{ matrix.tauri_bundles }}"
- name: Sign Windows desktop artifacts
if: matrix.platform == 'windows-x64' && !inputs.allow_unsigned_desktop
if: matrix.platform == 'windows-x64' && env.WINDOWS_SIGNING_ENABLED == 'true'
shell: pwsh
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
@@ -701,15 +688,6 @@ jobs:
WINDOWS_TIMESTAMP_URL: ${{ secrets.WINDOWS_TIMESTAMP_URL }}
WINDOWS_SIGNTOOL_PATH: ${{ secrets.WINDOWS_SIGNTOOL_PATH }}
run: |
$missing = @()
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE)) { $missing += "WINDOWS_CERTIFICATE" }
if ([string]::IsNullOrWhiteSpace($env:WINDOWS_CERTIFICATE_PASSWORD)) { $missing += "WINDOWS_CERTIFICATE_PASSWORD" }
if ($missing.Count -gt 0) {
Write-Error "Public Windows desktop releases require signing inputs: $($missing -join ', ')"
exit 1
}
$certificatePath = Join-Path $env:RUNNER_TEMP "kandev-code-signing.pfx"
[IO.File]::WriteAllBytes($certificatePath, [Convert]::FromBase64String($env:WINDOWS_CERTIFICATE))
@@ -1185,13 +1163,40 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add unsigned desktop warning to release notes
if: ${{ inputs.allow_unsigned_desktop }}
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }}
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
set -euo pipefail
unsigned=()
if ! bash scripts/release/desktop-signing-ready.sh macos >/dev/null 2>&1; then
unsigned+=("macOS")
fi
if ! bash scripts/release/desktop-signing-ready.sh windows >/dev/null 2>&1; then
unsigned+=("Windows")
fi
if [ "${#unsigned[@]}" -eq 0 ]; then
exit 0
fi
platforms="${unsigned[0]}"
for ((i = 1; i < ${#unsigned[@]}; i++)); do
platforms="$platforms, ${unsigned[$i]}"
done
tmp="$(mktemp)"
{
echo "> [!WARNING]"
echo "> macOS and Windows desktop installers in this release are unsigned."
echo "> $platforms desktop installers in this release are unsigned development builds."
echo "> They may require manual OS security bypasses and are not trusted downloads."
echo
cat RELEASE_NOTES.md