diff --git a/.changeset/fresh-poems-greet.md b/.changeset/fresh-poems-greet.md new file mode 100644 index 0000000000..19ad40585e --- /dev/null +++ b/.changeset/fresh-poems-greet.md @@ -0,0 +1,6 @@ +--- +"app-builder-lib": minor +"electron-builder": minor +--- + +mac: Support for a custom 'sign' action diff --git a/docs/configuration/mac.md b/docs/configuration/mac.md index bbdca05228..6ca24cfbc6 100644 --- a/docs/configuration/mac.md +++ b/docs/configuration/mac.md @@ -92,6 +92,9 @@ The top-level [mac](configuration.md#Configuration-mac) key contains set of opti

signIgnore Array<String> | String | “undefined” - Regex or an array of regex’s that signal skipping signing a file.

  • +

    sign module:app-builder-lib/out/macPackager.__type | String | “undefined” - The custom function (or path to file or module id) to sign an app bundle.

    +
  • +
  • timestamp String | “undefined” - Specify the URL of the timestamp authority server

  • diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json index de502df940..441adba73d 100644 --- a/packages/app-builder-lib/scheme.json +++ b/packages/app-builder-lib/scheme.json @@ -2787,6 +2787,20 @@ "string" ] }, + "sign": { + "anyOf": [ + { + "typeof": "function" + }, + { + "type": [ + "null", + "string" + ] + } + ], + "description": "The custom function (or path to file or module id) to sign an app bundle." + }, "signIgnore": { "anyOf": [ { @@ -3420,6 +3434,20 @@ "string" ] }, + "sign": { + "anyOf": [ + { + "typeof": "function" + }, + { + "type": [ + "null", + "string" + ] + } + ], + "description": "The custom function (or path to file or module id) to sign an app bundle." + }, "signIgnore": { "anyOf": [ { diff --git a/packages/app-builder-lib/src/index.ts b/packages/app-builder-lib/src/index.ts index 1f03ee50bf..c43805afee 100644 --- a/packages/app-builder-lib/src/index.ts +++ b/packages/app-builder-lib/src/index.ts @@ -39,6 +39,7 @@ export { SnapOptions, PlugDescriptor, SlotDescriptor } from "./options/SnapOptio export { Metadata, AuthorMetadata, RepositoryInfo } from "./options/metadata" export { AppInfo } from "./appInfo" export { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions" +export { CustomMacSign, CustomMacSignOptions } from "./macPackager" export { WindowsSignOptions, CustomWindowsSignTaskConfiguration, diff --git a/packages/app-builder-lib/src/macPackager.ts b/packages/app-builder-lib/src/macPackager.ts index 8124d9b686..04844a909e 100644 --- a/packages/app-builder-lib/src/macPackager.ts +++ b/packages/app-builder-lib/src/macPackager.ts @@ -13,7 +13,7 @@ import { DIR_TARGET, Platform, Target } from "./core" import { AfterPackContext, ElectronPlatformName } from "./index" import { MacConfiguration, MasConfiguration, NotarizeLegacyOptions, NotarizeNotaryOptions } from "./options/macOptions" import { Packager } from "./packager" -import { chooseNotNull, PlatformPackager } from "./platformPackager" +import { chooseNotNull, resolveFunction, PlatformPackager } from "./platformPackager" import { ArchiveTarget } from "./targets/ArchiveTarget" import { PkgTarget, prepareProductBuildArgs } from "./targets/pkg" import { createCommonTarget, NoOpTarget } from "./targets/targetFactory" @@ -23,6 +23,9 @@ import * as fs from "fs/promises" import { notarize, NotarizeOptions } from "@electron/notarize" import { LegacyNotarizePasswordCredentials, LegacyNotarizeStartOptions, NotaryToolStartOptions, NotaryToolCredentials } from "@electron/notarize/lib/types" +export type CustomMacSignOptions = SignOptions +export type CustomMacSign = (configuration: CustomMacSignOptions, packager: MacPackager) => Promise + export default class MacPackager extends PlatformPackager { readonly codeSigningInfo = new Lazy(() => { const cscLink = this.getCscLink() @@ -231,7 +234,7 @@ export default class MacPackager extends PlatformPackager { } } - if (identity == null) { + if (!options.sign && identity == null) { await reportError(isMas, certificateTypes, qualifier, keychainFile, this.forceCodeSigning) return false } @@ -263,9 +266,9 @@ export default class MacPackager extends PlatformPackager { return path.resolve(appPath, destination) }) ) - log.info("Signing addtional user-defined binaries: " + JSON.stringify(binaries, null, 1)) + log.info({ binaries }, "signing additional user-defined binaries") } - const customSignOptions = (isMas ? masOptions : this.platformSpecificBuildOptions) || this.platformSpecificBuildOptions + const customSignOptions: MasConfiguration | MacConfiguration = (isMas ? masOptions : this.platformSpecificBuildOptions) || this.platformSpecificBuildOptions const signOptions: SignOptions = { identityValidation: false, @@ -306,16 +309,7 @@ export default class MacPackager extends PlatformPackager { provisioningProfile: customSignOptions.provisioningProfile || undefined, } - log.info( - { - file: log.filePath(appPath), - identityName: identity.name, - identityHash: identity.hash, - provisioningProfile: signOptions.provisioningProfile || "none", - }, - "signing" - ) - await this.doSign(signOptions) + await this.doSign(signOptions, customSignOptions) // https://github.com/electron-userland/electron-builder/issues/1196#issuecomment-312310209 if (masOptions != null && !isDevelopment) { @@ -393,8 +387,22 @@ export default class MacPackager extends PlatformPackager { } //noinspection JSMethodCanBeStatic - protected doSign(opts: SignOptions): Promise { - return signAsync(opts) + protected async doSign(opts: SignOptions, customSignOptions: MacConfiguration): Promise { + const customSign = await resolveFunction(this.appInfo.type, customSignOptions.sign, "sign") + + const { app, platform, type, identity, provisioningProfile } = opts + log.info( + { + file: log.filePath(app), + platform, + type, + identity: identity || "none", + provisioningProfile: provisioningProfile || "none", + }, + customSign ? "executing custom sign" : "signing" + ) + + return customSign ? Promise.resolve(customSign(opts, this)) : signAsync(opts) } //noinspection JSMethodCanBeStatic diff --git a/packages/app-builder-lib/src/options/macOptions.ts b/packages/app-builder-lib/src/options/macOptions.ts index 191c6722f2..91548eb9d4 100644 --- a/packages/app-builder-lib/src/options/macOptions.ts +++ b/packages/app-builder-lib/src/options/macOptions.ts @@ -1,4 +1,5 @@ import { PlatformSpecificBuildOptions, TargetConfiguration, TargetSpecificOptions } from "../index" +import { CustomMacSign } from "../macPackager" export type MacOsTargetName = "default" | "dmg" | "mas" | "mas-dev" | "pkg" | "7z" | "zip" | "tar.xz" | "tar.lz" | "tar.gz" | "tar.bz2" | "dir" @@ -175,6 +176,11 @@ export interface MacConfiguration extends PlatformSpecificBuildOptions { */ readonly signIgnore?: Array | string | null + /** + * The custom function (or path to file or module id) to sign an app bundle. + */ + readonly sign?: CustomMacSign | string | null + /** * Specify the URL of the timestamp authority server */