diff --git a/.changeset/rude-bottles-walk.md b/.changeset/rude-bottles-walk.md new file mode 100644 index 00000000000..65509b00269 --- /dev/null +++ b/.changeset/rude-bottles-walk.md @@ -0,0 +1,5 @@ +--- +"dmg-builder": patch +--- + +fix(dmg): use APFS as default filesystem for DMG builds due to incompatibilities on latest MacOS w/ HFS+ diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json index 2eadec7b1cc..41a988dd749 100644 --- a/packages/app-builder-lib/scheme.json +++ b/packages/app-builder-lib/scheme.json @@ -898,6 +898,14 @@ }, "type": "array" }, + "filesystem": { + "default": "APFS", + "description": "The filesystem for the DMG volume (e.g. `\"APFS\"` or `\"HFS+\"`). APFS is the default and recommended on macOS 10.13+.", + "type": [ + "null", + "string" + ] + }, "format": { "default": "UDZO", "description": "The disk image format. `ULFO` (lzfse-compressed image (OS X 10.11+ only)).", diff --git a/packages/app-builder-lib/src/options/macOptions.ts b/packages/app-builder-lib/src/options/macOptions.ts index a8754081ed6..dcf0b8798b2 100644 --- a/packages/app-builder-lib/src/options/macOptions.ts +++ b/packages/app-builder-lib/src/options/macOptions.ts @@ -293,6 +293,12 @@ export interface DmgOptions extends TargetSpecificOptions { */ format?: "UDRW" | "UDRO" | "UDCO" | "UDZO" | "UDBZ" | "ULFO" + /** + * The filesystem for the DMG volume (e.g. `"APFS"` or `"HFS+"`). APFS is the default and recommended on macOS 10.13+. + * @default APFS + */ + readonly filesystem?: string | null + /** * The initial size of the DMG filesystem. Accepts the same syntax as the `-size` argument to `hdiutil`, e.g. `"150m"`, `"4g"`. * If not specified, the size is calculated automatically. diff --git a/packages/dmg-builder/src/dmg.ts b/packages/dmg-builder/src/dmg.ts index 9366636f922..cf84590422c 100644 --- a/packages/dmg-builder/src/dmg.ts +++ b/packages/dmg-builder/src/dmg.ts @@ -159,7 +159,7 @@ export class DmgTarget extends Target { // public to test async computeDmgOptions(appPath: string): Promise { const packager = this.packager - const specification: DmgOptions = { ...this.options } + const specification: DmgOptions = { ...this.options, filesystem: this.options.filesystem ?? "APFS" } if (specification.icon == null && specification.icon !== null) { specification.icon = await packager.getIconPath() } diff --git a/packages/dmg-builder/src/dmgUtil.ts b/packages/dmg-builder/src/dmgUtil.ts index 927aa473f04..07a05c8f97f 100644 --- a/packages/dmg-builder/src/dmgUtil.ts +++ b/packages/dmg-builder/src/dmgUtil.ts @@ -132,7 +132,7 @@ export async function customizeDmg({ appPath, artifactPath, volumeName, specific "text-size": iconTextSize, "compression-level": Number(process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL || "9"), - // filesystem: specification.filesystem || "HFS+", + filesystem: specification.filesystem || "APFS", format: specification.format, size: specification.size, shrink: specification.shrink, diff --git a/packages/electron-publish/src/gitlabPublisher.ts b/packages/electron-publish/src/gitlabPublisher.ts index ceedfa3d84e..ce210a99acf 100644 --- a/packages/electron-publish/src/gitlabPublisher.ts +++ b/packages/electron-publish/src/gitlabPublisher.ts @@ -121,9 +121,7 @@ export class GitlabPublisher extends HttpPublisher { const releaseName = this.releaseName || defaultName const branchName = await this.getDefaultBranch() - const description = this.releaseBody - ? trimStringWithWarn(this.releaseBody, 100000, "release body exceeds GitLab limit, truncating") - : `Release ${releaseName}` + const description = this.releaseBody ? trimStringWithWarn(this.releaseBody, 100000, "release body exceeds GitLab limit, truncating") : `Release ${releaseName}` const releaseData = { tag_name: this.tag, diff --git a/packages/electron-publish/src/util.ts b/packages/electron-publish/src/util.ts index 1d072bdca54..2a1db98a3d8 100644 --- a/packages/electron-publish/src/util.ts +++ b/packages/electron-publish/src/util.ts @@ -6,4 +6,4 @@ export const trimStringWithWarn = (str: string, maxLength: number, warnMessage: } log.warn({ length: str.length, maxLength }, warnMessage) return str.substring(0, maxLength) -} \ No newline at end of file +} diff --git a/test/snapshots/mac/dmgTest.js.snap b/test/snapshots/mac/dmgTest.js.snap index db0ba394b9b..530e550bdfc 100644 --- a/test/snapshots/mac/dmgTest.js.snap +++ b/test/snapshots/mac/dmgTest.js.snap @@ -160,6 +160,7 @@ exports[`dmg > background color 1`] = ` "y": 220, }, ], + "filesystem": "APFS", "format": "UDRO", "title": "Bar", "writeUpdateInfo": false, diff --git a/test/src/mac/dmgTest.ts b/test/src/mac/dmgTest.ts index eb8eb0c8c49..d2a7516b531 100644 --- a/test/src/mac/dmgTest.ts +++ b/test/src/mac/dmgTest.ts @@ -127,9 +127,10 @@ describe.heavy.ifMac("dmg", { sequential: true }, () => { const totalBytes = stats.bsize * stats.blocks // 500m should give ~524,288,000 bytes (500 * 1024 * 1024) - // Allow margin for filesystem overhead (450MB to 600MB) + // Allow margin for filesystem overhead. APFS can report larger sizes than HFS+ due to + // different block sizing and allocation, so use a wide range (450MB–1GB). const minBytes = 450 * 1024 * 1024 - const maxBytes = 600 * 1024 * 1024 + const maxBytes = 1024 * 1024 * 1024 expect(totalBytes).toBeGreaterThan(minBytes) expect(totalBytes).toBeLessThan(maxBytes)