Files
learnharness/electron-builder.yml
T

99 lines
4.9 KiB
YAML
Raw Normal View History

# electron-builder config — LearnHarness desktop (macOS arm64 first).
#
# Shape (fact-checked 2026-09-17):
# - the app's real server (.next/standalone, curated by
# scripts/build-server.mjs) ships via extraResources — OUTSIDE the asar,
# because native .node/dylib can't dlopen from a read-only archive and
# server.js process.chdir()s into its own dir;
# - the asar holds only the shell (electron/main.cjs + package.json);
# - signed + notarized since 2026-10-08 (Developer ID Application cert in
# the login keychain; notary credentials in the LH_NOTARY keychain
# profile; the profile + team env vars are baked into desktop:dist).
appId: com.learnharness.LearnHarness
productName: LearnHarness
directories:
output: dist
files:
# Only the shell goes into the asar. ORDER IS LOAD-BEARING (payload
# wave, 2026-09-24): electron-builder's dependency collector packs the
# whole production dep tree into node_modules/ REGARDLESS of this
# allow-list — normalizeFiles turns this array into one {filter: [...]}
# fileSet, getNodeModuleFileMatcher feeds EVERY filter entry (positives
# included) to the per-dep copier, and without a negation its implicit
# '**/*' passes everything (the measured result: a 502MB asar holding
# next/@ai-sdk/pdfjs/mermaid/puppeteer… while the launcher requires
# nothing but electron + node builtins — the server ships via
# extraResources).
#
# The fix is gitignore-style ordering (verified against the installed
# app-builder-lib 26.15.3 + a DEBUG-mode rebuild): '!**/*' first excludes
# EVERYTHING, the two positives after it re-include only the shell.
# The per-dep collector then contributes ZERO files — app-builder-lib's
# filter evaluates each dep file's DESTINATION path (the
# stat.moduleFullFilePath quirk in util/filter.js getRelativePath), so
# '!**/*' matches every 'node_modules/<dep>/...' path and the bare
# positives can never re-include one (DEBUG logs confirm filesCount=0
# for all 566 modules). If a future electron-builder fixes that quirk,
# ~1MB of package.json stubs would start landing — harmless. The
# two-package.json layout avoids the collector entirely but
# restructures the repo. app.asar.unpacked dies with it: the natives
# were only unpacked because their packages were packed.
- "!**/*"
- electron/**/*
- package.json
extraResources:
# Copy from the PARENT dir (.next), not .next/standalone itself:
# electron-builder hard-excludes a copy's root node_modules and the
# default no-filter pattern is a literal path match (empirically both
# node_modules/ and .next/ were silently dropped → server died on
# "Cannot find module 'next'"). With `from: .next` the filter's
# relative paths start with standalone/, dodging the root-node_modules
# rule, and the explicit wildcard (minimatch dot:true) reaches
# standalone/.next and standalone/node_modules.
- from: .next
to: server
filter:
- "standalone/**/*"
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: dmg
arch:
- arm64
- target: zip
arch:
- arm64
# Locale trim (payload wave, 2026-09-24): English-only app — cuts
# every non-en .lproj from the frameworks (the STT/mic entitlements
# don't depend on locales). Revisit only if localization ever lands.
electronLanguages:
- en
category: public.app-category.education
# Laid for the STT milestone (researcher-verified): the TCC mic prompt
# reads this string; macOS asks regardless of Electron's own handlers.
extendInfo:
NSMicrophoneUsageDescription: "LearnHarness uses the microphone only for speech-to-text input into your sessions."
hardenedRuntime: true
entitlements: build/entitlements.mac.plist
# Signing + notarization (flipped 2026-10-08): identity auto-detects the
# Developer ID Application certificate from the login keychain;
# 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:
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