UNPKG

ember-cli-deploy-pn-pack

Version:

A pack of ember-cli-deploy plugins for deploying PrecisionNutrition's Ember apps.

327 lines (271 loc) 8.81 kB
'use strict'; function sshToServer(username, domain) { return new Promise(function(resolve, reject) { const client = require('scp2'); let options = { host: domain, username: username, path: `/home/${username}/eternal-sledgehammer/shared/.env`, }; if (process.env.SSH_AUTH_SOCK) { options.agent = process.env.SSH_AUTH_SOCK; } else { options.privateKey = require('fs').readFileSync(`/home/${process.env.USER}/.ssh/id_rsa`); } client.scp(options, '.env.remote', function(result) { if (result === null) { return resolve(); } else { return reject(result); } }); }); } class PnConfiguration { constructor(prefix, appName, deployTarget, pluginPackConfig) { this.prefix = prefix; this.appName = appName; this.deployTarget = deployTarget; this.pluginPackConfig = pluginPackConfig; this.ENV = {}; } async getConfig() { if (this.deployTarget === 'development-postbuild') { return this.getDevConfig(); } else { return this.getStandardConfig(); } } async getDevConfig() { this.ENV.plugins = ['redis']; this.ENV.build = { environment: 'development' }; this.ENV.redis = { revisionKey: '__development__', keyPrefix: this.prefix, allowOverwrite: true, maxRecentUploads: 100, host: 'localhost', port: 6379, distDir(context) { return context.commandOptions.buildDir; } }; return this.ENV; } async getStandardConfig() { this.ENV.plugins = ['ssh-tunnel', 'build', 'gzip', 'revision-data', 'manifest', 's3:s3-all', 's3:s3-source-maps', 'redis', 'display-revisions', 'slack']; let domain = this.pluginPackConfig.domain(this.deployTarget); let username = this.pluginPackConfig.SSH_USERNAME; let bastionHost = this.pluginPackConfig.bastionHost(this.deployTarget); return sshToServer(username, bastionHost || domain).then(function() { require('dotenv').load({path: '.env.remote'}); }).then(() => { this.accessKeyId = process.env[`AWS_ACCESS_KEY_ID`]; this.secretAccessKey = process.env[`AWS_SECRET_ACCESS_KEY`]; this.ENV.build = { environment: 'production' }; if (this.deployTarget === 'aws-prod' || this.deployTarget === 'aws-qa') { this.ENV['ssh-tunnel'] = { username: this.pluginPackConfig.SSH_USERNAME, host: bastionHost, dstHost: domain, }; } else { this.ENV['ssh-tunnel'] = { username: this.pluginPackConfig.SSH_USERNAME, host: domain, }; } this.build(); this.revisionData(); this.redis(); this.s3Assets(); this.slack(); return this.ENV; }); } async getNoeConfig(masterBuild = false) { this.ENV.pipeline = { alias: { s3: { as: ['s3-all', 's3-source-maps'] }, }, disabled: { build: false, gzip: false, 'revision-data': false, manifest: false, 's3-all': false, 's3-source-maps': false, 's3-index': false, 's3-index-latest': false, 'display-revisions': false, slack: false, redis: true, 'ssh-tunnel': true, }, } if (masterBuild) { this.ENV.pipeline.alias['s3-index'] = { as: ['s3-index-latest'] } this.ENV.pipeline.disabled['s3-index'] = true; this.ENV.pipeline.disabled['s3-index-latest'] = false; } const targetPrefix = this.deployTarget.toUpperCase().replace('-', '_'); this.accessKeyId = process.env[`${targetPrefix}_AWS_ACCESS_KEY_ID`]; this.secretAccessKey = process.env[`${targetPrefix}_AWS_SECRET_ACCESS_KEY`]; this.awsRegion = process.env[`${targetPrefix}_AWS_REGION`]; if (this.pluginPackConfig.isProduction(this.deployTarget)) { this.environment = 'production'; this.citadelEnvironment = 'production'; } else { this.environment = 'staging'; this.citadelEnvironment = 'cd'; } this.citadelBucket = `precisionnutrition-${this.citadelEnvironment}-citadel`; // for compatibility with s3Index(), s3Assets() process.env['AWS_DEPLOYMENT_REGION'] = this.awsRegion; process.env['AWS_ASSET_BUCKET'] = `precisionnutrition-${this.environment}-ember-deploy`; await this.populateEnv(); this.build(); this.revisionData(); if (masterBuild) { this.s3IndexLatest(); } else { this.s3Index(); } this.s3Assets(); this.slack(); return this.ENV; } async populateEnv() { let AWS = require('aws-sdk'); let s3client = new AWS.S3({ region: this.awsRegion, accessKeyId: this.accessKeyId, secretAccessKey: this.secretAccessKey }); let keys = (process.env['DEPLOY_ENV_KEYS'] || '').split(','); let application_settings = JSON.parse(await this.getObjectContents(s3client, 'application_settings')); for (const k of keys) { await this.setEnvKey(k, application_settings[k]); } } async setEnvKey(key, value) { try { process.env[key] = value; } catch (err) { console.error(`Error loading key: ${key} (${err.message})`); throw err; } } getObjectContents(s3client, name) { return new Promise((resolve, reject) => { const params = { Bucket: this.citadelBucket, Key: `keys/${this.citadelEnvironment}/${name}` }; s3client.getObject(params, (err, data) => { if (err) { reject(err); } else { resolve(data.Body.toString().trim()); } }); }); } build() { this.ENV.build = { environment: 'production' }; } revisionData() { this.ENV["revision-data"] = { type: 'git-commit', }; } redis() { this.ENV.redis = { allowOverwrite: true, host: 'localhost', keyPrefix: this.prefix }; } s3Index() { this.ENV['s3-index'] = { accessKeyId: this.accessKeyId, secretAccessKey: this.secretAccessKey, bucket: process.env.AWS_ASSET_BUCKET, region: process.env.AWS_DEPLOYMENT_REGION, prefix: `${this.deployTarget}/${this.prefix}/revisions`, allowOverwrite: true, }; } s3IndexLatest() { this.ENV['s3-index-latest'] = { revisionKey: '__latest__', accessKeyId: this.accessKeyId, secretAccessKey: this.secretAccessKey, bucket: process.env.AWS_ASSET_BUCKET, region: process.env.AWS_DEPLOYMENT_REGION, prefix: `${this.deployTarget}/${this.prefix}/revisions`, allowOverwrite: true, }; } s3Assets() { this.ENV['s3-all'] = { accessKeyId: this.accessKeyId, secretAccessKey: this.secretAccessKey, bucket: process.env.AWS_ASSET_BUCKET, region: process.env.AWS_DEPLOYMENT_REGION, prefix: `${this.deployTarget}/${this.prefix}`, }; this.ENV['s3-source-maps'] = { accessKeyId: this.accessKeyId, secretAccessKey: this.secretAccessKey, bucket: process.env.AWS_ASSET_BUCKET, region: process.env.AWS_DEPLOYMENT_REGION, prefix: `${this.deployTarget}/${this.prefix}`, manifestPath: null, filePattern: `**/+(vendor|${this.prefix}).map`, cacheControl: 'no-cache, no-store, must-revalidate', expires: 0 }; } slack() { let appName = this.appName; this.ENV.slack = { webhookURL: process.env.SLACK_DEPLOY_WEBHOOK_ENDPOINT, didDeploy(context) { return (slack) =>{ var message; var revisionKey = context.revisionData.revisionKey; if (revisionKey && context.revisionData.activatedRevisionKey) { message = `Deployed and activated ${appName} to ${process.env.DEPLOY_TARGET} (revision ${revisionKey})`; return slack.notify(message); } }; }, didActivate(context) { if (context.commandOptions.revision) { return (slack) => { let message = `Activated ${appName} revision on ${process.env.DEPLOY_TARGET}: ${context.revisionData.activatedRevisionKey}\n`; return slack.notify(message); }; } }, }; } } module.exports = { name: require('./package').name, getConfiguration(prefix, appName, deployTarget, pluginPackConfig) { let config = new PnConfiguration(prefix, appName, deployTarget, pluginPackConfig); return config.getConfig(); }, getNoeConfiguration(prefix, appName, deployTarget, pluginPackConfig, masterBuild = false) { let config = new PnConfiguration(prefix, appName, deployTarget, pluginPackConfig); return config.getNoeConfig(masterBuild); }, };