packaging: signing + notarization + zip target + GitHub Releases feed

The 2026-10-08 flip, verified end-to-end (notarized build accepted,
stapled, spctl clean): Developer ID auto-detect, LH_NOTARY keychain
profile, zip + blockmap beside the DMG for Squirrel.Mac, publish block
pointing at GitHub Releases (repo goes public before 0.3.0; builds never
auto-upload — publishing is a release-time act).
This commit is contained in:
amosblomqvist
2026-10-09 07:59:32 +03:00
parent 1f41fb05a5
commit 5c1eb47740
3 changed files with 31 additions and 10 deletions
+27 -6
View File
@@ -6,9 +6,9 @@
# because native .node/dylib can't dlopen from a read-only archive and # because native .node/dylib can't dlopen from a read-only archive and
# server.js process.chdir()s into its own dir; # server.js process.chdir()s into its own dir;
# - the asar holds only the shell (electron/main.cjs + package.json); # - the asar holds only the shell (electron/main.cjs + package.json);
# - signing/notarization config is laid now but inert until a Developer # - signed + notarized since 2026-10-08 (Developer ID Application cert in
# ID certificate exists (identity: null = unsigned local build, which # the login keychain; notary credentials in the LH_NOTARY keychain
# runs fine for personal use — Gatekeeper only gates quarantined apps). # profile; the profile + team env vars are baked into desktop:dist).
appId: com.learnharness.LearnHarness appId: com.learnharness.LearnHarness
productName: LearnHarness productName: LearnHarness
directories: directories:
@@ -55,10 +55,16 @@ extraResources:
filter: filter:
- "standalone/**/*" - "standalone/**/*"
mac: mac:
# zip rides next to dmg (flipped 2026-10-08): Squirrel.Mac — Electron's
# macOS auto-updater — installs from ZIP and cannot read DMGs. DMG is
# for humans; ZIP + blockmap are the updater's payload.
target: target:
- target: dmg - target: dmg
arch: arch:
- arm64 - arm64
- target: zip
arch:
- arm64
# Locale trim (payload wave, 2026-09-24): English-only app — cuts # Locale trim (payload wave, 2026-09-24): English-only app — cuts
# every non-en .lproj from the frameworks (the STT/mic entitlements # every non-en .lproj from the frameworks (the STT/mic entitlements
# don't depend on locales). Revisit only if localization ever lands. # don't depend on locales). Revisit only if localization ever lands.
@@ -71,8 +77,23 @@ mac:
NSMicrophoneUsageDescription: "LearnHarness uses the microphone only for speech-to-text input into your sessions." NSMicrophoneUsageDescription: "LearnHarness uses the microphone only for speech-to-text input into your sessions."
hardenedRuntime: true hardenedRuntime: true
entitlements: build/entitlements.mac.plist entitlements: build/entitlements.mac.plist
# Unsigned until a Developer ID certificate exists (research-confirmed: # Signing + notarization (flipped 2026-10-08): identity auto-detects the
# local builds run fine; distribution needs signing + notarization). # Developer ID Application certificate from the login keychain;
identity: null # notarize: true makes electron-builder sign → submit to Apple's notary
# service → staple the ticket, all inside this one build (credentials
# via the LH_NOTARY keychain profile, env baked into desktop:dist).
# Adds minutes per build (Apple's scan queue). Verification battery:
# codesign --verify --deep / spctl --assess / stapler validate.
notarize: true
dmg: dmg:
title: "${productName} ${version}" title: "${productName} ${version}"
publish:
# Update feed = GitHub Releases (decided 2026-10-08): latest-mac.yml +
# zip/blockmap live on releases; electron-updater reads them anonymously.
# REQUIRES THE REPO TO BE PUBLIC before 0.3.0 ships — anonymous downloads
# from a private repo are impossible, and a token baked into the app
# would be a leak. desktop:dist passes no --publish flag, so builds never
# upload; publishing happens at release time (GH_TOKEN + --publish).
- provider: github
owner: amosblomqvist
repo: learnharness
+2 -2
View File
@@ -1,7 +1,7 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/image-types/global" /> /// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts"; import "./.next/dev/types/routes.d.ts";
import "./.next/types/root-params.d.ts"; import "./.next/dev/types/root-params.d.ts";
// NOTE: This file should not be edited // NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+1 -1
View File
@@ -14,7 +14,7 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"desktop:dev": "concurrently -k \"next dev\" \"LH_DEV_URL=http://localhost:3000 electron .\"", "desktop:dev": "concurrently -k \"next dev\" \"LH_DEV_URL=http://localhost:3000 electron .\"",
"dev:fresh": "bash scripts/dev-fresh.sh", "dev:fresh": "bash scripts/dev-fresh.sh",
"desktop:dist": "rm -rf dist .next/standalone && next build && node scripts/build-server.mjs && node scripts/smoke-server.mjs && electron-builder --mac --arm64" "desktop:dist": "rm -rf dist .next/standalone && next build && node scripts/build-server.mjs && node scripts/smoke-server.mjs && APPLE_KEYCHAIN_PROFILE=LH_NOTARY APPLE_TEAM_ID=JS6XN22HY6 electron-builder --mac --arm64"
}, },
"dependencies": { "dependencies": {
"@earendil-works/pi-agent-core": "1.0.2", "@earendil-works/pi-agent-core": "1.0.2",