diff --git a/.travis.yml b/.travis.yml index e43b78531..a0c190d0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,52 +1,38 @@ -env: - global: - - NYLAS_ACCESS_TOKEN=cb200be7c921f73a1c35930f6a4ac8758b271be0 - compiler: - - clang - - gcc - +- clang +- gcc matrix: include: -# Wants a c++11 compiler - - os: linux - env: NODE_VERSION=0.10 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas - - os: linux - env: NODE_VERSION=0.12 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas - - os: linux - env: NODE_VERSION=4.2 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas - - os: linux - env: NODE_VERSION=5 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas - - os: osx - env: NODE_VERSION=0.10 - - os: osx - env: NODE_VERSION=0.12 CC=clang CXX=clang++ -# osx already supports c++11 in Apple LLVM - - os: osx - env: NODE_VERSION=4.2 CC=clang CXX=clang++ - - os: osx - env: NODE_VERSION=5 CC=clang CXX=clang++ - + - os: linux + env: NODE_VERSION=0.10 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas + - os: linux + env: NODE_VERSION=0.12 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas + - os: linux + env: NODE_VERSION=4.2 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas PUBLISH_BUILD=true + - os: linux + env: NODE_VERSION=5 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas + - os: osx + env: NODE_VERSION=0.10 + - os: osx + env: NODE_VERSION=0.12 CC=clang CXX=clang++ + - os: osx + env: NODE_VERSION=4.2 CC=clang CXX=clang++ PUBLISH_BUILD=true + - os: osx + env: NODE_VERSION=5 CC=clang CXX=clang++ sudo: false - install: - - echo $CC - - echo $CXX - - clang --version - - if [ "$CC" = "gcc-4.8" ]; then gcc-4.8 -v; else gcc -v; fi - - git clone https://github.com/creationix/nvm.git /tmp/.nvm - - source /tmp/.nvm/nvm.sh - - nvm install $NODE_VERSION - - nvm use --delete-prefix $NODE_VERSION - +- echo $CC +- echo $CXX +- clang --version +- if [ "$CC" = "gcc-4.8" ]; then gcc-4.8 -v; else gcc -v; fi +- git clone https://github.com/creationix/nvm.git /tmp/.nvm +- source /tmp/.nvm/nvm.sh +- nvm install $NODE_VERSION +- nvm use --delete-prefix $NODE_VERSION before_script: - - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then - export DISPLAY=:99.0; - sh -e /etc/init.d/xvfb start; - fi - +- if [ "${TRAVIS_OS_NAME}" == "linux" ]; then export DISPLAY=:99.0; sh -e /etc/init.d/xvfb + start; fi script: script/cibuild - addons: apt: sources: @@ -59,11 +45,22 @@ addons: - git - libgnome-keyring-dev - xvfb - branches: only: - master - ci-test - git: 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= diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..ff0d2d8c4 --- /dev/null +++ b/appveyor.yml @@ -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== diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 990e04ddb..077bede0e 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -9,6 +9,9 @@ babelOptions = require '../static/babelrc' # packages in the root-level node_modules are compiled against Chrome's v8 # headers. # +# See build/resources/nylas/docs/ContinuousIntegration.md for more detailed +# instructions on how we build N1. +# # Some useful grunt options are: # --install-dir # --build-dir @@ -37,7 +40,6 @@ babelOptions = require '../static/babelrc' # installDir = /usr/local OR $INSTALL_PREFIX # binDir = /usr/local/bin # shareDir = /usr/local/share/nylas - _ = require 'underscore' packageJson = require '../package.json' @@ -332,7 +334,7 @@ module.exports = (grunt) -> outputDir: 'electron' downloadDir: electronDownloadDir 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': installer: @@ -343,7 +345,7 @@ module.exports = (grunt) -> iconUrl: 'http://edgehill.s3.amazonaws.com/static/nylas.ico' setupIcon: path.resolve(__dirname, 'resources', 'win', 'nylas.ico') certificateFile: process.env.CERTIFICATE_FILE - certificatePassword: process.env.CERTIFICATE_PASSWORD + certificatePassword: process.env.WINDOWS_CODESIGN_KEY_PASSWORD exe: 'nylas.exe' shell: @@ -375,18 +377,25 @@ module.exports = (grunt) -> buildTasks.push('set-exe-icon') if process.platform is 'win32' 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('set-version', 'lint', 'generate-asar') - ciTasks.push('test') if process.platform is 'darwin' - unless process.env.TRAVIS - ciTasks.push('codesign') - ciTasks.push('mkdmg') if process.platform is 'darwin' - ciTasks.push('mkdeb') if process.platform is 'linux' + if process.platform is "darwin" + ciTasks.push('test', 'codesign', 'mkdmg') + + else if process.platform is "linux" + ciTasks.push('mkdeb') # Only works on Fedora build machines # 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') grunt.registerTask('ci', ciTasks) diff --git a/build/resources/nylas b/build/resources/nylas index 2c6ed6956..48e33fad6 160000 --- a/build/resources/nylas +++ b/build/resources/nylas @@ -1 +1 @@ -Subproject commit 2c6ed69565b82a5f9bdd6f3ae675070a797f5cdd +Subproject commit 48e33fad632565aa1ebfbfaa84e555c36a7d6572 diff --git a/build/resources/ssh/nylas-n1-ci-ssh-secure-file.enc b/build/resources/ssh/nylas-n1-ci-ssh-secure-file.enc new file mode 100755 index 000000000..679920ac8 Binary files /dev/null and b/build/resources/ssh/nylas-n1-ci-ssh-secure-file.enc differ diff --git a/build/resources/ssh/nylas-n1-ci-ssh.openssl.enc b/build/resources/ssh/nylas-n1-ci-ssh.openssl.enc new file mode 100644 index 000000000..935f01e4a Binary files /dev/null and b/build/resources/ssh/nylas-n1-ci-ssh.openssl.enc differ diff --git a/build/tasks/codesign-task.coffee b/build/tasks/codesign-task.coffee index 63bf636ee..30534d78b 100644 --- a/build/tasks/codesign-task.coffee +++ b/build/tasks/codesign-task.coffee @@ -1,61 +1,133 @@ +_ = require 'underscore' path = require 'path' fs = require 'fs-plus' -# Edgehill introduces the KEYCHAIN_ACCESS environment variable. This is -# injected via Jenkins. It is of the form: +# Codesigning is a Mac-only process that requires a valid Apple +# 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 # -# The KEYCHAIN_ACCESS variable is saved in a Jenkins Credential and -# injected via the Credentials Binding Plugin. +# In the case of Travis, we need to setup a temp keychain from encrypted files +# 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) -> - {spawn} = require('./task-helpers')(grunt) + {spawnP, shouldPublishBuild} = require('./task-helpers')(grunt) + tmpKeychain = "n1-build.keychain" grunt.registerTask 'codesign', 'Codesign the app', -> done = @async() + return unless process.platform is 'darwin' - if process.platform is 'darwin' and (process.env.XCODE_KEYCHAIN or process.env.KEYCHAIN_ACCESS) - unlockKeychain (error) -> - if error? - done(error) - else - signApp(done) - else - signApp(done) - - unlockKeychain = (callback) -> - cmd = 'security' - {XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN, KEYCHAIN_ACCESS} = process.env - - if KEYCHAIN_ACCESS? + {XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN} = process.env + if XCODE_KEYCHAIN? and XCODE_KEYCHAIN_PASSWORD? + unlockKeychain(XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD) + .then(signApp) + .then(verifyApp).then(done).catch(grunt.fail.fatal) + else if process.env.KEYCHAIN_ACCESS? [XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD] = KEYCHAIN_ACCESS.split(":") - - args = ['unlock-keychain', '-p', XCODE_KEYCHAIN_PASSWORD, XCODE_KEYCHAIN] - spawn {cmd, args}, (error) -> callback(error) - - signApp = (callback) -> - switch process.platform - when 'darwin' - cmd = 'codesign' - args = ['--deep', '--force', '--verbose', '--sign', 'Developer ID Application: InboxApp, Inc.', grunt.config.get('nylasGruntConfig.shellAppDir')] - spawn {cmd, args}, (error) -> callback(error) - 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() + unlockKeychain(XCODE_KEYCHAIN, XCODE_KEYCHAIN_PASSWORD) + .then(signApp) + .then(verifyApp).then(done).catch(grunt.fail.fatal) + else if process.env.TRAVIS + if shouldPublishBuild() + buildTravisKeychain() + .then(_.partial(signApp, tmpKeychain)) + .then(verifyApp) + .then(cleanupKeychain) + .then(done).catch(grunt.fail.fatal) 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} diff --git a/build/tasks/publish-nylas-build-task.coffee b/build/tasks/publish-nylas-build-task.coffee index 6365f0981..d87c165a5 100644 --- a/build/tasks/publish-nylas-build-task.coffee +++ b/build/tasks/publish-nylas-build-task.coffee @@ -51,10 +51,10 @@ module.exports = (grunt) -> resolve() 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) -> request.post - url: process.env.PUBLISH_SLACK_HOOK + url: process.env.NYLAS_INTERNAL_HOOK_URL json: username: "Edgehill Builds" text: msg @@ -126,11 +126,9 @@ module.exports = (grunt) -> awsSecret = process.env.AWS_SECRET_ACCESS_KEY ? "" if awsKey.length is 0 - grunt.log.error "Please set the AWS_ACCESS_KEY_ID environment variable" - return false + grunt.fail.fatal "Please set the AWS_ACCESS_KEY_ID environment variable" if awsSecret.length is 0 - grunt.log.error "Please set the AWS_SECRET_ACCESS_KEY environment variable" - return false + grunt.fail.fatal "Please set the AWS_SECRET_ACCESS_KEY environment variable" s3Client = s3.createClient s3Options: @@ -139,25 +137,34 @@ module.exports = (grunt) -> done = @async() - populateVersion().then -> - runEmailIntegrationTest().then -> - uploadPromises = [] - if process.platform is 'darwin' - uploadPromises.push uploadToS3(dmgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.dmg") - uploadPromises.push uploadZipToS3(appName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.zip") - if process.platform is 'win32' - uploadPromises.push uploadToS3("installer/"+winReleasesName(), "#{fullVersion}/#{process.platform}/#{process.arch}/RELEASES") - uploadPromises.push uploadToS3("installer/"+winSetupName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1Setup.exe") - uploadPromises.push uploadToS3("installer/"+winNupkgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/#{winNupkgName()}") - 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") + populateVersion() + .then -> + if process.env.RUN_APPLE_SCRIPT_INTEGRATION + runEmailIntegrationTest() + else Promise.resolve() + .then -> + uploadPromises = [] + if process.platform is 'darwin' + uploadPromises.push uploadToS3(dmgName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.dmg") + uploadPromises.push uploadZipToS3(appName(), "#{fullVersion}/#{process.platform}/#{process.arch}/N1.zip") - Promise.all(uploadPromises).then(done).catch (err) -> - grunt.log.error(err) - return false + else if process.platform is 'win32' + uploadPromises.push uploadToS3("installer/"+winReleasesName(), "#{fullVersion}/#{process.platform}/#{process.arch}/RELEASES") + 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 diff --git a/build/tasks/task-helpers.coffee b/build/tasks/task-helpers.coffee index fa0fb6f92..23c5a916e 100644 --- a/build/tasks/task-helpers.coffee +++ b/build/tasks/task-helpers.coffee @@ -61,6 +61,14 @@ module.exports = (grunt) -> grunt.log.error results.stderr if exitCode != 0 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) -> try {engines} = grunt.file.readJSON(path.join(packagePath, 'package.json')) @@ -69,12 +77,39 @@ module.exports = (grunt) -> false notifyAPI: (msg, callback) -> - if (process.env("TEST_ERROR_HOOK_URL") ? "").length > 0 + if (process.env("NYLAS_INTERNAL_HOOK_URL") ? "").length > 0 request.post - url: process.env("TEST_ERROR_HOOK_URL") + url: process.env("NYLAS_INTERNAL_HOOK_URL") json: username: "Edgehill Builds" text: msg , 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 + diff --git a/script/cibuild.ps1 b/script/cibuild.ps1 new file mode 100644 index 000000000..5b793db9b --- /dev/null +++ b/script/cibuild.ps1 @@ -0,0 +1,2 @@ +.\script\bootstrap.cmd +.\build\node_modules\.bin\grunt ci --gruntfile .\build\Gruntfile.coffee --statck --no-color diff --git a/spec_integration/package.json b/spec_integration/package.json index ecde74ed7..93a7df364 100644 --- a/spec_integration/package.json +++ b/spec_integration/package.json @@ -8,6 +8,7 @@ "scripts": { "test": "jasmine JASMINE_CONFIG_PATH=./config.json" }, + "license": "GPL-3.0", "dependencies": { "bluebird": "^3.0.5", "babel-core": "^5.8.21",