Skip to content

Commit

Permalink
[macOS] Use macapptool for signing and notarizing macOS binaries
Browse files Browse the repository at this point in the history
nw-builder has been producing invalid frameworks at least since
2017, at it seems there's no progress in fixing it (see
nwjs/nw.js#6338). To workaround this problem,
we use macapptool to proper seal all the framework resources so it
can be signed and passes the validations required for notarization.
Since we're introducing this dependency, we can also use macapptool
to simplify signing and notarization.

To create a signed macOS build, pass the --codesign flag.
--codesign-identity can be used to use a non-default identity
("Developer ID")

To notarize a signed bundle, use the --notarize flag. There are
also flags provided to specify the username/password for the
notarization service.
  • Loading branch information
fiam committed Feb 27, 2020
1 parent 75ca721 commit 5e3fd3e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 12 deletions.
16 changes: 16 additions & 0 deletions entitlements.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
66 changes: 54 additions & 12 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,31 @@ function get_task_name(key) {
return 'build-' + key.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();});
}

function getArguments() {
return minimist(process.argv.slice(2));
}

function getPlatforms() {
var defaultPlatforms = ['win32', 'win64', 'osx64', 'linux32', 'linux64'];
var argv = minimist(process.argv.slice(2));
if (argv.platform) {
if (defaultPlatforms.indexOf(argv.platform) < 0) {
throw "Invalid platform '" + argv.platform + "'. Available ones are: " + defaultPlatforms;
const defaultPlatforms = ['win32', 'win64', 'osx64', 'linux32', 'linux64'];
const platform = getArguments().platform;
if (platform) {
if (defaultPlatforms.indexOf(platform) < 0) {
throw new Error(`Invalid platform "${platform}". Available ones are: ${defaultPlatforms}`)
}
return [argv.platform];
return [platform];
}
return defaultPlatforms;
}

function execSync() {
const cmd = arguments[0];
const args = Array.prototype.slice.call(arguments, 1);
const result = child_process.spawnSync(cmd, args, {stdio: 'inherit'});
if (result.error) {
throw result.error;
}
}

// Define build tasks dynamically based on the sources
// and output variables.
var buildCssTasks = [];
Expand Down Expand Up @@ -289,23 +302,52 @@ gulp.task('release-win64', function() {
return archive.finalize();
});

gulp.task('release-osx64', function() {
gulp.task('release-osx64', function(done) {
var pkg = require('./package.json');
var src = path.join(appsDir, pkg.name, 'osx64', pkg.name + '.app');
// Check if we want to sign the .app bundle
if (process.env.CODESIGN_IDENTITY) {
var sign_cmd = 'codesign --verbose --force --sign "' + process.env.CODESIGN_IDENTITY + '" ' + src;
child_process.execSync(sign_cmd);
if (getArguments().codesign) {
// macapptool can be downloaded from
// https://github.com/fiam/macapptool
//
// Make sure the bundle is well formed
execSync('macapptool', '-v', '1', 'fix', src);
// Sign
const codesignArgs = ['macapptool', '-v', '1', 'sign'];
const codesignIdentity = getArguments()['codesign-identity'];
if (codesignIdentity) {
codesignArgs.push('-i', codesignIdentity);
}
codesignArgs.push('-e', 'entitlements.plist');
codesignArgs.push(src)
execSync.apply(this, codesignArgs);
}
var output = fs.createWriteStream(path.join(appsDir, get_release_filename('macOS', 'zip')));
const zipFilename = path.join(appsDir, get_release_filename('macOS', 'zip'));
var output = fs.createWriteStream(zipFilename);
var archive = archiver('zip', {
zlib: { level: 9 }
});
archive.on('warning', function(err) { throw err; });
archive.on('error', function(err) { throw err; });
archive.pipe(output);
archive.directory(src, 'INAV Configurator.app');
return archive.finalize();
output.on('close', function() {
if (getArguments().notarize) {
const notarizeArgs = ['macapptool', '-v', '1', 'notarize'];
const notarizationUsername = getArguments()['notarization-username'];
if (notarizationUsername) {
notarizeArgs.push('-u', notarizationUsername)
}
const notarizationPassword = getArguments()['notarization-password'];
if (notarizationPassword) {
notarizeArgs.push('-p', notarizationPassword)
}
notarizeArgs.push(zipFilename)
execSync.apply(this, notarizeArgs);
}
done();
});
archive.finalize();
});

function releaseLinux(bits) {
Expand Down

0 comments on commit 5e3fd3e

Please sign in to comment.