diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f1934493..80163aa61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ + +# [1.4.0](https://github.com/bleenco/abstruse/compare/v1.3.6...v1.4.0) (2017-12-04) + + +### Bug Fixes + +* **containers:** remove killed containers ([b90e6df](https://github.com/bleenco/abstruse/commit/b90e6df)) +* **socket:** fix build permissions on new triggered build appearing on UI ([6c25f23](https://github.com/bleenco/abstruse/commit/6c25f23)) + + +### Features + +* **deploy:** support for aws codeDeploy service ([252afd0](https://github.com/bleenco/abstruse/commit/252afd0)) +* **deploy:** support for deploy to aws s3 ([f7b35b5](https://github.com/bleenco/abstruse/commit/f7b35b5)) + + + ## [1.3.6](https://github.com/bleenco/abstruse/compare/v1.3.5...v1.3.6) (2017-11-21) diff --git a/package.json b/package.json index a51ad56b1..efbf70335 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "abstruse", - "version": "1.3.6", + "version": "1.4.0", "description": "Abstruse CI", "bin": { "abstruse": "./dist/api/index.js" diff --git a/src/api/deploy/aws-code-deploy.ts b/src/api/deploy/aws-code-deploy.ts index 2e12d9222..c33ae881e 100644 --- a/src/api/deploy/aws-code-deploy.ts +++ b/src/api/deploy/aws-code-deploy.ts @@ -7,219 +7,220 @@ import { error } from 'util'; import chalk from 'chalk'; export function codeDeploy( - preferences: any, container: string, variables: string[]): Observable { - return new Observable((observer: Observer) => { - - // 1. check preferences - const application = preferences.application; - const applicationRevision = preferences.applicationRevision; - const deployGroup = preferences.deploymentGroup; - const arn = findFromEnvVariables(variables, 'arn') || preferences.arn; - let applicationStore = preferences.applicationStore; - let applicationType = preferences.applicationType; - let applicationFileName = preferences.applicationFile; - let accessKeyId = findFromEnvVariables(variables, 'accessKeyId'); - let secretAccessKey = findFromEnvVariables(variables, 'secretAccessKey'); - let region = findFromEnvVariables(variables, 'region'); - let errors = false; - - if (!application) { - const msg = chalk.red('application is not set in yml config file \r\n'); + preferences: any, container: string, variables: string[] +): Observable { + return new Observable((observer: Observer) => { + + // 1. check preferences + const application = preferences.application; + const applicationRevision = preferences.applicationRevision; + const deployGroup = preferences.deploymentGroup; + const arn = findFromEnvVariables(variables, 'arn') || preferences.arn; + let applicationStore = preferences.applicationStore; + let applicationType = preferences.applicationType; + let applicationFileName = preferences.applicationFile; + let accessKeyId = findFromEnvVariables(variables, 'accessKeyId'); + let secretAccessKey = findFromEnvVariables(variables, 'secretAccessKey'); + let region = findFromEnvVariables(variables, 'region'); + let errors = false; + + if (!application) { + const msg = chalk.red('application is not set in yml config file \r\n'); + observer.next({ type: 'data', data: msg}); + errors = true; + } + + if (!applicationStore) { + applicationStore = 's3'; + } + + if (!applicationType) { + applicationType = 'zip'; + } + + if (!applicationFileName) { + applicationFileName = `${application}.${applicationType}`; + } + + if (!deployGroup) { + const msg = chalk.red('deploymentGroup is not set in yml config file \r\n'); + observer.next({ type: 'data', data: msg}); + errors = true; + } + + if (!accessKeyId) { + if (preferences && preferences.accessKeyId) { + accessKeyId = preferences.accessKeyId; + } else { + const msg = chalk.red('accessKeyId is not set in environment ' + + 'variables or in yml config \r\n'); observer.next({ type: 'data', data: msg}); errors = true; } + } - if (!applicationStore) { - applicationStore = 's3'; - } - - if (!applicationType) { - applicationType = 'zip'; - } - - if (!applicationFileName) { - applicationFileName = `${application}.${applicationType}`; - } - - if (!deployGroup) { - const msg = chalk.red('deploymentGroup is not set in yml config file \r\n'); + if (!secretAccessKey) { + if (preferences && preferences.secretAccessKey) { + secretAccessKey = preferences.secretAccessKey; + } else { + const msg = chalk.red('secretAccessKey is not set in environment variables or' + + ' in yml config \r\n'); observer.next({ type: 'data', data: msg}); errors = true; } + } - if (!accessKeyId) { - if (preferences && preferences.accessKeyId) { - accessKeyId = preferences.accessKeyId; - } else { - const msg = chalk.red('accessKeyId is not set in environment ' - + 'variables or in yml config \r\n'); - observer.next({ type: 'data', data: msg}); - errors = true; - } - } - - if (!secretAccessKey) { - if (preferences && preferences.secretAccessKey) { - secretAccessKey = preferences.secretAccessKey; - } else { - const msg = chalk.red('secretAccessKey is not set in environment variables or' - + ' in yml config \r\n'); - observer.next({ type: 'data', data: msg}); - errors = true; - } - } - - if (!region) { - if (preferences && preferences.region) { - region = preferences.region; - } else { - const msg = chalk.red('region is not set in environment variables or in yml config \r\n'); - observer.next({ type: 'data', data: msg}); - errors = true; - } + if (!region) { + if (preferences && preferences.region) { + region = preferences.region; + } else { + const msg = chalk.red('region is not set in environment variables or in yml config \r\n'); + observer.next({ type: 'data', data: msg}); + errors = true; } + } + + if (!errors) { + let msg = style.yellow.open + style.bold.open + '==> deploy started' + + style.bold.close + style.yellow.close + '\r\n'; + observer.next({ type: 'data', data: msg }); + + // 2. install awscli and set credentials + let command = { type: CommandType.deploy, command: 'sudo apt-get install awscli -y' }; + attachExec(container, command) + .toPromise() + .then(result => { + if (!(result && result.data === 0)) { + const msg = `apt-get install awscli failed`; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - if (!errors) { - let msg = style.yellow.open + style.bold.open + '==> deploy started' + - style.bold.close + style.yellow.close + '\r\n'; - observer.next({ type: 'data', data: msg }); - - // 2. install awscli and set credentials - let command = { type: CommandType.deploy, command: 'sudo apt-get install awscli -y' }; - attachExec(container, command) - .toPromise() - .then(result => { - if (!(result && result.data === 0)) { - const msg = `apt-get install awscli failed`; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } - - command = { - type: CommandType.deploy, - command: `aws configure set aws_access_key_id ${accessKeyId}` - }; + command = { + type: CommandType.deploy, + command: `aws configure set aws_access_key_id ${accessKeyId}` + }; + + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'aws configure aws_access_key_id failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'aws configure aws_access_key_id failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + command = { + type: CommandType.deploy, + command: `aws configure set aws_secret_access_key ${secretAccessKey}` + }; + + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'aws configure aws_secret_access_key failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - command = { - type: CommandType.deploy, - command: `aws configure set aws_secret_access_key ${secretAccessKey}` - }; + command = { + type: CommandType.deploy, command: `aws configure set region ${region}` + }; + + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'aws configure region failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'aws configure aws_secret_access_key failed'; + // 3. check if deployment-group exists (otherwise create it) + return depGroupExists(container, application, deployGroup); + }) + .then(exists => { + if (!exists) { + if (arn) { + command = { + type: CommandType.deploy, + command: `aws deploy create-deployment-group --application-name ${application}` + + ` --deployment-group-name ${deployGroup} --service-role-arn ${arn}` + }; + + return attachExec(container, command) + .toPromise() + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'create-deployment-group failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } + + Promise.resolve(); + }); + } else { + const msg = `deployment group doesn't exists and arn parameter is empty`; observer.next({ type: 'containerError', data: msg}); return Promise.reject(-1); } + } else { + Promise.resolve(); + } + }) + .then(() => { + // 4. create deployment + let location = `bucket=${application},bundleType=${applicationType},` + + `key=${applicationFileName}`; + if (applicationRevision) { + location += `,eTag=${applicationRevision}`; + } - command = { - type: CommandType.deploy, command: `aws configure set region ${region}` - }; - - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'aws configure region failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + command = { + type: CommandType.deploy, + command: `aws deploy create-deployment --application-name ${application}` + + ` --deployment-group-name ${deployGroup}` + }; + + if (applicationStore === 's3') { + command.command += ` --s3-location ${location}`; + } else if (applicationStore === 'github') { + command.command += ` --github-location ${location}`; + } else { + const msg = 'ApplicationStore can only be s3 or github,' + + ' other stores are not supported'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - // 3. check if deployment-group exists (otherwise create it) - return depGroupExists(container, application, deployGroup); - }) - .then(exists => { - if (!exists) { - if (arn) { - command = { - type: CommandType.deploy, - command: `aws deploy create-deployment-group --application-name ${application}` - + ` --deployment-group-name ${deployGroup} --service-role-arn ${arn}` - }; - - return attachExec(container, command) - .toPromise() - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'create-deployment-group failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } - - Promise.resolve(); - }); - } else { - const msg = `deployment group doesn't exists and arn parameter is empty`; + return attachExec(container, command) + .toPromise() + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'create-deployment failed'; observer.next({ type: 'containerError', data: msg}); return Promise.reject(-1); } - } else { - Promise.resolve(); - } - }) - .then(() => { - // 4. create deployment - let location = `bucket=${application},bundleType=${applicationType},` - + `key=${applicationFileName}`; - if (applicationRevision) { - location += `,eTag=${applicationRevision}`; - } - - command = { - type: CommandType.deploy, - command: `aws deploy create-deployment --application-name ${application}` - + ` --deployment-group-name ${deployGroup}` - }; - - if (applicationStore === 's3') { - command.command += ` --s3-location ${location}`; - } else if (applicationStore === 'github') { - command.command += ` --github-location ${location}`; - } else { - const msg = 'ApplicationStore can only be s3 or github,' - + ' other stores are not supported'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } - return attachExec(container, command) - .toPromise() - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'create-deployment failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } - - Promise.resolve(); - }); - }) - .then(() => { - let msg = style.yellow.open + style.bold.open + '==> deployment completed successfully!' - + style.bold.close + style.yellow.close + '\r\n'; - observer.next({ type: 'data', data: msg }); - observer.complete(); - }) - .catch(err => { - observer.error(err); - observer.complete(); - }); - } else { - observer.error(-1); - observer.complete(); - } - }); + Promise.resolve(); + }); + }) + .then(() => { + let msg = style.yellow.open + style.bold.open + '==> deployment completed successfully!' + + style.bold.close + style.yellow.close + '\r\n'; + observer.next({ type: 'data', data: msg }); + observer.complete(); + }) + .catch(err => { + observer.error(err); + observer.complete(); + }); + } else { + observer.error(-1); + observer.complete(); + } + }); } function depGroupExists(container, application, group): Promise { diff --git a/src/api/deploy/aws-s3.ts b/src/api/deploy/aws-s3.ts index 18b2315c5..87c789e03 100644 --- a/src/api/deploy/aws-s3.ts +++ b/src/api/deploy/aws-s3.ts @@ -6,192 +6,193 @@ import * as style from 'ansi-styles'; import chalk from 'chalk'; export function s3Deploy( - preferences: any, container: string, variables: string[]): Observable { - return new Observable((observer: Observer) => { - - // 1. check preferences - const bucket = preferences.bucket; - let accessKeyId = findFromEnvVariables(variables, 'accessKeyId'); - let secretAccessKey = findFromEnvVariables(variables, 'secretAccessKey'); - let region = findFromEnvVariables(variables, 'region'); - let errors = false; - - if (!bucket) { - const msg = chalk.red('bucket is not set in yml config file \r\n'); + preferences: any, container: string, variables: string[] +): Observable { + return new Observable((observer: Observer) => { + + // 1. check preferences + const bucket = preferences.bucket; + let accessKeyId = findFromEnvVariables(variables, 'accessKeyId'); + let secretAccessKey = findFromEnvVariables(variables, 'secretAccessKey'); + let region = findFromEnvVariables(variables, 'region'); + let errors = false; + + if (!bucket) { + const msg = chalk.red('bucket is not set in yml config file \r\n'); + observer.next({ type: 'data', data: msg}); + errors = true; + } + + if (!accessKeyId) { + if (preferences && preferences.accessKeyId) { + accessKeyId = preferences.accessKeyId; + } else { + const msg = chalk.red('accessKeyId is not set in environment ' + + 'variables or in yml config \r\n'); observer.next({ type: 'data', data: msg}); errors = true; } + } - if (!accessKeyId) { - if (preferences && preferences.accessKeyId) { - accessKeyId = preferences.accessKeyId; - } else { - const msg = chalk.red('accessKeyId is not set in environment ' - + 'variables or in yml config \r\n'); - observer.next({ type: 'data', data: msg}); - errors = true; - } + if (!secretAccessKey) { + if (preferences && preferences.secretAccessKey) { + secretAccessKey = preferences.secretAccessKey; + } else { + const msg = chalk.red('secretAccessKey is not set in environment variables or' + + ' in yml config \r\n'); + observer.next({ type: 'data', data: msg}); + errors = true; } + } - if (!secretAccessKey) { - if (preferences && preferences.secretAccessKey) { - secretAccessKey = preferences.secretAccessKey; - } else { - const msg = chalk.red('secretAccessKey is not set in environment variables or' - + ' in yml config \r\n'); - observer.next({ type: 'data', data: msg}); - errors = true; - } + if (!region) { + if (preferences && preferences.region) { + region = preferences.region; + } else { + const msg = + chalk.red('region is not set in environment variables or in yml config file \r\n'); + observer.next({ type: 'data', data: msg}); + errors = true; } - - if (!region) { - if (preferences && preferences.region) { - region = preferences.region; - } else { - const msg = - chalk.red('region is not set in environment variables or in yml config file \r\n'); - observer.next({ type: 'data', data: msg}); - errors = true; + } + + if (!errors) { + let msg = style.yellow.open + style.bold.open + '==> deploy started' + + style.bold.close + style.yellow.close + '\r\n'; + observer.next({ type: 'data', data: msg }); + + // 2. check if appspec.yml exists (otherwise create it) + appSpecExists(container).then(exists => { + let commands = []; + if (!exists) { + commands.push( + { type: CommandType.deploy, command: `echo version: 0.0 >> appspec.yml` }, + { type: CommandType.deploy, command: `echo os: linux >> appspec.yml` }, + { type: CommandType.deploy, command: `echo files: >> appspec.yml` }, + { type: CommandType.deploy, command: `echo ' - source: ./' >> appspec.yml` }, + { type: CommandType.deploy, command: `echo ' destination: ./' >> appspec.yml` } + ); } - } - if (!errors) { - let msg = style.yellow.open + style.bold.open + '==> deploy started' + - style.bold.close + style.yellow.close + '\r\n'; - observer.next({ type: 'data', data: msg }); - - // 2. check if appspec.yml exists (otherwise create it) - appSpecExists(container).then(exists => { - let commands = []; - if (!exists) { - commands.push( - { type: CommandType.deploy, command: `echo version: 0.0 >> appspec.yml` }, - { type: CommandType.deploy, command: `echo os: linux >> appspec.yml` }, - { type: CommandType.deploy, command: `echo files: >> appspec.yml` }, - { type: CommandType.deploy, command: `echo ' - source: ./' >> appspec.yml` }, - { type: CommandType.deploy, command: `echo ' destination: ./' >> appspec.yml` } - ); - } - - return Observable - .concat(...commands.map(command => attachExec(container, command))) - .toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = `creating appspec.yml failed`; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + return Observable + .concat(...commands.map(command => attachExec(container, command))) + .toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = `creating appspec.yml failed`; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - // 3. install awscli and set credentials - let command = { type: CommandType.deploy, command: 'sudo apt-get install awscli -y' }; + // 3. install awscli and set credentials + let command = { type: CommandType.deploy, command: 'sudo apt-get install awscli -y' }; - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = `apt-get install awscli failed`; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = `apt-get install awscli failed`; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - let command = { - type: CommandType.deploy, - command: `aws configure set aws_access_key_id ${accessKeyId}` - }; - - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'aws configure aws_access_key_id failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + let command = { + type: CommandType.deploy, + command: `aws configure set aws_access_key_id ${accessKeyId}` + }; + + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'aws configure aws_access_key_id failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - let command = { - type: CommandType.deploy, - command: `aws configure set aws_secret_access_key ${secretAccessKey}` - }; - - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'aws configure aws_secret_access_key failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + let command = { + type: CommandType.deploy, + command: `aws configure set aws_secret_access_key ${secretAccessKey}` + }; + + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'aws configure aws_secret_access_key failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - let command = { - type: CommandType.deploy, command: `aws configure set region ${region}` - }; - - return attachExec(container, command).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = 'aws configure region failed'; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + let command = { + type: CommandType.deploy, command: `aws configure set region ${region}` + }; + + return attachExec(container, command).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = 'aws configure region failed'; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - // 4. check if application allready exists (otherwise create it) - return applicationExists(container, preferences.bucket); - }) - .then(exists => { - let application = [ - { type: CommandType.deploy, command: `aws s3 mb s3://${preferences.bucket}` } - ]; - - if (!exists) { - let cmd = `aws deploy create-application --application-name ${preferences.bucket}`; - application.push( { type: CommandType.deploy, command: cmd } ); - } + // 4. check if application allready exists (otherwise create it) + return applicationExists(container, preferences.bucket); + }) + .then(exists => { + let application = [ + { type: CommandType.deploy, command: `aws s3 mb s3://${preferences.bucket}` } + ]; + + if (!exists) { + let cmd = `aws deploy create-application --application-name ${preferences.bucket}`; + application.push( { type: CommandType.deploy, command: cmd } ); + } - return Observable - .concat(...application.map(command => attachExec(container, command))) - .toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = `aws deploy failed`; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + return Observable + .concat(...application.map(command => attachExec(container, command))) + .toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = `aws deploy failed`; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - // 5. deploy - const zipName = preferences.bucket; - const deploy = { - type: CommandType.deploy, - command: `aws deploy push --application-name ${preferences.bucket}` - + ` --s3-location s3://${preferences.bucket}/${zipName}.zip` - }; - - return attachExec(container, deploy).toPromise(); - }) - .then(result => { - if (!(result && result.data === 0)) { - const msg = `aws deploy push failed`; - observer.next({ type: 'containerError', data: msg}); - return Promise.reject(-1); - } + // 5. deploy + const zipName = preferences.bucket; + const deploy = { + type: CommandType.deploy, + command: `aws deploy push --application-name ${preferences.bucket}` + + ` --s3-location s3://${preferences.bucket}/${zipName}.zip` + }; + + return attachExec(container, deploy).toPromise(); + }) + .then(result => { + if (!(result && result.data === 0)) { + const msg = `aws deploy push failed`; + observer.next({ type: 'containerError', data: msg}); + return Promise.reject(-1); + } - let msg = style.yellow.open + style.bold.open + '==> deployment completed successfully!' - + style.bold.close + style.yellow.close + '\r\n'; - observer.next({ type: 'data', data: msg }); - observer.complete(); - }) - .catch(err => { - observer.error(err); - observer.complete(); - }); - } else { - observer.error(-1); + let msg = style.yellow.open + style.bold.open + '==> deployment completed successfully!' + + style.bold.close + style.yellow.close + '\r\n'; + observer.next({ type: 'data', data: msg }); observer.complete(); - } - }); + }) + .catch(err => { + observer.error(err); + observer.complete(); + }); + } else { + observer.error(-1); + observer.complete(); + } + }); } function appSpecExists(container): Promise { diff --git a/src/app/styles/colors.sass b/src/app/styles/colors.sass index fed375a75..d309c34a1 100644 --- a/src/app/styles/colors.sass +++ b/src/app/styles/colors.sass @@ -1,4 +1,4 @@ -$background: #fafafc +$background: #fff $background-secondary: #222C3C $background-button: #F1F5F7 $color: #354052 diff --git a/src/app/styles/nav.sass b/src/app/styles/nav.sass index ef4566268..22a7989a2 100644 --- a/src/app/styles/nav.sass +++ b/src/app/styles/nav.sass @@ -1,6 +1,6 @@ .header width: 100% - height: 50px + height: 65px background: $header-background border-bottom: 1px solid $border display: flex