All posts
EngineeringProduct16 Sep 2026 · 3 min read

First desktop release, three bugs

JPJean Perez

The fourth dispatch of the desktop release workflow went green. The first three each caught a real bug.

Getting there took a chain of work: Electron 28 to 42.11, a packaging bug that sealed about 150 MB of FFmpeg binaries into the app's asar archive, a CI pipeline that was quietly shipping desktop builds with no FFmpeg at all, and a Windows installer that had to be rebuilt around a different packager entirely. Each one is small on its own. Together they're what "cutting a release" turned out to mean.

Getting the binary in, and out of the wrong place

Electron's extraResource step is supposed to exclude bundled FFmpeg binaries from the app's compressed asar archive and ship them alongside it instead. An ignore rule was missing, so the binaries got sealed into the archive anyway: app.asar went from 168 MB to 8.4 MB once the rule was in.

Before that fix could matter, a later PR found something worse: CI had been shipping desktop builds with no FFmpeg binary in them at all. The fix pins exact builds by sha256: BtbN's LGPL builds for Windows and Linux, evermeet.cx's for macOS. There is no LGPL static build for macOS, so the Mac app ships a GPL binary. That mismatch is still an open decision.

Four dispatches to get the pipeline itself working

The next change swapped Windows packaging from Squirrel (which fails outright on hosted GitHub runners) to NSIS via electron-builder, following the same approach already proven in a sister project. Getting the new workflow green took four real CI runs.

RunWhat it found
1An if: condition inside a workflow step referenced secrets where that context isn't valid, silently invalid since an earlier PR merged
2The desktop TypeScript compile step ran before the @beemmeup/ffmpeg-runner package it depends on had been built
3The Windows flatten step dropped scoped workspace packages it needed
4Succeeded

All three are ordinary bugs in a build matrix that had never run for real. macOS runs cost roughly $5 each, so the same PR caps macOS builds to arm64-only by default and puts a 20-minute cap on every job, with Intel available as an opt-in tag suffix.

What the first real release found

desktop-v1.1.0 published unsigned (no signing secrets were configured yet) and immediately surfaced two bugs the CI matrix had no way to catch, because they only show up once a release actually exists.

The Windows installer disappeared from /download. electron-builder's default NSIS filename has spaces (BeemMeUp Setup 1.1.0.exe); GitHub Releases rewrites spaces to dots on upload; every asset matcher in the codebase (the sync script, the Blob upload script, the download page) expected spaces. The installer existed, uploaded correctly, and was invisible to every consumer that looked for it. The fix sets the artifact name at the source going forward and makes every matcher tolerant of space, dot, or hyphen for the release already published.

The same PR fixed a second bug in the same release: the post-notarization Gatekeeper check ran spctl --assess --type install, the flag for a .pkg installer, against a .dmg, and reported "no usable signature" on a disk image that was correctly notarized and stapled. The type flag was wrong. --type open is what a DMG needs.

A third bug needed its own PR: build artifacts land in nested folders (dist/zip/darwin/arm64/…), but the update-feed generator only scanned the top level of dist/, so latest-mac.yml was never written and the macOS auto-updater had no feed to check against after the first release. The fix is a flatten-by-basename step, and introduces a "republish" dispatch mode alongside it: re-run just the release and feed-generation job against assets that already exist, no rebuild, roughly one free Ubuntu-runner minute instead of the macOS cost. It's now how any plumbing fix reaches a release that already shipped.

The update feed itself lives on a public Vercel Blob store, not GitHub Releases directly, because the repo is private and electron-updater's anonymous checks 404 against private release assets. Every non-draft release mirrors into it. Code signing and the macOS GPL question are what's left before a release I'd point people at.