Skip to content

Add tagged multi-platform desktop release workflow and unified artifact builder - #135

Merged
juliusmarminge merged 5 commits into
mainfrom
codething/4e64c33f
Mar 2, 2026
Merged

juliusmarminge merged 5 commits into
mainfrom
codething/4e64c33f

prep npm

8c2797a
Select commit
Loading
Failed to load commit list.
MacroscopeApp / Macroscope - Correctness Check succeeded Mar 2, 2026 in 1m 24s

No issues identified (29 code objects reviewed).

• Merge Base: 1af43db
• Head: 8c2797a

Details

✅ File Path Comments Posted
➖ bun.lock
➖ package.json
➖ .github/workflows/release.yml
➖ README.md
➖ docs/release.md
✅ scripts/build-desktop-artifact.ts 0

Filtered Issues Details

scripts/build-desktop-artifact.ts
  • line 142: The function resolveBooleanFlag introduces a strictness regression where boolean CLI flags set to false are ignored in favor of the environment variable default (which might also be false, or potentially true if defaults change). In the previous implementation (implied by typical CLI parsers), passing --skip-build=false explicitly would disable the flag. However, Option.filter(flag, Boolean) filters out false values, treating Some(false) as None. Then Option.getOrElse returns the environment value. This means if a user explicitly passes false via CLI but the environment variable or default is true, the CLI argument is ignored. While the current defaults for these flags are false, if a user provides an environment variable like T3CODE_DESKTOP_SKIP_BUILD=true and then tries to override it with --skip-build=false on the command line, the false will be filtered out, and it will resolve to true. [ Already posted ]
  • line 234: Similar to the sips issue, the iconutil command in generateMacIconSet injects ${iconsetDir} and ${targetIcns} directly into the shell string without quotes. If the temporary directory path or the target path contains spaces, iconutil will receive malformed arguments and fail. [ Already posted ]
  • line 257: The stageMacIcons function introduces a runtime crash for cross-compilation scenarios. It unconditionally executes the macOS-exclusive command-line tools sips and iconutil whenever the target platform is 'mac', regardless of the host OS. If the script is executed on Linux or Windows (allowed by the CLI platform argument), ChildProcess.spawn will fail with an ENOENT error when attempting to run sips, causing the build to fail. [ Already posted ]
  • line 536: The getDefaultArch function blindly accesses config.archChoices and potentially returns undefined if the array is empty, but getDefaultArch is typed to return a non-undefined BuildArch.Type. While the current static config has non-empty arrays, the function's fallback logic return config.archChoices[0] ?? "x64"; relies on archChoices[0] existing. If archChoices were empty (valid per array type but not per logic), undefined would be returned where a string is expected, potentially causing issues downstream. However, a more immediate issue is in getDefaultArch logic: if process.arch does not match the platform's options (e.g. running on an ARM machine but building for a platform that only supports x64 in PLATFORM_CONFIG), it falls back to config.archChoices[0]. This change forces a specific architecture from PLATFORM_CONFIG which might mismatch the host if process.arch is different, but the more critical runtime crash risk is in buildDesktopArtifact. Specifically, inside buildDesktopArtifact, the code constructs a command string: bunx --bun electron-builder ... --${options.arch}. If getDefaultArch returned a fallback that isn't compatible with the current machine (e.g. trying to build universal or arm64 on a strictly x64 machine without cross-compilation tools set up, or vice versa), electron-builder will fail. But the most specific runtime crash introduced here is related to universal support. The new BuildArch includes universal. If getDefaultArch or the user selects universal, the command becomes ... --universal. Electron-builder supports --universal for macOS (--mac), but if a user (or default logic) selects universal for Linux or Windows (which do not support universal binaries in the same way via that flag), electron-builder will fail at runtime. PLATFORM_CONFIG for mac includes universal, but linux/win do not. However, if a user manually passes --arch universal via CLI for a Windows build, resolveBuildOptions accepts it (as it's in BuildArch literals). buildDesktopArtifact then executes electron-builder ... --universal. This flag is invalid for Windows/Linux in standard electron-builder usage and will cause the subprocess to exit with non-zero code, triggering a BuildScriptError. [ Already posted ]
  • line 536: In resolveBuildOptions, the target resolution uses PLATFORM_CONFIG[platform].defaultTarget as a fallback. The BuildPlatform schema defines mac, linux, win. If detectHostBuildPlatform returns undefined (e.g. on unknown OS) and no platform is provided via CLI/Env, the script errors out early. However, if a platform IS provided, say win, defaultTarget becomes nsis. The issue arises in buildDesktopArtifact where electron-builder is invoked. The code executes: electron-builder ${platformConfig.cliFlag} ${options.target} .... If the user provides a target that is valid for one platform but not the selected one (e.g. platform=win but target=dmg), or if BuildPlatform allows universal arch but the target doesn't support it, electron-builder will crash. Specifically related to the review objects: BuildArch now allows universal. If a user runs build-desktop-artifact --platform win --arch universal, resolveBuildOptions succeeds. buildDesktopArtifact then runs electron-builder --win nsis --universal. Electron builder for Windows does not support --universal (it's a Mac concept). This will cause the build command to fail at runtime. [ Already posted ]
  • line 571: The resolveBuildOptions function will throw a TypeError at runtime when accessing PLATFORM_CONFIG[platform] if platform is undefined. While detectHostBuildPlatform handles darwin/linux/win32, it returns undefined for other platforms (e.g. aix, sunos, freebsd). If the user runs this script on an unsupported platform without providing a platform flag or env var, mergeOptions returns undefined. The subsequent check if (!platform) catches this, preventing the crash. However, there is a subtlety: mergeOptions uses the third argument as a default. If input.platform is None, env.platform is None, and detectHostBuildPlatform returns undefined, then platform becomes undefined. The check if (!platform) correctly handles this. [ Already posted ]