Native Installers & Packaging — Design
.app, quarantine stripped on install — no Apple Developer account), and Windows Authenticode is free via the SignPath Foundation OSS program. No purchase from Apple or Microsoft is required. See "Signing — the OSS way". Related: Fyne GUI client design, .goreleaser.yaml, .github/workflows/release.yml.Native Installers & Packaging — Design
Date: 2026-07-17
Status: implemented contract (reconciled 2026-07-25).
Revision (2026-07-17): the earlier "Scope B is blocked on paid Apple/MS
credentials" framing was WRONG. OSS projects sign for free: macOS ships as a
Homebrew cask (ad-hoc-signed .app, quarantine stripped on install — no
Apple Developer account), and Windows Authenticode is free via the SignPath
Foundation OSS program. No purchase from Apple or Microsoft is required. See
"Signing — the OSS way".
Related: Fyne GUI client design,
.goreleaser.yaml, .github/workflows/release.yml.
Goal
Ship radioactive-ralph as real, installable software on every platform — both the CLI (already largely done) and the GUI desktop app (new) — with the widest set of native package formats each ecosystem expects, verifiable by signature.
What already exists (baseline on main)
.goreleaser.yaml: CGO-off CLI binaries for 6 GOOS/GOARCH,.tar.gz/.ziparchives,checksums.txtcosign-signed (keyless), and generated Homebrew, Scoop, and winget manifests. Only the Homebrew and Scoop manifests are published tojbcom/pkgsvia checked PRs; winget remains generated-only..goreleaser.chocolatey.yaml: Chocolatey publish from a Windows runner.docs/install.sh: curl-pipe installer — resolves latest, downloads the arch archive, verifies its SHA-256 againstchecksums.txt, extracts the CLI.release.yml: one Ubuntu GoReleaser build plus an optional Windows Chocolatey publisher that runs only after immutable GitHub publication.- Icon source:
assets/brand/ralph-mascot.png.
The central design fork: how to build the GUI-enabled binaries
The CLI ships CGO-off; the GUI needs -tags gui with CGO and the platform GL
stack. That is the whole difficulty of this item. Three options considered:
goreleaser with per-platform CGO builds + native runners. Add a second goreleaser
build(idradioactive_ralph_gui,-tags gui,CGO_ENABLED=1) and run goreleaser on a matrix of native runners (macos for darwin, ubuntu for linux, windows for windows) so each GUI binary links against its own OS toolchain — no cross-CGO. Downsides: goreleaser's single-run model fights a per-OS matrix; you split into per-OS configs and merge.fyne-cross(Docker-based cross-compile). Fyne's official cross tool builds.app/.dmg,.exe+installer, and Linux tarballs from one Linux host via Docker images carrying each toolchain. Clean for GUI bundles, but it's a second release tool bolted alongside goreleaser, and macOS notarization still can't happen inside Linux Docker.Split by concern (RECOMMENDED). Keep goreleaser as the CLI + Linux packaging authority (it already is), and add GUI-app bundling per-OS on native runners using each platform's idiomatic tool:
- macOS:
fyne packageon a macos runner →.app, wrapped to.dmg. - Windows:
fyne packageon a windows runner →.exe. - Linux:
fyne package→ tarball, repacked as AppImage; ship.desktop.
Rationale: no cross-CGO, each OS uses its native toolchain, goreleaser stays the CLI/signing/manifest authority, and
fyne packageis the tool that actually knows how to bundle a Fyne app per platform. The GUI bundles are uploaded as additional release assets alongside goreleaser's CLI archives.- macOS:
Decision: Option 3. Recorded in decisions.ndjson.
Scope A — credential-free, do now
These need no new credentials (reuse the existing cosign keyless + tokens):
- goreleaser
nfpms→.deb+.rpmfor the CLI, for linux amd64/arm64. Straight goreleaser config addition; artifacts cosign-signed like the archives. Includes aradioactive_ralphbin in/usr/bin. - winget manifest generation → GoReleaser writes the manifest under
dist/for inspection. Upload, staging, and submission are disabled until there is a real consumer-tested publication path; winget is not part of the supported install surface. - Linux
.desktop+ AppImage for the GUI. The.desktopfile (radioactive-ralph.desktop, Exec=radioactive_ralph gui, the mascot icon) is committed; the AppImage is built on the ubuntu GUI runner from the-tags guibinary viaappimagetool. AppImages are unsigned by convention (verified by the release checksum instead), so no cert needed. - install.sh audit — verify the archive against
checksums.txt, and whencosignis present verify that manifest's Sigstore bundle against the exact tagged release-workflow identity and GitHub Actions issuer first. Withoutcosign, print an explicit SHA-only fallback notice. Document the GUI install path (the app bundles are not curl-pipe installable; point at the native installers).
Scope B — GUI app bundles (no purchase required)
The GUI desktop bundles. Signing is handled the OSS way (next section), so none of this needs a paid Apple/Microsoft account:
- macOS
.appvia a Homebrew cask.fyne packageon a macos runner producesradioactive-ralph.app, ad-hoc-signed (codesign -s -, free). It is delivered as the distinctradioactive-ralph-guiHomebrew cask injbcom/pkgs, beside theradioactive-ralphCLI cask:brew install --cask radioactive-ralph-gui. Itspostflightexplicitly strips thecom.apple.quarantinexattr, so Gatekeeper does not block it despite the absence of notarization — the standard OSS-app path. A.dmgis also produced as a release asset for direct download (that path shows a Gatekeeper prompt; the cask is the recommended install). - Windows
.exe.fyne packageon a windows runner. Sign with the SignPath Foundation OSS certificate when enrollment credentials exist; otherwise publish it unsigned as a best-effort direct download that may trigger SmartScreen. No MSI/WiX artifact is implemented. - Linux AppImage (from Scope A) is the GUI delivery; AppImages are unsigned by convention and verified by the release checksum.
The Windows signing step is guarded on the corresponding secret being present,
so the pipeline builds the .exe unsigned until signing is wired, then signs
automatically once the secret lands. The AppImage is unsigned by convention;
all receive one consolidated workflow-identity-signed GUI checksum manifest.
Signing — the OSS way (free, no purchase)
Open source does not pay for code signing.
- macOS: an ad-hoc signature (
codesign --sign -) is free and sufficient when delivered through Homebrew, because the cask install removes the quarantine attribute. No Apple Developer Program membership, no Developer ID cert, no notarization for the cask path. (Notarization would only matter for a double-click-from-browser.dmg; the cask is the blessed install and the.dmgis best-effort.) - Windows: the SignPath Foundation gives free OV Authenticode signing to qualifying OSS projects (radioactive-ralph is MIT-licensed and public — it qualifies). SignPath signs through a managed pipeline triggered from the release workflow; the publisher shown is "SignPath Foundation". Clears SmartScreen at zero cost.
The one genuine user action is a one-time signup (not a purchase): enroll the
repo in SignPath's OSS program, then add the SIGNPATH_* token as a repo secret.
Until that token exists the Windows bundle ships unsigned; the signing step is
gated on the secret, so it turns on the moment the token is added.
Testing / verification
goreleaser release --snapshot --cleanlocally produces the CLI archives + the new.deb/.rpmwithout publishing. Native install proof runs throughscripts/ci/smoke_goreleaser_artifacts.shon Ubuntu x86_64 and arm64 (the helper intentionally rejects non-Linux hosts), usingdpkg/rpmandradioactive_ralph --version.- The
-tags guibinary + AppImage build on the ubuntu GUI runner; smoke-run--version(the GUI itself needs a display, but--versionproves the bundle links). .desktopvalidated withdesktop-file-validate.- install.sh: shellcheck clean; a dry-run against a snapshot checksums file.
Out of scope
- Auto-update / Sparkle / MSIX auto-update channels.
- Flatpak / Snap (AppImage covers portable Linux; revisit if requested).
- The GUI app's own in-app "check for updates".
Summary for the user
Nothing here requires paying Apple or Microsoft:
- macOS ships as a Homebrew cask (ad-hoc-signed
.app, quarantine stripped on install) — no Apple Developer account. - Windows can sign via the free SignPath Foundation OSS program — no
purchased cert. Until the one-time enrollment and
SIGNPATH_*secret exist, the best-effort direct.exeremains unsigned. - Linux CLI deb/rpm artifacts are covered by the keyless-signed GoReleaser checksum manifest. The AppImage is unsigned and has its own signed checksum manifest. Homebrew and Scoop are the supported published CLI managers; winget is generated-only and Chocolatey is optional only after immutable GitHub publication.
The supported stable paths can be built and verified autonomously. SignPath enrollment is an optional upgrade for the best-effort Windows direct download.
