From 7cdf25eb5bedde73fe8ba81921938b5ba3c910dc Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 6 Aug 2016 10:40:47 -0600 Subject: [PATCH] Start on electron-winstaller --- script/build | 18 ++++-- script/lib/code-sign-on-mac.js | 43 ++++++++++++++ script/lib/code-sign.js | 81 -------------------------- script/lib/create-windows-installer.js | 33 +++++++++++ script/lib/download-github-raw-file.js | 15 +++++ script/package.json | 1 + 6 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 script/lib/code-sign-on-mac.js delete mode 100644 script/lib/code-sign.js create mode 100644 script/lib/create-windows-installer.js create mode 100644 script/lib/download-github-raw-file.js diff --git a/script/build b/script/build index 839f0aaf5..c0c4b2c92 100755 --- a/script/build +++ b/script/build @@ -8,8 +8,9 @@ require('colors') const argv = require('yargs').argv const cleanOutputDirectory = require('./lib/clean-output-directory') -const codeSign = require('./lib/code-sign') +const codeSignOnMac = require('./lib/code-sign-on-mac') const copyAssets = require('./lib/copy-assets') +const createWindowsInstaller = require('./lib/create-windows-installer') const dumpSymbols = require('./lib/dump-symbols') const generateAPIDocs = require('./lib/generate-api-docs') const generateMetadata = require('./lib/generate-metadata') @@ -40,12 +41,17 @@ generateAPIDocs() dumpSymbols() .then(packageApplication) .then(packagedAppPath => { - if (argv.codeSign) { - codeSign(packagedAppPath) - } else { - console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing...'.gray) + if (process.platform === 'darwin') { + if (argv.codeSign) { + codeSignOnMac(packagedAppPath) + } else { + console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing...'.gray) + } + return Promise.resolve(packagedAppPath) + } else if (process.platform === 'win32') { + return createWindowsInstaller(packagedAppPath, argv.codeSign).then(() => packagedAppPath) } - + }).then(packagedAppPath => { if (argv.install) { installApplication(packagedAppPath) } else { diff --git a/script/lib/code-sign-on-mac.js b/script/lib/code-sign-on-mac.js new file mode 100644 index 000000000..036466236 --- /dev/null +++ b/script/lib/code-sign-on-mac.js @@ -0,0 +1,43 @@ +const childProcess = require('child_process') +const downloadGithubRawFile = require('./download-github-raw-file') +const fs = require('fs-extra') +const os = require('os') +const path = require('path') + +module.exports = function (packagedAppPath) { + if (!process.env.ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL) { + console.log('Skipping code signing because the ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL environment variable is not defined'.gray) + return + } + + try { + const certPath = path.join(os.tmpdir(), 'mac.p12') + downloadGithubRawFile(process.env.ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL, certPath) + + console.log(`Unlocking keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN}`) + const unlockArgs = ['unlock-keychain', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN] + // For signing on local workstations, password could be entered interactively + if (process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD) { + unlockArgs.push('-p', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD) + } + childProcess.spawnSync('security', unlockArgs, {stdio: 'inherit'}) + + console.log(`Importing certificate at ${certPath} into ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN} keychain`) + childProcess.spawnSync('security', [ + 'import', certPath, + '-P', process.env.ATOM_MAC_CODE_SIGNING_CERT_PASSWORD, + '-k', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN, + '-T', '/usr/bin/codesign' + ]) + + console.log(`Code-signing application at ${packagedAppPath}`) + childProcess.spawnSync('codesign', [ + '--deep', '--force', '--verbose', + '--keychain', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN, + '--sign', 'Developer ID Application: GitHub', packagedAppPath + ], {stdio: 'inherit'}) + } finally { + console.log(`Deleting certificate at ${certPath}`) + fs.removeSync(certPath) + } +} diff --git a/script/lib/code-sign.js b/script/lib/code-sign.js deleted file mode 100644 index 56f0b0f15..000000000 --- a/script/lib/code-sign.js +++ /dev/null @@ -1,81 +0,0 @@ -const childProcess = require('child_process') -const fs = require('fs-extra') -const os = require('os') -const path = require('path') -const syncRequest = require('sync-request') - -module.exports = function (packagedAppPath) { - if (process.platform === 'darwin') { - if (!process.env.ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL) { - console.log('Skipping code signing because the ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL environment variable is not defined'.gray) - return - } - - const certPath = path.join(os.tmpdir(), 'mac.p12') - downloadCertificate(process.env.ATOM_MAC_CODE_SIGNING_CERT_DOWNLOAD_URL, certPath) - - try { - console.log(`Unlocking keychain ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN}`) - - const unlockArgs = ['unlock-keychain', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN] - // For signing on local workstations, password could be entered interactively - if (process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD) { - unlockArgs.push('-p', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN_PASSWORD) - } - childProcess.spawnSync('security', unlockArgs, {stdio: 'inherit'}) - - console.log(`Importing certificate at ${certPath} into ${process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN} keychain`) - childProcess.spawnSync('security', [ - 'import', certPath, - '-P', process.env.ATOM_MAC_CODE_SIGNING_CERT_PASSWORD, - '-k', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN, - '-T', '/usr/bin/codesign' - ]) - - console.log(`Code-signing application at ${packagedAppPath}`) - childProcess.spawnSync('codesign', [ - '--deep', '--force', '--verbose', - '--keychain', process.env.ATOM_MAC_CODE_SIGNING_KEYCHAIN, - '--sign', 'Developer ID Application: GitHub', packagedAppPath - ], {stdio: 'inherit'}) - } finally { - console.log(`Deleting certificate at ${certPath}`); - fs.removeSync(certPath) - } - } else if (process.platform === 'win32') { - const signtoolPath = path.join('C:', 'Program Files (x86)', 'Microsoft SDKs', 'Windows', 'v7.1A', 'bin', 'signtool.exe') - - const binToSignPath = path.join(packagedAppPath, 'atom.exe') - console.log(`Signing Windows Binary at ${binToSignPath}`) - childProcess.spawnSync(signtoolPath, [ - 'sign', '/v', - '/f', process.env.WIN_P12KEY_PATH, - '/p', process.env.WIN_P12KEY_PASSWORD, - binToSignPath - ], {stdio: 'inherit'}) - - // TODO: when we will be able to generate an installer, sign that too! - // const installerToSignPath = computeInstallerPath() - // console.log(`Signing Windows Installer at ${installerToSignPath}`) - // childProcess.spawnSync(signtoolPath, [ - // 'sign', binToSignPath, '/v', - // '/f', process.env.WIN_P12KEY_PATH, - // '/p', process.env.WIN_P12KEY_PASSWORD - // ], {stdio: 'inherit'}) - } else { - throw new Error(`Code-signing is not supported for platform ${process.platform}!`) - } -} - -function downloadCertificate (downloadURL, certificatePath) { - console.log(`Dowloading certificate to ${certificatePath}`) - const response = syncRequest('GET', downloadURL, { - 'headers': {'Accept': 'application/vnd.github.v3.raw', 'User-Agent': 'Atom Build'} - }) - - if (response.statusCode === 200) { - fs.writeFileSync(certificatePath, response.body) - } else { - throw new Error('Error downloading certificate. HTTP Status ' + response.statusCode + '.') - } -} diff --git a/script/lib/create-windows-installer.js b/script/lib/create-windows-installer.js new file mode 100644 index 000000000..025906ae8 --- /dev/null +++ b/script/lib/create-windows-installer.js @@ -0,0 +1,33 @@ +const downloadCertificate = require('./download-github-raw-file') +const electronInstaller = require('electron-winstaller') +const fs = require('fs-extra') +const os = require('os') +const path = require('path') + +module.exports = function (packagedAppPath, codeSign) { + console.log(`Creating Windows Installer for ${packagedAppPath}`) + const options = { + appDirectory: packagedAppPath, + authors: 'GitHub Inc.', + iconUrl: `https://raw.githubusercontent.com/atom/atom/master/resources/app-icons/${CONFIG.channel}/atom.ico` + loadingGif: path.join(CONFIG.repositoryRootPath, 'resources', 'win', 'loading.gif'), + outputDirectory: CONFIG.buildOutputPath, + remoteReleases: `https://atom.io/api/updates?version=${CONFIG.appMetadata.version}`, + setupIcon: path.join(CONFIG.repositoryRootPath, 'resources', 'app-icons', CONFIG.channel, 'atom.ico') + } + + if (codeSign && WIN_P12KEY_URL) { + const certPath = path.join(os.tmpdir(), 'win.p12') + downloadGithubRawFile(WIN_P12KEY_URL, certPath) + const deleteCertificate = function () { + console.log(`Deleting certificate at ${certPath}`) + fs.removeSync(certPath) + } + options.certificateFile = certPath + options.certificatePassword = WIN_P12KEY_PASSWORD + return electronInstaller.createWindowsInstaller(options).then(deleteCertificate, deleteCertificate) + } else { + console.log('Skipping code-signing. Specify the --code-sign option and provide a WIN_P12KEY_URL environment variable to perform code-signing'.gray) + return electronInstaller.createWindowsInstaller(options) + } +} diff --git a/script/lib/download-github-raw-file.js b/script/lib/download-github-raw-file.js new file mode 100644 index 000000000..d26b34075 --- /dev/null +++ b/script/lib/download-github-raw-file.js @@ -0,0 +1,15 @@ +const fs = require('fs-extra') +const syncRequest = require('sync-request') + +module.exports = function (downloadURL, destinationPath) { + console.log(`Dowloading raw file from GitHub Repository to ${destinationPath}`) + const response = syncRequest('GET', downloadURL, { + 'headers': {'Accept': 'application/vnd.github.v3.raw', 'User-Agent': 'Atom Build'} + }) + + if (response.statusCode === 200) { + fs.writeFileSync(destinationPath, response.body) + } else { + throw new Error('Error downloading file. HTTP Status ' + response.statusCode + '.') + } +} diff --git a/script/package.json b/script/package.json index 7ff50490c..fe26df694 100644 --- a/script/package.json +++ b/script/package.json @@ -8,6 +8,7 @@ "colors": "1.1.2", "donna": "1.0.13", "electron-packager": "7.3.0", + "electron-winstaller": "^2.3.3", "fs-extra": "0.30.0", "glob": "7.0.3", "joanna": "0.0.6",