Skip to content

Commit

Permalink
feat: allow notarization on macOS versions down to 10.15 (#201)
Browse files Browse the repository at this point in the history
* notarytoolPath option

* Removed NotaryToolOptions interface

* Update README.md

Co-authored-by: Erick Zhao <[email protected]>

* Removed unnecessary typeof uses

---------

Co-authored-by: Erick Zhao <[email protected]>
  • Loading branch information
pjaspinski and erickzhao authored Sep 17, 2024
1 parent 4ac5fba commit 268fa30
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ For notarization, you need the following things:
> If you are using Electron 11 or below, you must add the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement too.
> When using version 12+, this entitlement should not be applied as it increases your app's attack surface.
### Notarization on older macOS versions

Xcode 13 is available from macOS 11.3, but notarization can be performed on systems down to macOS 10.15
(see [TN3147](https://developer.apple.com/documentation/technotes/tn3147-migrating-to-the-latest-notarization-tool#Enable-notarization-on-an-older-version-of-macOS) for more information).

To achieve this, you can copy notarytool binary from a newer macOS version and provide its path as `notarytoolPath` option.

## API

`@electron/notarize` exposes a single `notarize` function that accepts the following parameters:
* `appPath` — the absolute path to your codesigned and packaged Electron application.
* `notarytoolPath` - String (optional) - Path of the notarytool binary ([more details](#notarization-on-older-macos-versions))
* additional options required for authenticating your Apple ID (see below)

The method returns a void Promise once app notarization is complete. Please note that notarization may take
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ async function notarize({ appPath, ...otherOptions }: NotarizeOptions) {

d('notarizing using notarytool');
if (!(await isNotaryToolAvailable())) {
throw new Error('notarytool is not available, you must be on at least Xcode 13');
throw new Error(
'notarytool is not available, you must be on at least Xcode 13 or provide notarytoolPath',
);
}

await notarizeAndWaitForNotaryTool({
Expand Down
25 changes: 19 additions & 6 deletions src/notarytool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import { NotaryToolCredentials, NotaryToolStartOptions } from './types';

const d = debug('electron-notarize:notarytool');

function runNotaryTool(args: string[], notarytoolPath?: string) {
const useXcrun = notarytoolPath === undefined;
const cmd = useXcrun ? 'xcrun' : notarytoolPath;
return spawn(cmd, useXcrun ? ['notarytool', ...args] : args);
}

function authorizationArgs(rawOpts: NotaryToolCredentials): string[] {
const opts = validateNotaryToolAuthorizationArgs(rawOpts);
if (isNotaryToolPasswordCredentials(opts)) {
Expand Down Expand Up @@ -43,17 +49,25 @@ function authorizationArgs(rawOpts: NotaryToolCredentials): string[] {

async function getNotarizationLogs(opts: NotaryToolStartOptions, id: string) {
try {
const logResult = await spawn('xcrun', ['notarytool', 'log', id, ...authorizationArgs(opts)]);
const logResult = await runNotaryTool(
['log', id, ...authorizationArgs(opts)],
opts.notarytoolPath,
);
d('notarization log', logResult.output);
return logResult.output;
} catch (e) {
d('failed to pull notarization logs', e);
}
}

export async function isNotaryToolAvailable() {
const result = await spawn('xcrun', ['--find', 'notarytool']);
return result.code === 0;
export async function isNotaryToolAvailable(notarytoolPath?: string) {
if (notarytoolPath !== undefined) {
const result = await spawn(notarytoolPath, ['--version']);
return result.code === 0;
} else {
const result = await spawn('xcrun', ['--find', 'notarytool']);
return result.code === 0;
}
}

export async function notarizeAndWaitForNotaryTool(opts: NotaryToolStartOptions) {
Expand Down Expand Up @@ -83,7 +97,6 @@ export async function notarizeAndWaitForNotaryTool(opts: NotaryToolStartOptions)
}

const notarizeArgs = [
'notarytool',
'submit',
filePath,
...authorizationArgs(opts),
Expand All @@ -92,7 +105,7 @@ export async function notarizeAndWaitForNotaryTool(opts: NotaryToolStartOptions)
'json',
];

const result = await spawn('xcrun', notarizeArgs);
const result = await runNotaryTool(notarizeArgs, opts.notarytoolPath);
const rawOut = result.output.trim();

let parsed: any;
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export interface NotaryToolNotarizeAppOptions {
* Absolute path to your packaged and codesigned Electron application.
*/
appPath: string;
notarytoolPath?: string;
}

/**
Expand Down

0 comments on commit 268fa30

Please sign in to comment.