mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-04 19:54:32 +08:00
feat(ci): add Travis and AppVeyor ci support
This commit is contained in:
parent
07f81f81a6
commit
d95cb45147
11 changed files with 303 additions and 131 deletions
85
.travis.yml
85
.travis.yml
|
@ -1,52 +1,38 @@
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- NYLAS_ACCESS_TOKEN=cb200be7c921f73a1c35930f6a4ac8758b271be0
|
|
||||||
|
|
||||||
compiler:
|
compiler:
|
||||||
- clang
|
- clang
|
||||||
- gcc
|
- gcc
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# Wants a c++11 compiler
|
- os: linux
|
||||||
- os: linux
|
env: NODE_VERSION=0.10 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
||||||
env: NODE_VERSION=0.10 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
- os: linux
|
||||||
- os: linux
|
env: NODE_VERSION=0.12 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
||||||
env: NODE_VERSION=0.12 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
- os: linux
|
||||||
- os: linux
|
env: NODE_VERSION=4.2 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas PUBLISH_BUILD=true
|
||||||
env: NODE_VERSION=4.2 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
- os: linux
|
||||||
- os: linux
|
env: NODE_VERSION=5 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
||||||
env: NODE_VERSION=5 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
|
- os: osx
|
||||||
- os: osx
|
env: NODE_VERSION=0.10
|
||||||
env: NODE_VERSION=0.10
|
- os: osx
|
||||||
- os: osx
|
env: NODE_VERSION=0.12 CC=clang CXX=clang++
|
||||||
env: NODE_VERSION=0.12 CC=clang CXX=clang++
|
- os: osx
|
||||||
# osx already supports c++11 in Apple LLVM
|
env: NODE_VERSION=4.2 CC=clang CXX=clang++ PUBLISH_BUILD=true
|
||||||
- os: osx
|
- os: osx
|
||||||
env: NODE_VERSION=4.2 CC=clang CXX=clang++
|
env: NODE_VERSION=5 CC=clang CXX=clang++
|
||||||
- os: osx
|
|
||||||
env: NODE_VERSION=5 CC=clang CXX=clang++
|
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- echo $CC
|
- echo $CC
|
||||||
- echo $CXX
|
- echo $CXX
|
||||||
- clang --version
|
- clang --version
|
||||||
- if [ "$CC" = "gcc-4.8" ]; then gcc-4.8 -v; else gcc -v; fi
|
- if [ "$CC" = "gcc-4.8" ]; then gcc-4.8 -v; else gcc -v; fi
|
||||||
- git clone https://github.com/creationix/nvm.git /tmp/.nvm
|
- git clone https://github.com/creationix/nvm.git /tmp/.nvm
|
||||||
- source /tmp/.nvm/nvm.sh
|
- source /tmp/.nvm/nvm.sh
|
||||||
- nvm install $NODE_VERSION
|
- nvm install $NODE_VERSION
|
||||||
- nvm use --delete-prefix $NODE_VERSION
|
- nvm use --delete-prefix $NODE_VERSION
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
|
- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then export DISPLAY=:99.0; sh -e /etc/init.d/xvfb
|
||||||
export DISPLAY=:99.0;
|
start; fi
|
||||||
sh -e /etc/init.d/xvfb start;
|
|
||||||
fi
|
|
||||||
|
|
||||||
script: script/cibuild
|
script: script/cibuild
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
|
@ -59,11 +45,22 @@ addons:
|
||||||
- git
|
- git
|
||||||
- libgnome-keyring-dev
|
- libgnome-keyring-dev
|
||||||
- xvfb
|
- xvfb
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- ci-test
|
- ci-test
|
||||||
|
|
||||||
git:
|
git:
|
||||||
submodules: false
|
submodules: false
|
||||||
|
before_install:
|
||||||
|
- openssl aes-256-cbc -k "$DECRYPTION_PASSWORD" -in build/resources/ssh/nylas-n1-ci-ssh.openssl.enc -out nylas-n1-ci-ssh -d
|
||||||
|
- mv nylas-n1-ci-ssh ~/.ssh/id_rsa
|
||||||
|
- ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||||
|
- chmod 400 ~/.ssh/id_rsa
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
- 2>/dev/null 1>/dev/null openssl aes-256-cbc -K $encrypted_d583b56b822e_key -iv $encrypted_d583b56b822e_iv -in build/resources/nylas/encrypted_certificates/travis/travis-files.tar.enc -out build/resources/nylas/encrypted_certificates/travis/travis-files.tar -d
|
||||||
|
- mkdir build/resources/certs
|
||||||
|
- 2>/dev/null 1>/dev/null tar xvf build/resources/nylas/encrypted_certificates/travis/travis-files.tar --directory=build/resources/certs/
|
||||||
|
- 2>/dev/null 1>/dev/null source build/resources/certs/set_unix_env.sh
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
secure: O+XG3C/VnCfCVXTHudOQ6JMmBqrRHXh1j7jRwfQ3PYd27gm9BWNjvwlbWTLNcaar9gM00Pwi3rR8IujzJLlw3usZGWbJMLkz+aPYdOlbiDLhyMdIHwX4oI58d1eHx7m8Eun3qT3Y0VkO3blBNdWFWV4ebkfLZyygzXva4CDlSFtbeQYGy4ft76v7Au9uVlOUoV8f+juPx+0Jv+AtQmsY9Sf+6WbxrNaE9y2u2q1ks+XpjFn8Wt1f/xp/Vae0/MjJFpGIVfaUy+q7W8QQ0TyzSCM0eGtjxilS+BkGHjjvlLlMdCspRnZzpSJC+KkpEKLJrAPjR0DAfYMedWockEaIwGG8Onf90fXKG0nlvAg4WrWjnpr0q+V79zOU/yYD/kysLBYg6fYzv6uTvN7TzNaFkKaiQZvorI9P8w/wShGFHE4Y8JC5QU4CLI8q2qrkI38KKt3valIP4qxA/56aM0+D5roTecfh3Y40OcpqKZicpeNvuB1u2FmD2+oxLEb3MVnyfnVnDBP7Crp8/oLsIl/gGR/SVUEyLIimozugUySnCig1BEicygECvp6eRpEHryNrEvLKfxtppr3eWcRKQwnYwch4CaFwya0Lpc1dSA9NaOFQu0kR374s+fhqYgrkaCJevZd+ouKY+0Zt8gZ4CjJVhJ5YamwZAPG+obRd9G3xRM0=
|
||||||
|
|
49
appveyor.yml
Normal file
49
appveyor.yml
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
version: '{build}'
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x86
|
||||||
|
|
||||||
|
pull_requests:
|
||||||
|
do_not_increment_build_number: true
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- ci-test
|
||||||
|
|
||||||
|
test: off
|
||||||
|
|
||||||
|
# We deploy via grunt publish-nylas-build instead of AppVeyor
|
||||||
|
deploy: off
|
||||||
|
|
||||||
|
# We need to only clone the main module because our submodule requires the
|
||||||
|
# encrypted ssh key to access submodules
|
||||||
|
clone_depth: 1
|
||||||
|
build:
|
||||||
|
verbosity: minimal
|
||||||
|
install:
|
||||||
|
- ps: Install-Product node $env:NODE_VERSION $env:PLATFORM
|
||||||
|
- ps: nuget install secure-file -ExcludeVersion
|
||||||
|
|
||||||
|
# We need to extract the encrypted private ssh key to clone the submodule.
|
||||||
|
- ps: secure-file\tools\secure-file -decrypt build\resources\ssh\nylas-n1-ci-ssh-secure-file.enc -secret $env:DECRYPTION_PASSWORD
|
||||||
|
- ps: mv -Force build\resources\ssh\nylas-n1-ci-ssh-secure-file c:\users\appveyor\.ssh\id_rsa
|
||||||
|
- ps: git submodule init
|
||||||
|
# http://stackoverflow.com/questions/21002919/running-a-remote-powershell-script-with-a-git-command-in-it-results-in-nativecom
|
||||||
|
- ps: Start-Process -FilePath git.exe -ArgumentList 'submodule update' -Wait -NoNewWindow
|
||||||
|
|
||||||
|
- ps: secure-file\tools\secure-file -decrypt build\resources\nylas\encrypted_certificates\appveyor\win-nylas-n1.p12.enc -secret $env:DECRYPTION_PASSWORD
|
||||||
|
- ps: secure-file\tools\secure-file -decrypt build\resources\nylas\encrypted_certificates\appveyor\set_win_env.ps1.enc -secret $env:DECRYPTION_PASSWORD
|
||||||
|
- ps: . build\resources\nylas\encrypted_certificates\appveyor\set_win_env.ps1
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- ps: .\script\cibuild.ps1
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- NODE_VERSION: 0.12
|
||||||
|
PUBLISH_BUILD: true
|
||||||
|
global:
|
||||||
|
CERTIFICATE_FILE: .\build\resources\nylas\encrypted_certificates\appveyor\win-nylas-n1.p12
|
||||||
|
DECRYPTION_PASSWORD:
|
||||||
|
secure: 48VSzDtdBd52Xlo3TZ1NeR1yRRrZ3AU6Px5XjD5RDp44cFU5GYVspecGqX6DGCV7i0D7nldGMyEbXNrjM1t1Kw==
|
|
@ -9,6 +9,9 @@ babelOptions = require '../static/babelrc'
|
||||||
# packages in the root-level node_modules are compiled against Chrome's v8
|
# packages in the root-level node_modules are compiled against Chrome's v8
|
||||||
# headers.
|
# headers.
|
||||||
#
|
#
|
||||||
|
# See build/resources/nylas/docs/ContinuousIntegration.md for more detailed
|
||||||
|
# instructions on how we build N1.
|
||||||
|
#
|
||||||
# Some useful grunt options are:
|
# Some useful grunt options are:
|
||||||
# --install-dir
|
# --install-dir
|
||||||
# --build-dir
|
# --build-dir
|
||||||
|
@ -37,7 +40,6 @@ babelOptions = require '../static/babelrc'
|
||||||
# installDir = /usr/local OR $INSTALL_PREFIX
|
# installDir = /usr/local OR $INSTALL_PREFIX
|
||||||
# binDir = /usr/local/bin
|
# binDir = /usr/local/bin
|
||||||
# shareDir = /usr/local/share/nylas
|
# shareDir = /usr/local/share/nylas
|
||||||
|
|
||||||
_ = require 'underscore'
|
_ = require 'underscore'
|
||||||
|
|
||||||
packageJson = require '../package.json'
|
packageJson = require '../package.json'
|
||||||
|
@ -332,7 +334,7 @@ module.exports = (grunt) ->
|
||||||
outputDir: 'electron'
|
outputDir: 'electron'
|
||||||
downloadDir: electronDownloadDir
|
downloadDir: electronDownloadDir
|
||||||
rebuild: true # rebuild native modules after electron is updated
|
rebuild: true # rebuild native modules after electron is updated
|
||||||
token: process.env.NYLAS_ACCESS_TOKEN
|
token: process.env.NYLAS_GITHUB_OAUTH_TOKEN
|
||||||
|
|
||||||
'create-windows-installer':
|
'create-windows-installer':
|
||||||
installer:
|
installer:
|
||||||
|
@ -343,7 +345,7 @@ module.exports = (grunt) ->
|
||||||
iconUrl: 'http://edgehill.s3.amazonaws.com/static/nylas.ico'
|
iconUrl: 'http://edgehill.s3.amazonaws.com/static/nylas.ico'
|
||||||
setupIcon: path.resolve(__dirname, 'resources', 'win', 'nylas.ico')
|
setupIcon: path.resolve(__dirname, 'resources', 'win', 'nylas.ico')
|
||||||
certificateFile: process.env.CERTIFICATE_FILE
|
certificateFile: process.env.CERTIFICATE_FILE
|
||||||
certificatePassword: process.env.CERTIFICATE_PASSWORD
|
certificatePassword: process.env.WINDOWS_CODESIGN_KEY_PASSWORD
|
||||||
exe: 'nylas.exe'
|
exe: 'nylas.exe'
|
||||||
|
|
||||||
shell:
|
shell:
|
||||||
|
@ -375,18 +377,25 @@ module.exports = (grunt) ->
|
||||||
buildTasks.push('set-exe-icon') if process.platform is 'win32'
|
buildTasks.push('set-exe-icon') if process.platform is 'win32'
|
||||||
grunt.registerTask('build', buildTasks)
|
grunt.registerTask('build', buildTasks)
|
||||||
|
|
||||||
ciTasks = ['output-disk-space', 'download-electron', 'build']
|
ciTasks = ['output-disk-space',
|
||||||
|
'download-electron',
|
||||||
|
'build']
|
||||||
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
|
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
|
||||||
ciTasks.push('set-version', 'lint', 'generate-asar')
|
ciTasks.push('set-version', 'lint', 'generate-asar')
|
||||||
ciTasks.push('test') if process.platform is 'darwin'
|
|
||||||
|
|
||||||
unless process.env.TRAVIS
|
if process.platform is "darwin"
|
||||||
ciTasks.push('codesign')
|
ciTasks.push('test', 'codesign', 'mkdmg')
|
||||||
ciTasks.push('mkdmg') if process.platform is 'darwin'
|
|
||||||
ciTasks.push('mkdeb') if process.platform is 'linux'
|
else if process.platform is "linux"
|
||||||
|
ciTasks.push('mkdeb')
|
||||||
# Only works on Fedora build machines
|
# Only works on Fedora build machines
|
||||||
# ciTasks.push('mkrpm') if process.platform is 'linux'
|
# ciTasks.push('mkrpm') if process.platform is 'linux'
|
||||||
ciTasks.push('create-windows-installer:installer') if process.platform is 'win32'
|
|
||||||
|
else if process.platform is "win32"
|
||||||
|
ciTasks.push('create-windows-installer:installer')
|
||||||
|
|
||||||
|
{shouldPublishBuild} = require('./tasks/task-helpers')(grunt)
|
||||||
|
if shouldPublishBuild()
|
||||||
ciTasks.push('publish-nylas-build')
|
ciTasks.push('publish-nylas-build')
|
||||||
|
|
||||||
grunt.registerTask('ci', ciTasks)
|
grunt.registerTask('ci', ciTasks)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2c6ed69565b82a5f9bdd6f3ae675070a797f5cdd
|
Subproject commit 48e33fad632565aa1ebfbfaa84e555c36a7d6572
|
BIN
build/resources/ssh/nylas-n1-ci-ssh-secure-file.enc
Executable file
BIN
build/resources/ssh/nylas-n1-ci-ssh-secure-file.enc
Executable file
Binary file not shown.
BIN
build/resources/ssh/nylas-n1-ci-ssh.openssl.enc
Normal file
BIN
build/resources/ssh/nylas-n1-ci-ssh.openssl.enc
Normal file
Binary file not shown.
|
@ -1,61 +1,133 @@
|
||||||
|
_ = require 'underscore'
|
||||||
path = require 'path'
|
path = require 'path'
|
||||||
fs = require 'fs-plus'
|
fs = require 'fs-plus'
|
||||||
|
|
||||||
# Edgehill introduces the KEYCHAIN_ACCESS environment variable. This is
|
# Codesigning is a Mac-only process that requires a valid Apple
|
||||||
# injected via Jenkins. It is of the form:
|
# certificate, the private key, and access to the Mac keychain.
|
||||||
|
#
|
||||||
|
# We can only codesign from keys in the keychain. At the end of the day we need
|
||||||
|
# the certificate and private key to exist in the keychain, and these two
|
||||||
|
# variables to be set:
|
||||||
|
#
|
||||||
|
# XCODE_KEYCHAIN - The path to the keychain we're using
|
||||||
|
# XCODE_KEYCHAIN_PASSWORD - The keychain password
|
||||||
|
#
|
||||||
|
# If these variables are already set we don't have to do anything.
|
||||||
|
#
|
||||||
|
# If the keychain and password already exists, we'll know by detecting the
|
||||||
|
# KEYCHAIN_ACCESS environment variable. It is of the form:
|
||||||
#
|
#
|
||||||
# /full/keychain/path/login.keychain:password
|
# /full/keychain/path/login.keychain:password
|
||||||
#
|
#
|
||||||
# The KEYCHAIN_ACCESS variable is saved in a Jenkins Credential and
|
# In the case of Travis, we need to setup a temp keychain from encrypted files
|
||||||
# injected via the Credentials Binding Plugin.
|
# in the repository. # We'll decrypt and import our certificates, put them in
|
||||||
|
# a temporary keychain, and use that.
|
||||||
#
|
#
|
||||||
|
# If you want to verify the app was signed you can run the commands:
|
||||||
|
#
|
||||||
|
# spctl -a -t exec -vv /path/to/N1.app
|
||||||
|
#
|
||||||
|
# Which should return "satisfies its Designated Requirement"
|
||||||
|
#
|
||||||
|
# And:
|
||||||
|
#
|
||||||
|
# codesign --verify --deep --verbose=2 /path/to/N1.app
|
||||||
|
#
|
||||||
|
# Which should return "accepted"
|
||||||
module.exports = (grunt) ->
|
module.exports = (grunt) ->
|
||||||
{spawn} = require('./task-helpers')(grunt)
|
{spawnP, shouldPublishBuild} = require('./task-helpers')(grunt)
|
||||||
|
tmpKeychain = "n1-build.keychain"
|
||||||
|
|
||||||
grunt.registerTask 'codesign', 'Codesign the app', ->
|
grunt.registerTask 'codesign', 'Codesign the app', ->
|
||||||
done = @async()
|
done = @async()
|
||||||
|
return unless process.platform is 'darwin'
|
||||||
|
|
||||||
if process.platform is 'darwin' and (process.env.XCODE_KEYCHAIN or process.env.KEYCHAIN_ACCESS)
|
{XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN} = process.env
|
||||||
unlockKeychain (error) ->
|
if XCODE_KEYCHAIN? and XCODE_KEYCHAIN_PASSWORD?
|
||||||
if error?
|
unlockKeychain(XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD)
|
||||||
done(error)
|
.then(signApp)
|
||||||
else
|
.then(verifyApp).then(done).catch(grunt.fail.fatal)
|
||||||
signApp(done)
|
else if process.env.KEYCHAIN_ACCESS?
|
||||||
else
|
|
||||||
signApp(done)
|
|
||||||
|
|
||||||
unlockKeychain = (callback) ->
|
|
||||||
cmd = 'security'
|
|
||||||
{XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN, KEYCHAIN_ACCESS} = process.env
|
|
||||||
|
|
||||||
if KEYCHAIN_ACCESS?
|
|
||||||
[XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD] = KEYCHAIN_ACCESS.split(":")
|
[XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD] = KEYCHAIN_ACCESS.split(":")
|
||||||
|
unlockKeychain(XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD)
|
||||||
args = ['unlock-keychain', '-p', XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN]
|
.then(signApp)
|
||||||
spawn {cmd, args}, (error) -> callback(error)
|
.then(verifyApp).then(done).catch(grunt.fail.fatal)
|
||||||
|
else if process.env.TRAVIS
|
||||||
signApp = (callback) ->
|
if shouldPublishBuild()
|
||||||
switch process.platform
|
buildTravisKeychain()
|
||||||
when 'darwin'
|
.then(_.partial(signApp, tmpKeychain))
|
||||||
cmd = 'codesign'
|
.then(verifyApp)
|
||||||
args = ['--deep', '--force', '--verbose', '--sign', 'Developer ID Application: InboxApp, Inc.', grunt.config.get('nylasGruntConfig.shellAppDir')]
|
.then(cleanupKeychain)
|
||||||
spawn {cmd, args}, (error) -> callback(error)
|
.then(done).catch(grunt.fail.fatal)
|
||||||
when 'win32'
|
|
||||||
# TODO: Don't do anything now, because we need a certificate pfx file
|
|
||||||
# issued from a certificate authority, and we don't have one.
|
|
||||||
return callback()
|
|
||||||
spawn {cmd: 'taskkill', args: ['/F', '/IM', 'nylas.exe']}, ->
|
|
||||||
cmd = process.env.JANKY_SIGNTOOL ? 'signtool'
|
|
||||||
args = ['sign', path.join(grunt.config.get('nylasGruntConfig.shellAppDir'), 'nylas.exe')]
|
|
||||||
|
|
||||||
spawn {cmd, args}, (error) ->
|
|
||||||
return callback(error) if error?
|
|
||||||
|
|
||||||
setupExePath = path.resolve(grunt.config.get('nylasGruntConfig.buildDir'), 'installer', 'NylasSetup.exe')
|
|
||||||
if fs.isFileSync(setupExePath)
|
|
||||||
args = ['sign', setupExePath]
|
|
||||||
spawn {cmd, args}, (error) -> callback(error)
|
|
||||||
else
|
|
||||||
callback()
|
|
||||||
else
|
else
|
||||||
callback()
|
return done()
|
||||||
|
else
|
||||||
|
grunt.fail.fatal("Can't codesign without keychain or certs")
|
||||||
|
|
||||||
|
unlockKeychain = (keychain, keychainPass) ->
|
||||||
|
args = ['unlock-keychain', '-p', keychainPass, keychain]
|
||||||
|
spawnP("security", args)
|
||||||
|
|
||||||
|
signApp = (keychain) ->
|
||||||
|
devId = 'Developer ID Application: InboxApp, Inc.'
|
||||||
|
appPath = grunt.config.get('nylasGruntConfig.shellAppDir')
|
||||||
|
args = ['--deep', '--force', '--verbose', '--sign', devId]
|
||||||
|
args.push("--keychain", keychain) if keychain
|
||||||
|
args.push(appPath)
|
||||||
|
spawnP("codesign", args)
|
||||||
|
|
||||||
|
buildTravisKeychain = ->
|
||||||
|
crypto = require('crypto')
|
||||||
|
tmpPass = crypto.randomBytes(32).toString('hex')
|
||||||
|
{appleCert, nylasCert, nylasPrivateKey, keyPass} = getCertData()
|
||||||
|
codesignBin = path.join("/", "usr","bin", "codesign")
|
||||||
|
|
||||||
|
# Create a custom, temporary keychain
|
||||||
|
cleanupKeychain()
|
||||||
|
.then -> spawnP("security", ["create-keychain", '-p', tmpPass, tmpKeychain])
|
||||||
|
|
||||||
|
# Make the custom keychain default, so xcodebuild will use it for signing
|
||||||
|
.then -> spawnP("security", ["default-keychain", "-s", tmpKeychain])
|
||||||
|
|
||||||
|
# Unlock the keychain
|
||||||
|
.then -> unlockKeychain(tmpKeychain, tmpPass)
|
||||||
|
|
||||||
|
# Set keychain timeout to 1 hour for long builds
|
||||||
|
.then -> spawnP("security", ["set-keychain-settings", "-t", "3600", "-l", tmpKeychain])
|
||||||
|
|
||||||
|
# Add certificates to keychain and allow codesign to access them
|
||||||
|
.then -> spawnP("security", ["import", appleCert, "-k", tmpKeychain, "-T", codesignBin])
|
||||||
|
|
||||||
|
.then -> spawnP("security", ["import", nylasCert, "-k", tmpKeychain, "-T", codesignBin])
|
||||||
|
|
||||||
|
# Load the password for the private key from environment variables
|
||||||
|
.then -> spawnP("security", ["import", nylasPrivateKey, "-k", tmpKeychain, "-P", keyPass, "-T", codesignBin])
|
||||||
|
|
||||||
|
verifyApp = ->
|
||||||
|
appPath = grunt.config.get('nylasGruntConfig.shellAppDir')
|
||||||
|
spawnP("codesign", ["--verify", "--deep", "--verbose=2", appPath])
|
||||||
|
.then -> spawnP("spctl", ["-a", "-t", "exec", "-vv", appPath])
|
||||||
|
|
||||||
|
cleanupKeychain = ->
|
||||||
|
if fs.existsSync(path.join(process.env.HOME, "Library", "Keychains", tmpKeychain))
|
||||||
|
return spawnP("security", ["delete-keychain", tmpKeychain])
|
||||||
|
else return Promise.resolve()
|
||||||
|
|
||||||
|
getCertData = ->
|
||||||
|
certs = path.resolve(path.join('build', 'resources', 'certs'))
|
||||||
|
appleCert = path.join(certs, 'AppleWWDRCA.cer')
|
||||||
|
nylasCert = path.join(certs, 'mac-nylas-n1.cer')
|
||||||
|
nylasPrivateKey = path.join(certs, 'mac-nylas-n1.p12')
|
||||||
|
|
||||||
|
keyPass = process.env.APPLE_CODESIGN_KEY_PASSWORD
|
||||||
|
|
||||||
|
if not keyPass
|
||||||
|
throw new Error("APPLE_CODESIGN_KEY_PASSWORD must be set")
|
||||||
|
if not fs.existsSync(appleCert)
|
||||||
|
throw new Error("#{appleCert} doesn't exist")
|
||||||
|
if not fs.existsSync(nylasCert)
|
||||||
|
throw new Error("#{nylasCert} doesn't exist")
|
||||||
|
if not fs.existsSync(nylasPrivateKey)
|
||||||
|
throw new Error("#{nylasPrivateKey} doesn't exist")
|
||||||
|
|
||||||
|
return {appleCert, nylasCert, nylasPrivateKey, keyPass}
|
||||||
|
|
|
@ -51,10 +51,10 @@ module.exports = (grunt) ->
|
||||||
resolve()
|
resolve()
|
||||||
|
|
||||||
postToSlack = (msg) ->
|
postToSlack = (msg) ->
|
||||||
return Promise.resolve() unless process.env.PUBLISH_SLACK_HOOK
|
return Promise.resolve() unless process.env.NYLAS_INTERNAL_HOOK_URL
|
||||||
new Promise (resolve, reject) ->
|
new Promise (resolve, reject) ->
|
||||||
request.post
|
request.post
|
||||||
url: process.env.PUBLISH_SLACK_HOOK
|
url: process.env.NYLAS_INTERNAL_HOOK_URL
|
||||||
json:
|
json:
|
||||||
username: "Edgehill Builds"
|
username: "Edgehill Builds"
|
||||||
text: msg
|
text: msg
|
||||||
|
@ -126,11 +126,9 @@ module.exports = (grunt) ->
|
||||||
awsSecret = process.env.AWS_SECRET_ACCESS_KEY ? ""
|
awsSecret = process.env.AWS_SECRET_ACCESS_KEY ? ""
|
||||||
|
|
||||||
if awsKey.length is 0
|
if awsKey.length is 0
|
||||||
grunt.log.error "Please set the AWS_ACCESS_KEY_ID environment variable"
|
grunt.fail.fatal "Please set the AWS_ACCESS_KEY_ID environment variable"
|
||||||
return false
|
|
||||||
if awsSecret.length is 0
|
if awsSecret.length is 0
|
||||||
grunt.log.error "Please set the AWS_SECRET_ACCESS_KEY environment variable"
|
grunt.fail.fatal "Please set the AWS_SECRET_ACCESS_KEY environment variable"
|
||||||
return false
|
|
||||||
|
|
||||||
s3Client = s3.createClient
|
s3Client = s3.createClient
|
||||||
s3Options:
|
s3Options:
|
||||||
|
@ -139,25 +137,34 @@ module.exports = (grunt) ->
|
||||||
|
|
||||||
done = @async()
|
done = @async()
|
||||||
|
|
||||||
populateVersion().then ->
|
populateVersion()
|
||||||
runEmailIntegrationTest().then ->
|
.then ->
|
||||||
uploadPromises = []
|
if process.env.RUN_APPLE_SCRIPT_INTEGRATION
|
||||||
if process.platform is 'darwin'
|
runEmailIntegrationTest()
|
||||||
uploadPromises.push uploadToS3(dmgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.dmg")
|
else Promise.resolve()
|
||||||
uploadPromises.push uploadZipToS3(appName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.zip")
|
.then ->
|
||||||
if process.platform is 'win32'
|
uploadPromises = []
|
||||||
uploadPromises.push uploadToS3("installer/"+winReleasesName(), "#{fullVersion}/#{process.platform}/#{process.arch}/RELEASES")
|
if process.platform is 'darwin'
|
||||||
uploadPromises.push uploadToS3("installer/"+winSetupName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1Setup.exe")
|
uploadPromises.push uploadToS3(dmgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.dmg")
|
||||||
uploadPromises.push uploadToS3("installer/"+winNupkgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/#{winNupkgName()}")
|
uploadPromises.push uploadZipToS3(appName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.zip")
|
||||||
if process.platform is 'linux'
|
|
||||||
buildDir = grunt.config.get('nylasGruntConfig.buildDir')
|
|
||||||
files = fs.readdirSync(buildDir)
|
|
||||||
for file in files
|
|
||||||
if path.extname(file) is '.deb'
|
|
||||||
uploadPromises.push uploadToS3(file, "#{fullVersion}/#{process.platform}/#{process.arch}/N1.deb")
|
|
||||||
if path.extname(file) is '.rpm'
|
|
||||||
uploadPromises.push uploadToS3(file, "#{fullVersion}/#{process.platform}/#{process.arch}/N1.rpm")
|
|
||||||
|
|
||||||
Promise.all(uploadPromises).then(done).catch (err) ->
|
else if process.platform is 'win32'
|
||||||
grunt.log.error(err)
|
uploadPromises.push uploadToS3("installer/"+winReleasesName(), "#{fullVersion}/#{process.platform}/#{process.arch}/RELEASES")
|
||||||
return false
|
uploadPromises.push uploadToS3("installer/"+winSetupName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1Setup.exe")
|
||||||
|
uploadPromises.push uploadToS3("installer/"+winNupkgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/#{winNupkgName()}")
|
||||||
|
|
||||||
|
else if process.platform is 'linux'
|
||||||
|
buildDir = grunt.config.get('nylasGruntConfig.buildDir')
|
||||||
|
files = fs.readdirSync(buildDir)
|
||||||
|
for file in files
|
||||||
|
if path.extname(file) is '.deb'
|
||||||
|
uploadPromises.push uploadToS3(file, "#{fullVersion}/#{process.platform}/#{process.arch}/N1.deb")
|
||||||
|
if path.extname(file) is '.rpm'
|
||||||
|
uploadPromises.push uploadToS3(file, "#{fullVersion}/#{process.platform}/#{process.arch}/N1.rpm")
|
||||||
|
|
||||||
|
else
|
||||||
|
grunt.fail.fatal "Unsupported platform: '#{process.platform}'"
|
||||||
|
|
||||||
|
Promise.all(uploadPromises).then(done).catch (err) ->
|
||||||
|
grunt.log.error(err)
|
||||||
|
return false
|
||||||
|
|
|
@ -61,6 +61,14 @@ module.exports = (grunt) ->
|
||||||
grunt.log.error results.stderr if exitCode != 0
|
grunt.log.error results.stderr if exitCode != 0
|
||||||
callback(error, results, exitCode)
|
callback(error, results, exitCode)
|
||||||
|
|
||||||
|
spawnP: (cmd, args=[], opts={}) -> new Promise (resolve, reject) ->
|
||||||
|
childProcess = require 'child_process'
|
||||||
|
opts.stdio ?= 'inherit'
|
||||||
|
proc = childProcess.spawn(cmd, args, opts)
|
||||||
|
proc.on 'error', grunt.fail.fatal
|
||||||
|
proc.on 'close', (exitCode, signal) ->
|
||||||
|
if exitCode is 0 then resolve() else reject(exitCode)
|
||||||
|
|
||||||
isNylasPackage: (packagePath) ->
|
isNylasPackage: (packagePath) ->
|
||||||
try
|
try
|
||||||
{engines} = grunt.file.readJSON(path.join(packagePath, 'package.json'))
|
{engines} = grunt.file.readJSON(path.join(packagePath, 'package.json'))
|
||||||
|
@ -69,12 +77,39 @@ module.exports = (grunt) ->
|
||||||
false
|
false
|
||||||
|
|
||||||
notifyAPI: (msg, callback) ->
|
notifyAPI: (msg, callback) ->
|
||||||
if (process.env("TEST_ERROR_HOOK_URL") ? "").length > 0
|
if (process.env("NYLAS_INTERNAL_HOOK_URL") ? "").length > 0
|
||||||
request.post
|
request.post
|
||||||
url: process.env("TEST_ERROR_HOOK_URL")
|
url: process.env("NYLAS_INTERNAL_HOOK_URL")
|
||||||
json:
|
json:
|
||||||
username: "Edgehill Builds"
|
username: "Edgehill Builds"
|
||||||
text: msg
|
text: msg
|
||||||
, callback
|
, callback
|
||||||
else callback()
|
else callback()
|
||||||
|
|
||||||
|
shouldPublishBuild: ->
|
||||||
|
return false unless process.env.PUBLISH_BUILD
|
||||||
|
if process.env.APPVEYOR
|
||||||
|
if process.env.APPVEYOR_PULL_REQUEST_NUMBER
|
||||||
|
grunt.log.writeln("Skipping because this is a pull request")
|
||||||
|
return false
|
||||||
|
|
||||||
|
branch = process.env.APPVEYOR_REPO_BRANCH
|
||||||
|
if branch is "master" or branch is "ci-test"
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
grunt.log.writeln("Skipping. We don't operate on branch '#{branch}''")
|
||||||
|
return false
|
||||||
|
|
||||||
|
else if process.env.TRAVIS
|
||||||
|
if process.env.TRAVIS_PULL_REQUEST isnt "false"
|
||||||
|
grunt.log.writeln("Skipping because this is a pull request")
|
||||||
|
return false
|
||||||
|
|
||||||
|
branch = process.env.TRAVIS_BRANCH
|
||||||
|
if branch is "master" or branch is "ci-test"
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
grunt.log.writeln("Skipping. We don't operate on branch '#{branch}''")
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
2
script/cibuild.ps1
Normal file
2
script/cibuild.ps1
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.\script\bootstrap.cmd
|
||||||
|
.\build\node_modules\.bin\grunt ci --gruntfile .\build\Gruntfile.coffee --statck --no-color
|
|
@ -8,6 +8,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jasmine JASMINE_CONFIG_PATH=./config.json"
|
"test": "jasmine JASMINE_CONFIG_PATH=./config.json"
|
||||||
},
|
},
|
||||||
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^3.0.5",
|
"bluebird": "^3.0.5",
|
||||||
"babel-core": "^5.8.21",
|
"babel-core": "^5.8.21",
|
||||||
|
|
Loading…
Add table
Reference in a new issue