Skip to content

Commit f855004

Browse files
committed
Trust artifact presence over electron-builder exit status
electron-builder 26.x exits 1 during post-build publish metadata when no publish config is set, even though the .dmg/.exe/.AppImage is already written to disk. Under processx::run this surfaced as misleading "build failed" output next to the real "Successfully built" line. Generated npm scripts now pass --publish never, and build_for_platforms falls back to checking dist/ for platform artifacts when the exit status is non-zero.
1 parent 183f11a commit f855004

2 files changed

Lines changed: 49 additions & 11 deletions

File tree

R/build-package-json.R

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,24 @@ generate_package_json <- function(app_slug, app_version, backend, config,
2020
version = app_version,
2121
description = paste0(app_slug, " - Shiny Electron App"),
2222
main = "main.js",
23+
# --publish never suppresses electron-builder's publish pipeline, which
24+
# 26.x crashes in ("Cannot read properties of null (reading 'channel')")
25+
# whenever the package.json has no publish or repository config. Local
26+
# builds never want publishing anyway; CI pipelines override with
27+
# --publish always.
2328
scripts = list(
2429
electron = "electron .",
25-
build = "electron-builder",
26-
`build-all` = "electron-builder -mwl",
27-
`build-win` = "electron-builder --win",
28-
`build-mac` = "electron-builder --mac",
29-
`build-linux` = "electron-builder --linux",
30-
`build-win-x64` = "electron-builder --win --x64",
31-
`build-win-arm64` = "electron-builder --win --arm64",
32-
`build-mac-x64` = "electron-builder --mac --x64",
33-
`build-mac-arm64` = "electron-builder --mac --arm64",
34-
`build-linux-x64` = "electron-builder --linux --x64",
35-
`build-linux-arm64` = "electron-builder --linux --arm64"
30+
build = "electron-builder --publish never",
31+
`build-all` = "electron-builder -mwl --publish never",
32+
`build-win` = "electron-builder --win --publish never",
33+
`build-mac` = "electron-builder --mac --publish never",
34+
`build-linux` = "electron-builder --linux --publish never",
35+
`build-win-x64` = "electron-builder --win --x64 --publish never",
36+
`build-win-arm64` = "electron-builder --win --arm64 --publish never",
37+
`build-mac-x64` = "electron-builder --mac --x64 --publish never",
38+
`build-mac-arm64` = "electron-builder --mac --arm64 --publish never",
39+
`build-linux-x64` = "electron-builder --linux --x64 --publish never",
40+
`build-linux-arm64` = "electron-builder --linux --arm64 --publish never"
3641
),
3742
author = "",
3843
license = "AGPL (>=3)",

R/build-steps.R

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,32 @@ install_npm_dependencies <- function(output_dir, verbose = TRUE) {
4848
#' @param arch Character vector of target architectures
4949
#' @param verbose Logical whether to show progress
5050
#' @keywords internal
51+
#' Check whether electron-builder produced output for a platform.
52+
#'
53+
#' electron-builder 26.x has a known bug where the build completes and the
54+
#' installer is written to disk, but the process then exits with status 1
55+
#' during post-build publish metadata. When that happens, processx-invoked
56+
#' npm inherits the non-zero exit even though the .dmg/.exe/.AppImage is
57+
#' sitting right there. We treat "artifact exists" as success.
58+
#' @keywords internal
59+
dist_has_platform_artifact <- function(output_dir, p) {
60+
dist_dir <- fs::path(output_dir, "dist")
61+
if (!fs::dir_exists(dist_dir)) return(FALSE)
62+
63+
# Platform-specific installer extensions
64+
patterns <- switch(p,
65+
mac = c("\\.dmg$", "\\.zip$", "^mac(-arm64|-x64)?$"),
66+
win = c("\\.exe$", "\\.msi$", "^win(-arm64|-x64|-unpacked)?$"),
67+
linux = c("\\.AppImage$", "\\.deb$", "\\.rpm$", "\\.snap$", "^linux(-arm64|-x64|-unpacked)?$"),
68+
character(0)
69+
)
70+
if (length(patterns) == 0) return(FALSE)
71+
72+
entries <- list.files(dist_dir, recursive = FALSE)
73+
any(vapply(patterns, function(pat) any(grepl(pat, entries, ignore.case = TRUE)),
74+
logical(1)))
75+
}
76+
5177
build_for_platforms <- function(output_dir, platform, arch, sign = FALSE, verbose = TRUE) {
5278
if (verbose) {
5379
cli::cli_alert_info("Building for platforms: {paste(platform, collapse = ', ')}")
@@ -121,6 +147,11 @@ build_for_platforms <- function(output_dir, platform, arch, sign = FALSE, verbos
121147
if (result$status == 0) {
122148
if (verbose) cli::cli_alert_success("Built for {target}")
123149
next
150+
} else if (dist_has_platform_artifact(output_dir, p)) {
151+
# electron-builder 26.x exits 1 during post-build publish metadata
152+
# even after the installer is written. Artifact exists => success.
153+
if (verbose) cli::cli_alert_success("Built for {target}")
154+
next
124155
} else {
125156
if (verbose) cli::cli_alert_warning("Specific script {build_script} failed: {result$stderr}")
126157
}
@@ -162,6 +193,8 @@ build_for_platforms <- function(output_dir, platform, arch, sign = FALSE, verbos
162193

163194
if (fallback_result$status == 0) {
164195
cli::cli_alert_success("Built for {p} (fallback - may include multiple architectures)")
196+
} else if (dist_has_platform_artifact(output_dir, p)) {
197+
cli::cli_alert_success("Built for {p} (fallback - may include multiple architectures)")
165198
} else {
166199
cli::cli_alert_warning("Fallback build also failed for {p}: {fallback_result$stderr}")
167200
}

0 commit comments

Comments
 (0)