Skip to content

refactor: build via electron-builder's programmatic API instead of the CLI#647

Merged
cwillisf merged 1 commit into
developfrom
feature/electron-builder-programmatic-api
Jun 9, 2026
Merged

refactor: build via electron-builder's programmatic API instead of the CLI#647
cwillisf merged 1 commit into
developfrom
feature/electron-builder-programmatic-api

Conversation

@cwillisf

@cwillisf cwillisf commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Resolves

Addresses an issue raised in review of #635 regarding the use of shell: true.

Proposed Changes

Replaces the spawnSync('electron-builder', ..., { shell: true }) invocation in
scripts/electron-builder-wrapper.js with a direct call to electron-builder's documented programmatic
build() API. Build options are passed as a structured object that electron-builder deep-merges over
electron-builder.yaml, instead of shell-quoted --c.x.y=value CLI flags.

Also in this change:

  • Target lists are passed under the platform key (win/mac/linux), not as a targets Map, so
    electron-builder's own option normalization still parses the type:arch suffixes and applies the
    dir/universal/identity handling. Passing a targets Map would short-circuit that and force us to
    reimplement it.
  • Because the build now runs in-process, CSC stripping removes those vars from process.env for the
    duration of the build and restores them after, rather than handing a child process a filtered env.
  • Target descriptors hold real arrays instead of space-joined strings that had to be re-split.
  • Sets publish: 'never' explicitly.

Reason for Changes

shell: true re-tokenizes the command line, so every config value containing a space (the
azureSignOptions publisherName, the appx CN= publisher) had to be manually double-quoted to survive
shell splitting, and Node warns about the unescaped concatenation (DEP0190). Passing options as a
structured object removes the shell and the quoting entirely.

publish: 'never' is set because we configure no publish providers and collect releases from the build
artifacts by hand, but electron-builder was inferring a publish policy from CI detection and warning
that the implicit behavior will be dropped in a future major.

Test Coverage

The build wrapper has no automated tests; npm run test:lint is the repo's only check. Validated by:

  • npm run test:lint (0 errors) and node --check.
  • ci.yml on push exercises the unsigned path: macOS dmg and Windows nsis-x64 through the new API.
  • Not covered by push CI: the signed multi-target path (the installers pass plus azureSignOptions,
    and the appx pass), which runs only in release-candidate.yml (workflow_dispatch, Azure
    credentials). A release-candidate dispatch is recommended before merge.

@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 20:20 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 20:20 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 20:20 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 20:20 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 20:20 — with GitHub Actions Inactive
@cwillisf cwillisf marked this pull request as ready for review June 9, 2026 20:36
@cwillisf cwillisf requested a review from Copilot June 9, 2026 20:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the Electron build wrapper to invoke electron-builder via its programmatic build() API (instead of spawning the CLI with shell: true), eliminating shell tokenization/quoting issues and enabling structured config overrides.

Changes:

  • Replaces spawnSync('electron-builder', …, {shell: true}) with an in-process electron-builder.build(options) call.
  • Passes build targets as arrays and supplies config overrides via an object (including publish: 'never' and Azure signing options when enabled).
  • Updates signing behavior to strip/restore CSC-related variables from process.env during unsigned/AppX passes, and makes the wrapper execution async/serial.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/electron-builder-wrapper.js
Comment thread scripts/electron-builder-wrapper.js Outdated
@cwillisf cwillisf force-pushed the feature/electron-builder-programmatic-api branch from 399c957 to e474b1c Compare June 9, 2026 20:46
@cwillisf cwillisf requested a review from Copilot June 9, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread scripts/electron-builder-wrapper.js
…e CLI

The wrapper spawned `electron-builder` through `spawnSync(shell: true)`,
which re-tokenizes the command line — so every config value containing a
space (the azureSignOptions publisherName, the appx `CN=` publisher) had to
be manually double-quoted to survive shell splitting, and Node warns about
the unescaped concatenation (DEP0190).

Call the documented `build()` API directly instead. Options are passed as a
structured object that electron-builder deep-merges over
electron-builder.yaml, so there is no shell and no quoting to get wrong.
Target lists go under the platform key (win/mac/linux) rather than as a
`targets` Map, so electron-builder's own option normalization still parses
the `type:arch` suffixes and applies the dir/universal/identity handling
instead of us reimplementing it.

Because the build now runs in-process, CSC stripping removes the vars from
process.env (which electron-builder reads directly) for the duration of the
build and restores them after. Target descriptors hold real arrays instead
of space-joined strings that had to be re-split.

Set `publish: 'never'` explicitly. electron-builder.yaml configures no
publish providers and releases are collected from the build artifacts by
hand, but electron-builder still inferred a publish policy from CI detection
and warned that the implicit behavior will be dropped in a future major.
@cwillisf cwillisf force-pushed the feature/electron-builder-programmatic-api branch from e474b1c to b73675b Compare June 9, 2026 21:20
@cwillisf cwillisf requested a review from Copilot June 9, 2026 21:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comment thread scripts/electron-builder-wrapper.js
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 21:29 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 21:29 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 21:29 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 21:29 — with GitHub Actions Inactive
@cwillisf cwillisf temporarily deployed to release-candidate June 9, 2026 21:29 — with GitHub Actions Inactive
@cwillisf cwillisf merged commit cc936a5 into develop Jun 9, 2026
9 checks passed
@cwillisf cwillisf deleted the feature/electron-builder-programmatic-api branch June 9, 2026 21:41
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants