electron-notarize
Advanced tools
Comparing version 0.0.0 to 0.0.1
{ | ||
"name": "electron-notarize", | ||
"version": "0.0.0", | ||
"version": "0.0.1", | ||
"description": "Notarize your Electron app", | ||
"main": "src/index.js", | ||
"author": "Samuel Attard", | ||
"license": "MIT" | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "tsc", | ||
"lint": "tslint --project .", | ||
"prepublish": "yarn build" | ||
}, | ||
"devDependencies": { | ||
"@types/debug": "^0.0.31", | ||
"@types/fs-extra": "^5.0.4", | ||
"electron": "^3.0.5", | ||
"tslint": "^5.11.0", | ||
"tslint-config-airbnb": "^5.11.0", | ||
"typescript": "^3.1.3" | ||
}, | ||
"dependencies": { | ||
"debug": "^4.1.0", | ||
"fs-extra": "^7.0.0" | ||
} | ||
} |
130
src/index.ts
@@ -0,3 +1,9 @@ | ||
import * as debug from 'debug'; | ||
import * as path from 'path'; | ||
import { spawn } from './spawn'; | ||
import { withTempDir, makeSecret, parseNotarizationInfo } from './helpers'; | ||
const d = debug('electron-notarize'); | ||
export interface NotarizeCredentials { | ||
@@ -9,3 +15,3 @@ appleId: string; | ||
export interface NotarizeAppOptions { | ||
dmgPath: string; | ||
appPath: string; | ||
appBundleId: string; | ||
@@ -20,28 +26,124 @@ } | ||
export type NotarizeWaitOptions = NotarizeResult & NotarizeCredentials; | ||
export type NotarizeStapleOptions = Pick<NotarizeAppOptions, 'dmgPath'> | ||
export type NotarizeStapleOptions = Pick<NotarizeAppOptions, 'appPath'>; | ||
async function startNotarize(opts: NotarizeStartOptions): Promise<NotarizeResult> { | ||
await spawn( | ||
export async function startNotarize(opts: NotarizeStartOptions): Promise<NotarizeResult> { | ||
d('starting notarize process for app:', opts.appPath); | ||
return await withTempDir<NotarizeResult>(async (dir) => { | ||
const zipPath = path.resolve(dir, `${path.basename(opts.appleIdPassword, '.app')}.zip`); | ||
d('zipping application to:', zipPath); | ||
const zipResult = await spawn( | ||
'zip', | ||
[ | ||
'-r', | ||
'-y', | ||
zipPath, | ||
path.basename(opts.appPath), | ||
], | ||
{ | ||
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 result = await spawn( | ||
'xcrun', | ||
[ | ||
'altool', | ||
'--notarize-app', | ||
'-f', | ||
zipPath, | ||
'--primary-bundle-id', | ||
opts.appBundleId, | ||
'-u', | ||
makeSecret(opts.appleId), | ||
'-p', | ||
makeSecret(opts.appleIdPassword), | ||
], | ||
); | ||
if (result.code !== 0) { | ||
throw new Error(`Failed to upload app to Apples notarization servers\n\n${result.output}`); | ||
} | ||
d('upload success'); | ||
const uuidMatch = /\nRequestUUID = (.+?)\n/g.exec(result.output); | ||
if (!uuidMatch) { | ||
throw new Error(`Failed to find request UUID in output:\n\n${result.output}`); | ||
} | ||
d('found UUID:', uuidMatch[1]); | ||
return { | ||
uuid: uuidMatch[1], | ||
}; | ||
}); | ||
} | ||
export async function waitForNotarize(opts: NotarizeWaitOptions): Promise<void> { | ||
d('checking notarization status:', opts.uuid); | ||
const result = await spawn( | ||
'xcrun', | ||
[ | ||
'altool', | ||
'--notarize-app', | ||
'-f', | ||
opts.dmgPath, | ||
'--primary-bundle-id', | ||
opts.appBundleId, | ||
'--notarization-info', | ||
opts.uuid, | ||
'-u', | ||
opts.appleId, | ||
makeSecret(opts.appleId), | ||
'-p', | ||
opts.appleIdPassword, | ||
makeSecret(opts.appleIdPassword), | ||
], | ||
); | ||
} | ||
if (result.code !== 0) { | ||
throw new Error(`Failed to check status of notarization request: ${opts.uuid}\n\n${result.output}`); | ||
} | ||
const notarizationInfo = parseNotarizationInfo(result.output); | ||
async function waitForNotarize(opts: NotarizeWaitOptions): Promise<void> { | ||
if (notarizationInfo.status === 'in progress') { | ||
d('still in progress, waiting 30 seconds'); | ||
await new Promise(r => setTimeout(r, 30000)); | ||
return waitForNotarize(opts); | ||
} | ||
d('notarzation done with info:', notarizationInfo); | ||
if (notarizationInfo.status === 'invalid') { | ||
d('notarization failed'); | ||
throw new Error(`Apple failed to notarize your application, check the logs for more info | ||
Status Code: ${notarizationInfo.statusCode || 'No Code'} | ||
Message: ${notarizationInfo.statusMessage || 'No Message'} | ||
Logs: ${notarizationInfo.logFileUrl}`); | ||
} | ||
if (notarizationInfo.status !== 'success') { | ||
throw new Error(`Unrecognized notarization status: "${notarizationInfo.status}"`); | ||
} | ||
d('notarization was successful'); | ||
return; | ||
} | ||
async function stapleDMG(opts: NotarizeStapleOptions): Promise<void> { | ||
export async function stapleApp(opts: NotarizeStapleOptions): Promise<void> { | ||
d('attempting to staple app:', opts.appPath); | ||
const result = await spawn( | ||
'xcrun', | ||
[ | ||
'stapler', | ||
'staple', | ||
'-v', | ||
path.basename(opts.appPath), | ||
], | ||
{ | ||
cwd: path.dirname(opts.appPath), | ||
}, | ||
); | ||
if (result.code !== 0) { | ||
throw new Error(`Failed to staple your application with code: ${result.code}\n\n${result.output}`); | ||
} | ||
d('staple succeeded'); | ||
return; | ||
} |
import { spawn as cpSpawn, SpawnOptions } from 'child_process'; | ||
import * as debug from 'debug'; | ||
import { isSecret } from './helpers'; | ||
const d = debug('electron-notarize:spawn'); | ||
export interface SpawnResult { | ||
@@ -9,2 +13,3 @@ code: number; | ||
export const spawn = (cmd: string, args: string[] = [], opts: SpawnOptions = {}): Promise<SpawnResult> => { | ||
d('spawning cmd:', cmd, 'args:', args.map(arg => isSecret(arg) ? '*********' : arg), 'opts:', opts); | ||
const child = cpSpawn(cmd, args, opts); | ||
@@ -17,2 +22,3 @@ const out: string[] = []; | ||
child.on('exit', (code) => { | ||
d(`cmd ${cmd} terminated with code: ${code}`); | ||
resolve({ | ||
@@ -19,0 +25,0 @@ code, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
60933
12
432
2
6
2
2
+ Addeddebug@^4.1.0
+ Addedfs-extra@^7.0.0
+ Addeddebug@4.3.7(transitive)
+ Addedfs-extra@7.0.1(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedjsonfile@4.0.0(transitive)
+ Addedms@2.1.3(transitive)
+ Addeduniversalify@0.1.2(transitive)