11var path = require ( 'path' ) ;
22var pkg = require ( path . resolve ( __dirname , '../package.json' ) ) ;
33var fs = require ( 'fs' ) ;
4- var cp = require ( 'child_process' ) ;
4+ var run = require ( './run' ) ;
5+ var format = require ( 'util' ) . format ;
6+ var chalk = require ( 'chalk' ) ;
7+ var figures = require ( 'figures' ) ;
58var series = require ( 'run-series' ) ;
69var _ = require ( 'lodash' ) ;
10+ var packager = require ( 'electron-packager' ) ;
11+ var createDMG = require ( 'electron-installer-dmg' ) ;
712
813var debug = require ( 'debug' ) ( 'scout:tasks:darwin' ) ;
914
1015var NAME = pkg . product_name ;
1116var PACKAGE = path . join ( 'dist' , NAME + '-darwin-x64' ) ;
1217var APP_PATH = path . join ( PACKAGE , NAME + '.app' ) ;
1318
14- var packager = require ( 'electron-packager' ) ;
15- var createDMG = require ( 'electron-installer-dmg' ) ;
16-
1719module . exports . ELECTRON = path . join ( APP_PATH , 'Contents' , 'MacOS' , 'Electron' ) ;
1820module . exports . RESOURCES = path . join ( APP_PATH , 'Contents' , 'Resources' ) ;
1921
@@ -29,7 +31,6 @@ var PACKAGER_CONFIG = {
2931 prune : true ,
3032 'app-bundle-id' : 'com.mongodb.compass' ,
3133 'app-version' : pkg . version ,
32- sign : '90E39AA7832E95369F0FC6DAF823A04DFBD9CF7A' ,
3334 protocols : [
3435 {
3536 name : 'MongoDB Prototcol' ,
@@ -38,11 +39,6 @@ var PACKAGER_CONFIG = {
3839 ]
3940} ;
4041
41- // Adjust config via environment variables
42- if ( process . env . SCOUT_INSTALLER_UNSIGNED !== undefined ) {
43- PACKAGER_CONFIG . sign = null ;
44- }
45-
4642// @todo (imlucas): Standardize `electron-installer-dmg`
4743// options w/ `electron-installer-squirrel-windows`.
4844var INSTALLER_CONFIG = {
@@ -69,39 +65,127 @@ var INSTALLER_CONFIG = {
6965 ]
7066} ;
7167
72- module . exports . build = function ( done ) {
73- fs . exists ( APP_PATH , function ( exists ) {
74- if ( exists ) {
75- debug ( '.app already exists. skipping packager run.' ) ;
76- return done ( ) ;
68+ var CODESIGN_IDENTITY_COMMON_NAME = 'Developer ID Application: Matt Kangas (ZD3CL9MT3L)' ;
69+ var CODESIGN_IDENTITY_SHA1 = '90E39AA7832E95369F0FC6DAF823A04DFBD9CF7A' ;
70+
71+ /**
72+ * Checks if the current environment can actually sign builds.
73+ * If signing can be done, `electron-packager`'s config will
74+ * be updated to sign artifacts. If not, gracefully degrade
75+ *
76+ * @param {Function } fn - Callback.
77+ */
78+ function addCodesignIdentityIfAvailable ( fn ) {
79+ run ( 'certtool' , [ 'y' ] , function ( err , output ) {
80+ if ( err ) {
81+ debug ( 'Failed to list certificates. Build will not be signed.' ) ;
82+ fn ( ) ;
83+ return ;
7784 }
78- debug ( 'running packager to create electron binaries...' ) ;
79- packager ( PACKAGER_CONFIG , done ) ;
85+ if ( output . indexOf ( CODESIGN_IDENTITY_COMMON_NAME ) === - 1 ) {
86+ debug ( 'Signing identity `%s` not detected. Build will not be signed.' ,
87+ CODESIGN_IDENTITY_COMMON_NAME ) ;
88+ fn ( ) ;
89+ return ;
90+ }
91+
92+ PACKAGER_CONFIG . sign = CODESIGN_IDENTITY_SHA1 ;
93+ debug ( 'The signing identity `%s` is available! '
94+ + 'This build will be signed!' , CODESIGN_IDENTITY_COMMON_NAME ) ;
95+
96+ console . log ( chalk . green . bold ( figures . tick ) ,
97+ format ( ' This build will be signed using the `%s` signing identity' ,
98+ CODESIGN_IDENTITY_COMMON_NAME ) ) ;
99+ fn ( ) ;
80100 } ) ;
81- } ;
101+ }
102+
103+ module . exports . build = function ( done ) {
104+ addCodesignIdentityIfAvailable ( function ( err ) {
105+ if ( err ) return done ( err ) ;
82106
83- var verify = function ( done ) {
84- var cmd = 'codesign --verify "' + APP_PATH + '"' ;
85- debug ( 'Verifying `%s` has been signed...' , APP_PATH ) ;
86- cp . exec ( cmd , done ) ;
107+ fs . exists ( APP_PATH , function ( exists ) {
108+ if ( exists && process . env . NODE_ENV !== 'production' ) {
109+ debug ( '.app already exists. skipping packager run.' ) ;
110+ return done ( ) ;
111+ }
112+ debug ( 'running electron-packager...' ) ;
113+ packager ( PACKAGER_CONFIG , done ) ;
114+ } ) ;
115+ } ) ;
87116} ;
88117
89- module . exports . installer = function ( done ) {
90- debug ( 'creating installer...' ) ;
118+ /**
119+ * If the app is supposed to be signed, verify that
120+ * the signing was actually completed correctly.
121+ * If signing is not available, print helpful details
122+ * on working with unsigned builds.
123+ *
124+ * @param {Function } done - Callback which receives `(err)`.
125+ */
126+ function verify ( done ) {
127+ if ( ! PACKAGER_CONFIG . sign ) {
128+ console . error ( chalk . yellow . bold ( figures . warning ) ,
129+ ' User confusion ahead!' ) ;
91130
92- var tasks = [ ] ;
93- if ( PACKAGER_CONFIG . sign ) {
94- tasks . push ( verify ) ;
131+ console . error ( chalk . gray (
132+ ' The default preferences for OSX Gatekeeper will not' ,
133+ 'allow users to run unsigned applications.' ) ) ;
134+
135+ console . error ( chalk . gray (
136+ ' However, we\'re going to continue building' ,
137+ 'the app and an installer because you\'re most likely' ) ) ;
138+
139+ console . error ( chalk . gray (
140+ ' a developer trying to test' ,
141+ 'the app\'s installation process.' ) ) ;
142+
143+ console . error ( chalk . gray (
144+ ' For more information on OSX Gatekeeper and how to change your' ,
145+ 'system preferences to run unsigned applications,' ) ) ;
146+ console . error ( chalk . gray ( ' please see' ,
147+ 'https://support.apple.com/en-us/HT202491' ) ) ;
148+ debug ( 'Build is not signed. Skipping codesign verification.' ) ;
149+ process . nextTick ( done ) ;
150+ return ;
95151 }
96152
97- tasks . push ( _ . partial ( createDMG , INSTALLER_CONFIG ) ) ;
153+ debug ( 'Verifying `%s` has been signed correctly...' , APP_PATH ) ;
154+ run ( 'codesign' , [ '--verify' , APP_PATH ] , function ( err ) {
155+ if ( err ) {
156+ err = new Error ( 'App is not correctly signed' ) ;
157+ done ( err ) ;
158+ return ;
159+ }
160+ debug ( 'Verified that the app has been signed correctly!' ) ;
161+ done ( ) ;
162+ } ) ;
163+ }
164+
165+ /**
166+ * Package the application as a single `.DMG` file which
167+ * is the OSX equivalent of a `Setup.exe` installer.
168+ *
169+ * @param {Function } done - Callback which receives `(err)`.
170+ */
171+ module . exports . installer = function ( done ) {
172+ debug ( 'creating installer...' ) ;
173+
174+ var tasks = [
175+ verify ,
176+ _ . partial ( createDMG , INSTALLER_CONFIG )
177+ ] ;
98178
99179 series ( tasks , function ( err ) {
100180 if ( err ) {
101- console . error ( err . stack ) ;
181+ console . error ( chalk . red . bold ( figures . cross ) ,
182+ 'Failed to create DMG installer:' , err . message ) ;
183+ console . error ( chalk . gray ( err . stack ) ) ;
102184 return done ( err ) ;
103185 }
104- console . log ( 'Installer created!' ) ;
186+ console . log ( chalk . green . bold ( figures . tick ) ,
187+ ' DMG installer written to' ,
188+ path . join ( INSTALLER_CONFIG . out , INSTALLER_CONFIG . name + '.dmg' ) ) ;
105189 done ( ) ;
106190 } ) ;
107191} ;
0 commit comments