-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathnotarytool.ts
136 lines (123 loc) · 4.09 KB
/
notarytool.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import debug from 'debug';
import * as path from 'path';
import { spawn } from './spawn';
import { makeSecret, withTempDir } from './helpers';
import {
validateNotaryToolAuthorizationArgs,
isNotaryToolPasswordCredentials,
isNotaryToolApiKeyCredentials,
} from './validate-args';
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)) {
return [
'--apple-id',
makeSecret(opts.appleId),
'--password',
makeSecret(opts.appleIdPassword),
'--team-id',
makeSecret(opts.teamId),
];
} else if (isNotaryToolApiKeyCredentials(opts)) {
return [
'--key',
makeSecret(opts.appleApiKey),
'--key-id',
makeSecret(opts.appleApiKeyId),
'--issuer',
makeSecret(opts.appleApiIssuer),
];
} else {
// --keychain is optional -- when not specified, the iCloud keychain is used by notarytool
if (opts.keychain) {
return ['--keychain', opts.keychain, '--keychain-profile', opts.keychainProfile];
}
return ['--keychain-profile', opts.keychainProfile];
}
}
async function getNotarizationLogs(opts: NotaryToolStartOptions, id: string) {
try {
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(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) {
d('starting notarize process for app:', opts.appPath);
return await withTempDir(async (dir) => {
const fileExt = path.extname(opts.appPath);
let filePath;
if (fileExt === '.dmg' || fileExt === '.pkg') {
filePath = path.resolve(dir, opts.appPath);
d('attempting to upload file to Apple: ', filePath);
} else {
filePath = path.resolve(dir, `${path.parse(opts.appPath).name}.zip`);
d('zipping application to:', filePath);
const zipResult = await spawn(
'ditto',
['-c', '-k', '--sequesterRsrc', '--keepParent', path.basename(opts.appPath), filePath],
{
cwd: path.dirname(opts.appPath),
},
);
if (zipResult.code !== 0) {
throw new Error(
`Failed to zip application, exited with code: ${zipResult.code}\n\n${zipResult.output}`,
);
}
d('zip succeeded, attempting to upload to Apple');
}
const notarizeArgs = [
'submit',
filePath,
...authorizationArgs(opts),
'--wait',
'--output-format',
'json',
];
const result = await runNotaryTool(notarizeArgs, opts.notarytoolPath);
const rawOut = result.output.trim();
let parsed: any;
try {
parsed = JSON.parse(rawOut);
} catch (err) {
throw new Error(
`Failed to notarize via notarytool. Failed with unexpected result: \n\n${rawOut}`,
);
}
let logOutput: undefined | string;
if (typeof parsed.id === 'string') {
logOutput = await getNotarizationLogs(opts, parsed.id);
}
if (result.code === 0 && parsed.status === 'Accepted') {
d(`notarization success (id: ${parsed.id})`);
return;
}
let message = `Failed to notarize via notarytool\n\n${result.output}`;
if (logOutput) {
message += `\n\nDiagnostics from notarytool log: ${logOutput}`;
}
throw new Error(message);
});
}