From 4d70559f3c8013d8f524bf60526292c4590d19af Mon Sep 17 00:00:00 2001 From: Hunter Loftis Date: Thu, 29 Sep 2016 08:54:30 -0400 Subject: [PATCH 01/24] 4.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec620a4..fedb521 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "heroku-container-registry", - "version": "4.1.0", + "version": "4.1.1", "topic": "container", "description": "Use containers to build and deploy Heroku apps", "main": "index.js", From d7cf20283749613979ff0e72431608074ac59cd2 Mon Sep 17 00:00:00 2001 From: Hunter Loftis Date: Fri, 30 Sep 2016 14:28:43 -0400 Subject: [PATCH 02/24] push multiple, recursive, choose nearest, warn multiple, fail ambiguous Dockerfile matches --- commands/login.js | 6 +-- commands/logout.js | 5 +- commands/push.js | 114 ++++++++++++++++++++++++++++++++++++--------- lib/log.js | 6 +++ package.json | 1 + 5 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 lib/log.js diff --git a/commands/login.js b/commands/login.js index df154c7..51fb7cc 100644 --- a/commands/login.js +++ b/commands/login.js @@ -3,6 +3,7 @@ const cli = require('heroku-cli-util'); const co = require('co'); const child = require('child_process'); +const log = require('../lib/log'); module.exports = function(topic) { return { @@ -26,6 +27,7 @@ function* login(context, heroku) { } catch (err) { cli.error(`Error: docker login exited with ${ err }`); + cli.hush(err.stack || err); } } @@ -37,9 +39,7 @@ function dockerLogin(registry, password, verbose) { `--password=${ password }`, registry ]; - if (verbose) { - console.log(['> docker'].concat(args).join(' ')); - } + log(verbose, args); child.spawn('docker', args, { stdio: 'inherit' }) .on('exit', (code, signal) => { if (signal || code) reject(signal || code); diff --git a/commands/logout.js b/commands/logout.js index 5f15187..da4e7ba 100644 --- a/commands/logout.js +++ b/commands/logout.js @@ -3,6 +3,7 @@ const cli = require('heroku-cli-util'); const co = require('co'); const child = require('child_process'); +const log = require('../lib/log'); module.exports = function(topic) { return { @@ -34,9 +35,7 @@ function dockerLogout(registry, verbose) { 'logout', registry ]; - if (verbose) { - console.log(['> docker'].concat(args).join(' ')); - } + log(verbose, args); child.spawn('docker', args, { stdio: 'inherit' }) .on('exit', (code, signal) => { if (signal || code) reject(signal || code); diff --git a/commands/push.js b/commands/push.js index e816541..872aad8 100644 --- a/commands/push.js +++ b/commands/push.js @@ -3,6 +3,12 @@ const cli = require('heroku-cli-util'); const co = require('co'); const child = require('child_process'); +const log = require('../lib/log'); +const fs = require('fs'); +const path = require('path'); +const glob = require('glob'); + +const DOCKERFILE_REGEX = /\/Dockerfile(.\w*)?$/; module.exports = function(topic) { return { @@ -11,8 +17,10 @@ module.exports = function(topic) { description: 'Builds, then pushes a Docker image to deploy your Heroku app', needsApp: true, needsAuth: true, - args: [{ name: 'process', optional: true }], - flags: [{ name: 'verbose', char: 'v', hasValue: false }], + variableArgs: true, + flags: [ + { name: 'verbose', char: 'v', hasValue: false } + ], run: cli.command(co.wrap(push)) }; }; @@ -20,37 +28,46 @@ module.exports = function(topic) { function* push(context, heroku) { let herokuHost = process.env.HEROKU_HOST || 'heroku.com'; let registry = `registry.${ herokuHost }`; - let proc = context.args.process || 'web'; - let resource = `${ registry }/${ context.app }/${ proc }`; + let dockerfiles = getDockerfiles(context.cwd, true); + let possibleJobs = getJobs(`${ registry }/${ context.app }`, context.args, dockerfiles); + let jobs = chooseJobs(possibleJobs); + + if (!jobs.length) { + cli.warn('No images to push'); + process.exit(); + } try { - let build = yield buildImage(resource, context.cwd, context.flags.verbose); + for (let job of jobs) { + cli.log(`Building ${ job.name } (${ job.dockerfile })`); + yield buildImage(job.dockerfile, job.resource, context.flags.verbose); + } } catch (err) { cli.error(`Error: docker build exited with ${ err }`); + cli.hush(err.stack || err); process.exit(1); } try { - let push = yield pushImage(resource, context.flags.verbose); + cli.log(`Pushing ${ jobs.length } images...`); + for (let job of jobs) { + cli.log(`Pushing ${ job.name } (${ job.dockerfile })`); + yield pushImage(job.resource, context.flags.verbose); + } } catch (err) { cli.error(`Error: docker push exited with ${ err }`); + cli.hush(err.stack || err); process.exit(1); } } -function buildImage(resource, cwd, verbose) { +function buildImage(dockerfile, resource, verbose) { return new Promise((resolve, reject) => { - let args = [ - 'build', - '-t', - resource, - cwd - ]; - if (verbose) { - console.log(['> docker'].concat(args).join(' ')); - } + let cwd = path.dirname(dockerfile); + let args = [ 'build', '-f', dockerfile, '-t', resource, cwd ]; + log(verbose, args); child.spawn('docker', args, { stdio: 'inherit' }) .on('exit', (code, signal) => { if (signal || code) reject(signal || code); @@ -61,13 +78,8 @@ function buildImage(resource, cwd, verbose) { function pushImage(resource, verbose) { return new Promise((resolve, reject) => { - let args = [ - 'push', - resource - ]; - if (verbose) { - console.log(['> docker'].concat(args).join(' ')); - } + let args = [ 'push', resource ]; + log(verbose, args); child.spawn('docker', args, { stdio: 'inherit' }) .on('exit', (code, signal) => { if (signal || code) reject(signal || code); @@ -75,3 +87,59 @@ function pushImage(resource, verbose) { }); }); } + +function getDockerfiles(dir, recursive) { + let match = recursive ? '**/Dockerfile?(.)*' : 'Dockerfile?(.)*'; + let dockerfiles = glob.sync(match, { cwd: dir, nonull: false, nodir: true }); + return dockerfiles.map(file => path.join(dir, file)); +} + +function getJobs(resourceRoot, procs, dockerfiles) { + return dockerfiles + // convert all Dockerfiles into job Objects + .map((dockerfile) => { + let match = dockerfile.match(DOCKERFILE_REGEX); + if (!match) return; + let proc = (match[1] || '.web').slice(1); + return { + name: proc, + resource: `${ resourceRoot }/${ proc }`, + dockerfile: dockerfile, + postfix: path.basename(dockerfile) === 'Dockerfile' ? 0 : 1, + depth: path.normalize(dockerfile).split(path.sep).length + }; + }) + // if process types have been specified, filter non matches out + .filter(job => { + return job && (!procs.length || procs.indexOf(job.name) !== -1); + }) + // prefer closer Dockerfiles, then prefer Dockerfile over Dockerfile.web + .sort((a, b) => { + return a.depth - b.depth || a.postfix - b.postfix; + }) + // group all Dockerfiles for the same process type together + .reduce((jobs, job) => { + jobs[job.name] = jobs[job.name] || []; + jobs[job.name].push(job); + return jobs; + }, {}); +} + +function chooseJobs(jobs) { + return Object.keys(jobs).map(name => { + let group = jobs[name]; + if (group.length > 1) { + let ambiguous = group.map(job => job.dockerfile); + if (group[1].depth === group[0].depth) { + if (group[1].postfix === group[0].postfix) { + cli.error(`Cannot build with ambiguous Dockerfiles:\n${ ambiguous.join('\n') }`); + process.exit(1); + } + } + cli.warn(`Using nearest match for the '${ group[0].name }' process:`); + cli.warn(`${ ambiguous[0] } (used)`); + cli.warn(`${ ambiguous.slice(1).join('\n') }`); + } + return group[0]; + }); +} diff --git a/lib/log.js b/lib/log.js new file mode 100644 index 0000000..fa0e6eb --- /dev/null +++ b/lib/log.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = (visible, args) => { + if (!visible) return; + console.log(`> docker ${ args.join(' ') }`); +}; diff --git a/package.json b/package.json index fedb521..9c6acfb 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "camelcase": "1.0.2", "co": "4.6.0", "dotenv": "^1.1.0", + "glob": "7.1.0", "heroku-cli-util": "^1.8.1", "heroku-client": "^1.9.1", "is-there": "4.0.0", From e66a79b2cb01dadd1b7c6e77024547ad5f66ad8b Mon Sep 17 00:00:00 2001 From: jbyrum Date: Wed, 5 Oct 2016 11:07:45 -0700 Subject: [PATCH 03/24] Update push.js * More explicit error messages --- commands/push.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/push.js b/commands/push.js index 872aad8..9695478 100644 --- a/commands/push.js +++ b/commands/push.js @@ -132,11 +132,11 @@ function chooseJobs(jobs) { let ambiguous = group.map(job => job.dockerfile); if (group[1].depth === group[0].depth) { if (group[1].postfix === group[0].postfix) { - cli.error(`Cannot build with ambiguous Dockerfiles:\n${ ambiguous.join('\n') }`); + cli.error(`Cannot build. More than one Dockerfile defines the process type:\n${ ambiguous.join('\n') }`); process.exit(1); } } - cli.warn(`Using nearest match for the '${ group[0].name }' process:`); + cli.warn(`Using nearest match for '${ group[0].name }' process type:`); cli.warn(`${ ambiguous[0] } (used)`); cli.warn(`${ ambiguous.slice(1).join('\n') }`); } From a66925e8cb2e6a46e6fc0a1efad0a780d0d0dfcc Mon Sep 17 00:00:00 2001 From: Hunter Loftis Date: Wed, 5 Oct 2016 17:32:15 -0400 Subject: [PATCH 04/24] more readable formatting --- commands/push.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/commands/push.js b/commands/push.js index 9695478..8431240 100644 --- a/commands/push.js +++ b/commands/push.js @@ -39,7 +39,7 @@ function* push(context, heroku) { try { for (let job of jobs) { - cli.log(`Building ${ job.name } (${ job.dockerfile })`); + cli.log(`\n=== Building ${ job.name } (${ job.dockerfile })`); yield buildImage(job.dockerfile, job.resource, context.flags.verbose); } } @@ -50,9 +50,8 @@ function* push(context, heroku) { } try { - cli.log(`Pushing ${ jobs.length } images...`); for (let job of jobs) { - cli.log(`Pushing ${ job.name } (${ job.dockerfile })`); + cli.log(`\n=== Pushing ${ job.name } (${ job.dockerfile })`); yield pushImage(job.resource, context.flags.verbose); } } @@ -136,9 +135,9 @@ function chooseJobs(jobs) { process.exit(1); } } - cli.warn(`Using nearest match for '${ group[0].name }' process type:`); - cli.warn(`${ ambiguous[0] } (used)`); - cli.warn(`${ ambiguous.slice(1).join('\n') }`); + cli.warn(`WARNING: Using nearest match for '${ group[0].name }' process type:`); + cli.warn(`WARNING: ${ ambiguous[0] } (used)`); + ambiguous.slice(1).forEach(file => cli.warn(`WARNING: ${ file } (ignored)`)); } return group[0]; }); From 502e3f1aeb5065dd4fcdbbcc0fafd606ffb1d1f5 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Wed, 3 May 2017 09:53:58 -0500 Subject: [PATCH 05/24] multiple dockerfiles use inquirer to pick --- commands/push.js | 149 +--- lib/sanbashi.js | 103 +++ package.json | 4 +- test/fixtures/Dockerfile.web | 0 test/fixtures/Nested/Dockerfile | 0 test/sanbashi.test.js | 82 +++ yarn.lock | 1119 +++++++++++++++++++++++++++++++ 7 files changed, 1341 insertions(+), 116 deletions(-) create mode 100644 lib/sanbashi.js create mode 100644 test/fixtures/Dockerfile.web create mode 100644 test/fixtures/Nested/Dockerfile create mode 100644 test/sanbashi.test.js create mode 100644 yarn.lock diff --git a/commands/push.js b/commands/push.js index 8431240..8b41097 100644 --- a/commands/push.js +++ b/commands/push.js @@ -1,16 +1,8 @@ -'use strict'; +const cli = require('heroku-cli-util') +const co = require('co') +let Sanbashi = require('../lib/sanbashi') -const cli = require('heroku-cli-util'); -const co = require('co'); -const child = require('child_process'); -const log = require('../lib/log'); -const fs = require('fs'); -const path = require('path'); -const glob = require('glob'); - -const DOCKERFILE_REGEX = /\/Dockerfile(.\w*)?$/; - -module.exports = function(topic) { +module.exports = function (topic) { return { topic: topic, command: 'push', @@ -19,126 +11,53 @@ module.exports = function(topic) { needsAuth: true, variableArgs: true, flags: [ - { name: 'verbose', char: 'v', hasValue: false } + { + name: 'verbose', + char: 'v', + hasValue: false + }, + { + name: 'recursive', + char: 'R', + hasValue: false + } ], run: cli.command(co.wrap(push)) - }; -}; - -function* push(context, heroku) { - let herokuHost = process.env.HEROKU_HOST || 'heroku.com'; - let registry = `registry.${ herokuHost }`; - let dockerfiles = getDockerfiles(context.cwd, true); - let possibleJobs = getJobs(`${ registry }/${ context.app }`, context.args, dockerfiles); - let jobs = chooseJobs(possibleJobs); + } +} +function* push (context, heroku) { + let herokuHost = process.env.HEROKU_HOST || 'heroku.com' + let registry = `registry.${ herokuHost }` + let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), true) + let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, context.args, dockerfiles) + let jobs = yield Sanbashi.chooseJobs(possibleJobs) if (!jobs.length) { - cli.warn('No images to push'); - process.exit(); + cli.warn('No images to push') + process.exit() } try { for (let job of jobs) { - cli.log(`\n=== Building ${ job.name } (${ job.dockerfile })`); - yield buildImage(job.dockerfile, job.resource, context.flags.verbose); + cli.log(`\n=== Building ${ job.name } (${ job.dockerfile })`) + yield Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) } } catch (err) { - cli.error(`Error: docker build exited with ${ err }`); - cli.hush(err.stack || err); - process.exit(1); + cli.error(`Error: docker build exited with ${ err }`) + cli.hush(err.stack || err) + process.exit(1) } try { for (let job of jobs) { - cli.log(`\n=== Pushing ${ job.name } (${ job.dockerfile })`); - yield pushImage(job.resource, context.flags.verbose); + cli.log(`\n=== Pushing ${ job.name } (${ job.dockerfile })`) + yield Sanbashi.pushImage(job.resource, context.flags.verbose) } } catch (err) { - cli.error(`Error: docker push exited with ${ err }`); - cli.hush(err.stack || err); - process.exit(1); + cli.error(`Error: docker push exited with ${ err }`) + cli.hush(err.stack || err) + process.exit(1) } } - -function buildImage(dockerfile, resource, verbose) { - return new Promise((resolve, reject) => { - let cwd = path.dirname(dockerfile); - let args = [ 'build', '-f', dockerfile, '-t', resource, cwd ]; - log(verbose, args); - child.spawn('docker', args, { stdio: 'inherit' }) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code); - else resolve(); - }); - }); -} - -function pushImage(resource, verbose) { - return new Promise((resolve, reject) => { - let args = [ 'push', resource ]; - log(verbose, args); - child.spawn('docker', args, { stdio: 'inherit' }) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code); - else resolve(); - }); - }); -} - -function getDockerfiles(dir, recursive) { - let match = recursive ? '**/Dockerfile?(.)*' : 'Dockerfile?(.)*'; - let dockerfiles = glob.sync(match, { cwd: dir, nonull: false, nodir: true }); - return dockerfiles.map(file => path.join(dir, file)); -} - -function getJobs(resourceRoot, procs, dockerfiles) { - return dockerfiles - // convert all Dockerfiles into job Objects - .map((dockerfile) => { - let match = dockerfile.match(DOCKERFILE_REGEX); - if (!match) return; - let proc = (match[1] || '.web').slice(1); - return { - name: proc, - resource: `${ resourceRoot }/${ proc }`, - dockerfile: dockerfile, - postfix: path.basename(dockerfile) === 'Dockerfile' ? 0 : 1, - depth: path.normalize(dockerfile).split(path.sep).length - }; - }) - // if process types have been specified, filter non matches out - .filter(job => { - return job && (!procs.length || procs.indexOf(job.name) !== -1); - }) - // prefer closer Dockerfiles, then prefer Dockerfile over Dockerfile.web - .sort((a, b) => { - return a.depth - b.depth || a.postfix - b.postfix; - }) - // group all Dockerfiles for the same process type together - .reduce((jobs, job) => { - jobs[job.name] = jobs[job.name] || []; - jobs[job.name].push(job); - return jobs; - }, {}); -} - -function chooseJobs(jobs) { - return Object.keys(jobs).map(name => { - let group = jobs[name]; - if (group.length > 1) { - let ambiguous = group.map(job => job.dockerfile); - if (group[1].depth === group[0].depth) { - if (group[1].postfix === group[0].postfix) { - cli.error(`Cannot build. More than one Dockerfile defines the process type:\n${ ambiguous.join('\n') }`); - process.exit(1); - } - } - cli.warn(`WARNING: Using nearest match for '${ group[0].name }' process type:`); - cli.warn(`WARNING: ${ ambiguous[0] } (used)`); - ambiguous.slice(1).forEach(file => cli.warn(`WARNING: ${ file } (ignored)`)); - } - return group[0]; - }); -} diff --git a/lib/sanbashi.js b/lib/sanbashi.js new file mode 100644 index 0000000..c4e5adb --- /dev/null +++ b/lib/sanbashi.js @@ -0,0 +1,103 @@ +let Glob = require('glob') +let Path = require('path') +let Inquirer = require('inquirer') +const Child = require('child_process') +const log = require('./log') + +const DOCKERFILE_REGEX = /\/Dockerfile(.\w*)?$/ +class Sanbashi { + constructor () {} + + static getDockerfiles (rootdir, recursive) { + let match = recursive ? './**/Dockerfile?(.)*' : 'Dockerfile*' + let dockerfiles = Glob.sync(match, { + cwd: rootdir, + nonull: false, + nodir: true + }) + return dockerfiles.map(file => Path.join(rootdir, file)) + } + + static getJobs (resourceRoot, procs, dockerfiles) { + return dockerfiles + // convert all Dockerfiles into job Objects + .map((dockerfile) => { + let match = dockerfile.match(DOCKERFILE_REGEX) + if (!match) return + let proc = (match[1] || '.web').slice(1) + return { + name: proc, + resource: `${ resourceRoot }/${ proc }`, + dockerfile: dockerfile, + postfix: Path.basename(dockerfile) === 'Dockerfile' ? 0 : 1, + depth: Path.normalize(dockerfile).split(Path.sep).length + } + }) + // if process types have been specified, filter non matches out + .filter(job => { + return job && (!procs.length || procs.indexOf(job.name) !== -1) + }) + // prefer closer Dockerfiles, then prefer Dockerfile over Dockerfile.web + .sort((a, b) => { + return a.depth - b.depth || a.postfix - b.postfix + }) + // group all Dockerfiles for the same process type together + .reduce((jobs, job) => { + jobs[job.name] = jobs[job.name] || [] + jobs[job.name].push(job) + return jobs + }, {}) + } + + static chooseJobs (jobs) { + return Object.keys(jobs).map(processType => { + let group = jobs[processType] + if (group.length > 1) { + let prompt = { + type: 'list', + name: processType, + choices: group.map(j => j.dockerfile), + message: `Found multiple Dockerfiles with process type ${processType}. Please choose one to build and push ` + } + return Inquirer.prompt(prompt) + .then((answer) => { + return group.find(o => o.dockerfile === answer.web) + } + ) + } else { + return group[0] + } + }) + } + + static buildImage (dockerfile, resource, verbose) { + return new Promise((resolve, reject) => { + let cwd = Path.dirname(dockerfile) + let args = ['build', '-f', dockerfile, '-t', resource, cwd] + log(verbose, args) + Child.spawn('docker', args, { + stdio: 'inherit' + }) + .on('exit', (code, signal) => { + if (signal || code) reject(signal || code) + else resolve() + }) + }) + } + + static pushImage (resource, verbose) { + return new Promise((resolve, reject) => { + let args = ['push', resource] + log(verbose, args) + Child.spawn('docker', args, { + stdio: 'inherit' + }) + .on('exit', (code, signal) => { + if (signal || code) reject(signal || code) + else resolve() + }) + }) + } +} + +module.exports = Sanbashi diff --git a/package.json b/package.json index 9c6acfb..01a5766 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,9 @@ "co": "4.6.0", "dotenv": "^1.1.0", "glob": "7.1.0", - "heroku-cli-util": "^1.8.1", + "heroku-cli-util": "^6.1.17", "heroku-client": "^1.9.1", + "inquirer": "^3.0.6", "is-there": "4.0.0", "lodash": "3.3.1", "mkdirp": "^0.5.0", @@ -35,6 +36,7 @@ }, "devDependencies": { "chai": "^3.2.0", + "sinon": "^2.1.0", "depcheck": "^0.4.7", "dir-compare": "^0.0.2", "fs-extra": "^0.23.1", diff --git a/test/fixtures/Dockerfile.web b/test/fixtures/Dockerfile.web new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/Nested/Dockerfile b/test/fixtures/Nested/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js new file mode 100644 index 0000000..f9d5dfb --- /dev/null +++ b/test/sanbashi.test.js @@ -0,0 +1,82 @@ +let Sinon = require('sinon') +let Sanbashi = require('../lib/sanbashi') +let expect = require('chai').expect +let Path = require('path') +let Inquirer = require('inquirer') + +describe('Sanbashi', () => { + describe('.getDockerfiles', () => { + it('can find in just the given directory', () => { + const searchpath = Path.join(process.cwd(), './test/fixtures') + let results = Sanbashi.getDockerfiles(searchpath, false) + expect(results).to.have.members([`${searchpath}/Dockerfile.web`]) + }) + it('can recurse the directory', () => { + const searchpath = Path.join(process.cwd(), './test/fixtures') + let results = Sanbashi.getDockerfiles(searchpath, true) + expect(results).to.have.members([`${searchpath}/Dockerfile.web`, `${searchpath}/Nested/Dockerfile`]) + }) + }) + describe('.getJobs', () => { + it('returns objects representing jobs per Dockerfile', () => { + const dockerfiles = ['./Dockerfile.web', './Nested/Dockerfile.web'] + const resourceRoot = 'rootfulroot' + const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) + expect(results.web).to.have.property('length', 2) + expect(results.web[0]).to.have.property('depth', 1, 'dockerfile', './Dockerfile.web', 'postfix', 1) + expect(results.web[1]).to.have.property('depth', 2, 'dockerfile', './Nested/Dockerfile.web', 'postfix', 1) + }) + it('filters out by process type', () => { + const dockerfiles = ['./Dockerfile.web', './Nested/Dockerfile.worker'] + const resourceRoot = 'rootfulroot' + const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) + expect(results.web).to.have.property('length', 1) + expect(results.web[0]).to.have.property('name', 'web') + expect(results).to.not.have.property('worker') + }) + it('sorts dockerfiles by directory depth, then proc type', () => { + const dockerfiles = ['./Nested/Dockerfile.worker', './Dockerfile.web', './Nested/Dockerfile'] + const resourceRoot = 'rootfulroot' + const results = Sanbashi.getJobs(resourceRoot, [], dockerfiles) + expect(results.web).to.have.property('length', 2) + expect(results.web[0]).to.have.property('dockerfile', './Dockerfile.web') + expect(results.web[1]).to.have.property('dockerfile', './Nested/Dockerfile') + expect(results.worker[0]).to.have.property('dockerfile', './Nested/Dockerfile.worker') + }) + it('groups the jobs by process type', () => { + const dockerfiles = ['./Nested/Dockerfile.worker', './Dockerfile.web', './Nested/Dockerfile'] + const resourceRoot = 'rootfulroot' + const results = Sanbashi.getJobs(resourceRoot, [], dockerfiles) + expect(results).to.have.keys('worker', 'web') + expect(results['worker'].map(j => j.dockerfile)).to.have.members(['./Nested/Dockerfile.worker']) + expect(results['web'].map(j => j.dockerfile)).to.have.members(['./Dockerfile.web', './Nested/Dockerfile']) + }) + }) + describe('.chooseJobs', () => { + it('returns the entry when ony one exist', () => { + const dockerfiles = ['./Nested/Dockerfile.web'] + const jobs = Sanbashi.getJobs('rootfulroot', [], dockerfiles) + let chosenJob = Sanbashi.chooseJobs(jobs) + expect(chosenJob[0]).to.have.property('dockerfile', dockerfiles[0]) + expect(chosenJob).to.have.property('length',1) + }) + it.skip('queries the user when more than one job of a type exists', () => { + //really no way to simulate user input for Inquirer + Sinon.stub(Inquirer, 'prompt').resolves('something') + const dockerfiles = ['./Nested/Dockerfile.web', './OtherNested/Dockerfile.web','./AnotherNested/Dockerfile.web', './Dockerfile.web'] + let jobs = Sanbashi.getJobs('rootfulroot', ['web'], dockerfiles) + let res = Sanbashi.chooseJobs(jobs) + // .then((chosen) => { + // console.dir(chosen, { + // colors: true, + // depth: null + // }) + // }) + console.dir(res) + }) + afterEach(() => { + if(Inquirer.prompt.restore) + Inquirer.prompt.restore() + }) + }) +}) diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..85a66e8 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1119 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +acorn@^4.0.3: + version "4.0.11" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" + +ansi-escapes@1.4.0, ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansicolors@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" + +argparse@^0.1.15: + version "0.1.16" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c" + dependencies: + underscore "~1.7.0" + underscore.string "~2.4.0" + +asn1@0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7" + +assert-plus@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160" + +assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + +async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + +aws-sign2@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +bl@~0.9.0: + version "0.9.5" + resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" + dependencies: + readable-stream "~1.0.26" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +brace-expansion@^1.0.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + +buffer-shims@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +camelcase@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.0.2.tgz#7912eac1d496836782c976c2d73e874dc54f2eaf" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +cardinal@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-1.0.0.tgz#50e21c1b0aa37729f9377def196b5a9cec932ee9" + dependencies: + ansicolors "~0.2.1" + redeyed "~1.0.0" + +caseless@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.9.0.tgz#b7b65ce6bf1413886539cfd533f0b30effa9cf88" + +chai@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" + dependencies: + assertion-error "^1.0.1" + deep-eql "^0.1.3" + type-detect "^1.0.0" + +chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + +co@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + +combined-stream@~0.0.4, combined-stream@~0.0.5: + version "0.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-0.0.7.tgz#0137e657baa5a7541c57ac37ac5fc07d73b4dc1f" + dependencies: + delayed-stream "0.0.5" + +commander@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" + +commander@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" + +commander@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.5.0.tgz#d777b6a4d847d423e5d475da864294ac1ff5aa9d" + +component-emitter@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.4.8: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +cookiejar@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.0.1.tgz#3d12752f6adf68a892f332433492bd5812bb668f" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +ctype@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" + +debug@2, debug@^2.2.0: + version "2.6.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a" + dependencies: + ms "0.7.3" + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +deep-eql@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" + dependencies: + type-detect "0.1.1" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +delayed-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" + +depcheck@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/depcheck/-/depcheck-0.4.7.tgz#2584e2dd05c50026f64a37f64c36e625c53a9d41" + dependencies: + detective "^4.0.0" + lodash "^3.3.0" + minimatch "^2.0.1" + optimist "~0.6.0" + q "^1.0.1" + walkdir "0.0.7" + +detective@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.5.0.tgz#6e5a8c6b26e6c7a254b1c6b6d7490d98ec91edd1" + dependencies: + acorn "^4.0.3" + defined "^1.0.0" + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +diff@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +dir-compare@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-0.0.2.tgz#156da5dfa7e841479d5e9d0ca857857f7faef36c" + dependencies: + buffer-equal "0.0.1" + colors "1.0.3" + commander "2.5.0" + minimatch "2.0.1" + +dotenv@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-1.2.0.tgz#7cd73e16e07f057c8072147a5bc3a8677f0ab5c6" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +escape-string-regexp@1.0.2, escape-string-regexp@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esprima@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9" + +extend@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-1.2.1.tgz#a0f5fd6cfc83a5fe49ef698d60ec8a624dd4576c" + +external-editor@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" + dependencies: + tmp "^0.0.31" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +forever-agent@~0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.5.2.tgz#6d0e09c4921f94a27f63d3b49c5feff1ea4c5130" + +form-data@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.1.3.tgz#4ee4346e6eb5362e8344a02075bd8dbd8c7373ea" + dependencies: + async "~0.9.0" + combined-stream "~0.0.4" + mime "~1.2.11" + +form-data@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.2.0.tgz#26f8bc26da6440e299cbdcfb69035c4f77a6e466" + dependencies: + async "~0.9.0" + combined-stream "~0.0.4" + mime-types "~2.0.3" + +formatio@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" + dependencies: + samsam "1.x" + +formidable@1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.14.tgz#2b3f4c411cbb5fdd695c44843e2a23514a43231a" + +fs-extra@^0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.23.1.tgz#6611dba6adf2ab8dc9c69fab37cddf8818157e3d" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +glob@3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + dependencies: + inherits "2" + minimatch "0.3" + +glob@7.1.0, glob@^7.0.5: + version "7.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.0.tgz#36add856d746d0d99e4cc2797bba1ae2c67272fd" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^4.0.0: + version "4.5.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "^2.0.1" + once "^1.3.0" + +got@^6.3.0: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +hawk@~2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-2.3.1.tgz#1e731ce39447fa1d0f6d707f7bceebec0fd1ec1f" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +heroku-cli-util@^6.1.17: + version "6.1.17" + resolved "https://registry.yarnpkg.com/heroku-cli-util/-/heroku-cli-util-6.1.17.tgz#3d1e5eb62f2a7e73053b4768054cc6df14b4d578" + dependencies: + ansi-escapes "1.4.0" + cardinal "1.0.0" + chalk "^1.1.3" + co "4.6.0" + got "^6.3.0" + heroku-client "3.0.2" + lodash.ary "4.1.1" + lodash.defaults "4.2.0" + lodash.get "4.4.2" + lodash.identity "3.0.0" + lodash.keys "4.2.0" + lodash.mapvalues "4.6.0" + lodash.noop "3.0.1" + lodash.partial "4.2.1" + lodash.pickby "4.6.0" + lodash.property "4.4.2" + lodash.repeat "4.1.0" + lodash.result "4.5.2" + netrc-parser "2.0.1" + opn "^3.0.3" + supports-color "^3.1.2" + tunnel-agent "^0.4.3" + +heroku-client@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-3.0.2.tgz#7e06f303ff18f7a0731725dcccbe210b76198657" + dependencies: + debug "^2.2.0" + is-retry-allowed "^1.0.0" + tunnel-agent "^0.4.0" + +heroku-client@^1.9.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-1.11.0.tgz#9ff0e041a3d1b363a72fa01ff876b316f6985773" + dependencies: + concat-stream "^1.4.8" + inflection "^1.7.0" + lazy.js "^0.4.0" + logfmt "^1.1.2" + memjs "^0.8.5" + path-proxy "^1.0" + q "^1.2.0" + simple-encryptor "^1.0.2" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +http-signature@~0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.10.1.tgz#4fbdac132559aa8323121e540779c0a012b27e66" + dependencies: + asn1 "0.1.11" + assert-plus "^0.1.5" + ctype "0.5.3" + +inflection@^1.7.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" + +inflection@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.3.8.tgz#cbd160da9f75b14c3cc63578d4f396784bf3014e" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inquirer@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" + dependencies: + ansi-escapes "^1.1.0" + chalk "^1.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.1" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx "^4.1.0" + string-width "^2.0.0" + strip-ansi "^3.0.0" + through "^2.3.6" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-there@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-there/-/is-there-4.0.0.tgz#d4183ff9b1bc657f285260db4d90b293ee7f5bd3" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isstream@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +jade@0.26.3: + version "0.26.3" + resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" + dependencies: + commander "0.6.1" + mkdirp "0.3.0" + +json-stringify-safe@~5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + +lazy.js@^0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/lazy.js/-/lazy.js-0.4.3.tgz#87f67a07ad36555121e4fff1520df31be66786d8" + +lex@^1.7.9: + version "1.7.9" + resolved "https://registry.yarnpkg.com/lex/-/lex-1.7.9.tgz#5d5636ccef574348362938b79a47f0eed8ed0d43" + +lodash.ary@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.ary/-/lodash.ary-4.1.1.tgz#66065fa91bacc7a034d9c8fce52f83d3c7e40212" + +lodash.defaults@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + +lodash.get@4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + +lodash.identity@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash.identity/-/lodash.identity-3.0.0.tgz#ad7bc6a4e647d79c972e1b80feef7af156267876" + +lodash.keys@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" + +lodash.mapvalues@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + +lodash.noop@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c" + +lodash.partial@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.partial/-/lodash.partial-4.2.1.tgz#49f3d8cfdaa3bff8b3a91d127e923245418961d4" + +lodash.pickby@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" + +lodash.property@4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.property/-/lodash.property-4.4.2.tgz#da07124821c6409d025f30db8df851314515bffe" + +lodash.repeat@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" + +lodash.result@4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.result/-/lodash.result-4.5.2.tgz#cb45b27fb914eaa8d8ee6f0ce7b2870b87cb70aa" + +lodash@3.3.1, lodash@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.3.1.tgz#3b914d4a1bb27efcee076e0dfa58152018e2042e" + +lodash@^4.3.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@~2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" + +logfmt@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/logfmt/-/logfmt-1.2.0.tgz#1ccc067c1cfe65f3ecf5856c09d2654f69203572" + dependencies: + lodash "~2.4.1" + split "0.2.x" + through "2.3.x" + +lolex@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" + +lowercase-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +memjs@^0.8.5: + version "0.8.9" + resolved "https://registry.yarnpkg.com/memjs/-/memjs-0.8.9.tgz#578d5c5a3c31711a9d137fcccc5af41147edc5ed" + +methods@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.0.1.tgz#75bc91943dffd7da037cf3eeb0ed73a0037cd14b" + +mime-db@~1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.12.0.tgz#3d0c63180f458eb10d325aaa37d7c58ae312e9d7" + +mime-types@~2.0.1, mime-types@~2.0.3: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.0.14.tgz#310e159db23e077f8bb22b748dabfa4957140aa6" + dependencies: + mime-db "~1.12.0" + +mime@1.2.11, mime@~1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" + +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.1.tgz#6c3760b45f66ed1cd5803143ee8d372488f02c37" + dependencies: + brace-expansion "^1.0.0" + +minimatch@^2.0.1: + version "2.0.10" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" + dependencies: + brace-expansion "^1.0.0" + +minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8, minimist@~0.0.1: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + +mkdirp@0.5.1, mkdirp@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^2.2.4: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" + dependencies: + commander "2.3.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.2" + glob "3.2.11" + growl "1.9.2" + jade "0.26.3" + mkdirp "0.5.1" + supports-color "1.2.0" + to-iso-string "0.0.2" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +native-promise-only@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" + +netrc-parser@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/netrc-parser/-/netrc-parser-2.0.1.tgz#bd1d8b1eaf9555d4cceb051b74da1ab0a018e440" + dependencies: + lex "^1.7.9" + +node-uuid@^1.4.3, node-uuid@~1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" + +oauth-sign@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.6.0.tgz#7dbeae44f6ca454e1f168451d630746735813ce3" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opn@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" + dependencies: + object-assign "^4.0.1" + +optimist@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +os-tmpdir@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-proxy@^1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/path-proxy/-/path-proxy-1.0.0.tgz#18e8a36859fc9d2f1a53b48dee138543c020de5e" + dependencies: + inflection "~1.3.0" + +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +progress@1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.0.1, q@^1.2.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" + +qs@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.0.tgz#ed079be28682147e6fd9a34cc2b0c1e0ec6453ee" + +qs@~2.3.1: + version "2.3.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" + +readable-stream@1.0.27-1: + version "1.0.27-1" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.27-1.tgz#6b67983c20357cefd07f0165001a16d710d91078" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.2.2: + version "2.2.9" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" + dependencies: + buffer-shims "~1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~1.0.0" + util-deprecate "~1.0.1" + +readable-stream@~1.0.26: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +redeyed@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-1.0.1.tgz#e96c193b40c0816b00aec842698e61185e55498a" + dependencies: + esprima "~3.0.0" + +reduce-component@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/reduce-component/-/reduce-component-1.0.1.tgz#e0c93542c574521bea13df0f9488ed82ab77c5da" + +request@2.53.0: + version "2.53.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.53.0.tgz#180a3ae92b7b639802e4f9545dd8fcdeb71d760c" + dependencies: + aws-sign2 "~0.5.0" + bl "~0.9.0" + caseless "~0.9.0" + combined-stream "~0.0.5" + forever-agent "~0.5.0" + form-data "~0.2.0" + hawk "~2.3.0" + http-signature "~0.10.0" + isstream "~0.1.1" + json-stringify-safe "~5.0.0" + mime-types "~2.0.1" + node-uuid "~1.4.0" + oauth-sign "~0.6.0" + qs "~2.3.1" + stringstream "~0.0.4" + tough-cookie ">=0.12.0" + tunnel-agent "~0.4.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@^2.2.8: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" + dependencies: + glob "^7.0.5" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +rx@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" + +safe-buffer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + +samsam@1.x, samsam@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67" + +scmp@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/scmp/-/scmp-0.0.3.tgz#3648df2d7294641e7f78673ffc29681d9bad9073" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-encryptor@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-encryptor/-/simple-encryptor-1.1.0.tgz#653bb1926c8f0fc2b8d7038577cc846053263ae8" + dependencies: + scmp "0.0.3" + +sinon@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.1.0.tgz#e057a9d2bf1b32f5d6dd62628ca9ee3961b0cafb" + dependencies: + diff "^3.1.0" + formatio "1.2.0" + lolex "^1.6.0" + native-promise-only "^0.8.1" + path-to-regexp "^1.7.0" + samsam "^1.1.3" + text-encoding "0.6.4" + type-detect "^4.0.0" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +split@0.2.x: + version "0.2.10" + resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" + dependencies: + through "2" + +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" + dependencies: + buffer-shims "~1.0.0" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +superagent@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-0.21.0.tgz#fb15027984751ee7152200e6cd21cd6e19a5de87" + dependencies: + component-emitter "1.1.2" + cookiejar "2.0.1" + debug "2" + extend "~1.2.1" + form-data "0.1.3" + formidable "1.0.14" + methods "1.0.1" + mime "1.2.11" + qs "1.2.0" + readable-stream "1.0.27-1" + reduce-component "1.0.1" + +supports-color@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.1.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +text-encoding@0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + +through@2, through@2.3.x, through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + +to-iso-string@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" + +tough-cookie@>=0.12.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +tunnel-agent@^0.4.0, tunnel-agent@^0.4.3, tunnel-agent@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +type-detect@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" + +type-detect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" + +type-detect@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +underscore.string@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" + +underscore@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +walkdir@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.7.tgz#04da0270a87a778540173cdbf0a2db499a8d9e29" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +wrench@^1.5.8: + version "1.5.9" + resolved "https://registry.yarnpkg.com/wrench/-/wrench-1.5.9.tgz#411691c63a9b2531b1700267279bdeca23b2142a" + +yamljs@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.2.4.tgz#98c34876227a06fd786c80f77d48036d59c67dca" + dependencies: + argparse "^0.1.15" + glob "^4.0.0" From b4c8b8561158ae2dac35084726485738474ba2cd Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Wed, 3 May 2017 11:36:42 -0500 Subject: [PATCH 06/24] some changes for excluding certain files --- commands/push.js | 7 ++++++- lib/sanbashi.js | 5 +++++ test/fixtures/Nested/Dockerfile.web | 0 test/sanbashi.test.js | 7 ++++++- 4 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/Nested/Dockerfile.web diff --git a/commands/push.js b/commands/push.js index 8b41097..4156b7c 100644 --- a/commands/push.js +++ b/commands/push.js @@ -27,9 +27,14 @@ module.exports = function (topic) { } function* push (context, heroku) { + const recurse = !!context.flags.recursive + if(context.args.length === 0 && !recurse){ + cli.error('Error: Requires either --recursive or one or more process types') + process.exit(1) + } let herokuHost = process.env.HEROKU_HOST || 'heroku.com' let registry = `registry.${ herokuHost }` - let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), true) + let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, context.args, dockerfiles) let jobs = yield Sanbashi.chooseJobs(possibleJobs) if (!jobs.length) { diff --git a/lib/sanbashi.js b/lib/sanbashi.js index c4e5adb..731d024 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -1,3 +1,5 @@ +// 'sanbashi' is a word in Japanese that refers to a pier or dock, usually very large in size, such as found in Tokyo's O-daiba region + let Glob = require('glob') let Path = require('path') let Inquirer = require('inquirer') @@ -15,6 +17,9 @@ class Sanbashi { nonull: false, nodir: true }) + if(recursive){ + dockerfiles = dockerfiles.filter(df => df.match(/Dockerfile\.[\w]+/)) + } return dockerfiles.map(file => Path.join(rootdir, file)) } diff --git a/test/fixtures/Nested/Dockerfile.web b/test/fixtures/Nested/Dockerfile.web new file mode 100644 index 0000000..e69de29 diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index f9d5dfb..2a93c88 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -14,7 +14,12 @@ describe('Sanbashi', () => { it('can recurse the directory', () => { const searchpath = Path.join(process.cwd(), './test/fixtures') let results = Sanbashi.getDockerfiles(searchpath, true) - expect(results).to.have.members([`${searchpath}/Dockerfile.web`, `${searchpath}/Nested/Dockerfile`]) + expect(results).to.have.members([`${searchpath}/Dockerfile.web`, `${searchpath}/Nested/Dockerfile.web`]) + }) + it('when recursing, rejects dockerfiles that have no postfix in the name', () => { + const searchpath = Path.join(process.cwd(), './test/fixtures') + let results = Sanbashi.getDockerfiles(searchpath, true) + expect(results).to.not.have.members([`${searchpath}/Dockerfile`]) }) }) describe('.getJobs', () => { From 952208753bb82f5e1850f882f9a1c65b479e9fa2 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Thu, 4 May 2017 11:28:09 -0500 Subject: [PATCH 07/24] review feedback use Path.join some formatting changes --- commands/index.js | 1 - commands/login.js | 53 ++++++++-------- commands/logout.js | 13 ++-- commands/push.js | 34 ++++++---- lib/log.js | 2 - lib/sanbashi.js | 33 +++++----- package.json | 14 ++--- test/sanbashi.test.js | 48 +++++++++----- yarn.lock | 143 +++++++++++++++++------------------------- 9 files changed, 166 insertions(+), 175 deletions(-) diff --git a/commands/index.js b/commands/index.js index 5c6ad97..32c515e 100644 --- a/commands/index.js +++ b/commands/index.js @@ -2,7 +2,6 @@ module.exports = function index(pkg) { return { topic: pkg.topic, description: pkg.description, - help: pkg.description, run: showVersion }; diff --git a/commands/login.js b/commands/login.js index 51fb7cc..1f16c98 100644 --- a/commands/login.js +++ b/commands/login.js @@ -1,49 +1,48 @@ -'use strict'; +const cli = require('heroku-cli-util') +const child = require('child_process') +const log = require('../lib/log') -const cli = require('heroku-cli-util'); -const co = require('co'); -const child = require('child_process'); -const log = require('../lib/log'); - -module.exports = function(topic) { +module.exports = function (topic) { return { topic: topic, command: 'login', - flags: [{ name: 'verbose', char: 'v', hasValue: false }], - description: 'Logs in to the Heroku Docker registry', + flags: [{name: 'verbose', char: 'v', hasValue: false}], + description: 'logs in to the Heroku Docker registry', + help: `Usage: + heroku container:login`, needsApp: false, needsAuth: true, - run: cli.command(co.wrap(login)) - }; -}; + run: cli.command(login) + } +} -function* login(context, heroku) { - let herokuHost = process.env.HEROKU_HOST || 'heroku.com'; - let registry = `registry.${ herokuHost }`; - let password = context.auth.password; +async function login (context, heroku) { + let herokuHost = process.env.HEROKU_HOST || 'heroku.com' + let registry = `registry.${ herokuHost }` + let password = context.auth.password try { - let user = yield dockerLogin(registry, password, context.flags.verbose); + let user = await dockerLogin(registry, password, context.flags.verbose) } catch (err) { - cli.error(`Error: docker login exited with ${ err }`); - cli.hush(err.stack || err); + cli.error(`Error: docker login exited with ${ err }`) + cli.hush(err.stack || err) } } -function dockerLogin(registry, password, verbose) { +function dockerLogin (registry, password, verbose) { return new Promise((resolve, reject) => { let args = [ 'login', '--username=_', `--password=${ password }`, registry - ]; - log(verbose, args); - child.spawn('docker', args, { stdio: 'inherit' }) + ] + log(verbose, args) + child.spawn('docker', args, {stdio: 'inherit'}) .on('exit', (code, signal) => { - if (signal || code) reject(signal || code); - else resolve(); - }); - }); + if (signal || code) reject(signal || code) + else resolve() + }) + }) } diff --git a/commands/logout.js b/commands/logout.js index da4e7ba..874d2f3 100644 --- a/commands/logout.js +++ b/commands/logout.js @@ -1,7 +1,4 @@ -'use strict'; - const cli = require('heroku-cli-util'); -const co = require('co'); const child = require('child_process'); const log = require('../lib/log'); @@ -10,19 +7,21 @@ module.exports = function(topic) { topic: topic, command: 'logout', flags: [{ name: 'verbose', char: 'v', hasValue: false }], - description: 'Logs out from the Heroku Docker registry', + description: 'logs out from the Heroku Docker registry', + help: `Usage: + heroku container:logout`, needsApp: false, needsAuth: false, - run: cli.command(co.wrap(logout)) + run: cli.command(logout) }; }; -function* logout(context, heroku) { +async function logout(context, heroku) { let herokuHost = process.env.HEROKU_HOST || 'heroku.com'; let registry = `registry.${ herokuHost }`; try { - let user = yield dockerLogout(registry, context.flags.verbose); + let user = await dockerLogout(registry, context.flags.verbose); } catch (err) { cli.error(`Error: docker logout exited with ${ err }`); diff --git a/commands/push.js b/commands/push.js index 4156b7c..94f7925 100644 --- a/commands/push.js +++ b/commands/push.js @@ -1,15 +1,23 @@ const cli = require('heroku-cli-util') -const co = require('co') -let Sanbashi = require('../lib/sanbashi') +const Sanbashi = require('../lib/sanbashi') +const Chalk = require('chalk') +let usage = ` + ${Chalk.bold.underline.magenta('Usage:')} + ${ Chalk.white(' heroku container:push web')} # Pushes Dockerfile in current directory + ${ Chalk.white(' heroku container:push web worker')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory + ${ Chalk.white(' heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory or subdirectories + ${ Chalk.white(' heroku container:push --recursive')} # Pushes Dockerfile.* found in current directory or subdirectories` + module.exports = function (topic) { return { topic: topic, command: 'push', - description: 'Builds, then pushes a Docker image to deploy your Heroku app', + description: 'builds, then pushes Docker images to deploy your Heroku app', needsApp: true, needsAuth: true, variableArgs: true, + help: usage, flags: [ { name: 'verbose', @@ -22,30 +30,30 @@ module.exports = function (topic) { hasValue: false } ], - run: cli.command(co.wrap(push)) + run: cli.command(push) } } -function* push (context, heroku) { +let push = async function (context, heroku) { const recurse = !!context.flags.recursive - if(context.args.length === 0 && !recurse){ - cli.error('Error: Requires either --recursive or one or more process types') + if (context.args.length === 0 && !recurse) { + cli.error( `Error: Requires either --recursive or one or more process types\n ${usage} `) process.exit(1) } let herokuHost = process.env.HEROKU_HOST || 'heroku.com' let registry = `registry.${ herokuHost }` let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, context.args, dockerfiles) - let jobs = yield Sanbashi.chooseJobs(possibleJobs) + let jobs = await Sanbashi.chooseJobs(possibleJobs) if (!jobs.length) { cli.warn('No images to push') - process.exit() + process.exit(1) } try { for (let job of jobs) { - cli.log(`\n=== Building ${ job.name } (${ job.dockerfile })`) - yield Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) + cli.log(Chalk.bold.white.bgMagenta(`\n=== Building ${job.name} (${job.dockerfile})`)) + await Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) } } catch (err) { @@ -56,8 +64,8 @@ function* push (context, heroku) { try { for (let job of jobs) { - cli.log(`\n=== Pushing ${ job.name } (${ job.dockerfile })`) - yield Sanbashi.pushImage(job.resource, context.flags.verbose) + cli.log(Chalk.bold.white.bgMagenta(`\n=== Pushing ${job.name} (${job.dockerfile })`)) + await Sanbashi.pushImage(job.resource, context.flags.verbose) } } catch (err) { diff --git a/lib/log.js b/lib/log.js index fa0e6eb..bb15041 100644 --- a/lib/log.js +++ b/lib/log.js @@ -1,5 +1,3 @@ -'use strict'; - module.exports = (visible, args) => { if (!visible) return; console.log(`> docker ${ args.join(' ') }`); diff --git a/lib/sanbashi.js b/lib/sanbashi.js index 731d024..dfc5cc7 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -6,24 +6,23 @@ let Inquirer = require('inquirer') const Child = require('child_process') const log = require('./log') -const DOCKERFILE_REGEX = /\/Dockerfile(.\w*)?$/ -class Sanbashi { - constructor () {} +const DOCKERFILE_REGEX = /\bDockerfile(.\w*)?$/ +let Sanbashi = function(){} - static getDockerfiles (rootdir, recursive) { + Sanbashi.getDockerfiles = function(rootdir, recursive) { let match = recursive ? './**/Dockerfile?(.)*' : 'Dockerfile*' let dockerfiles = Glob.sync(match, { cwd: rootdir, nonull: false, nodir: true }) - if(recursive){ + if (recursive) { dockerfiles = dockerfiles.filter(df => df.match(/Dockerfile\.[\w]+/)) } return dockerfiles.map(file => Path.join(rootdir, file)) } - static getJobs (resourceRoot, procs, dockerfiles) { + Sanbashi.getJobs = function(resourceRoot, procs, dockerfiles) { return dockerfiles // convert all Dockerfiles into job Objects .map((dockerfile) => { @@ -54,8 +53,9 @@ class Sanbashi { }, {}) } - static chooseJobs (jobs) { - return Object.keys(jobs).map(processType => { + Sanbashi.chooseJobs = async function(jobs) { + let chosenJobs = [] + for(let processType in jobs){ let group = jobs[processType] if (group.length > 1) { let prompt = { @@ -64,18 +64,16 @@ class Sanbashi { choices: group.map(j => j.dockerfile), message: `Found multiple Dockerfiles with process type ${processType}. Please choose one to build and push ` } - return Inquirer.prompt(prompt) - .then((answer) => { - return group.find(o => o.dockerfile === answer.web) - } - ) + let answer = await Inquirer.prompt(prompt) + chosenJobs.push(group.find(o => o.dockerfile === answer[processType])) } else { - return group[0] + chosenJobs.push(group[0]) } - }) + } + return chosenJobs } - static buildImage (dockerfile, resource, verbose) { + Sanbashi.buildImage = function(dockerfile, resource, verbose) { return new Promise((resolve, reject) => { let cwd = Path.dirname(dockerfile) let args = ['build', '-f', dockerfile, '-t', resource, cwd] @@ -90,7 +88,7 @@ class Sanbashi { }) } - static pushImage (resource, verbose) { + Sanbashi.pushImage = function(resource, verbose) { return new Promise((resolve, reject) => { let args = ['push', resource] log(verbose, args) @@ -103,6 +101,5 @@ class Sanbashi { }) }) } -} module.exports = Sanbashi diff --git a/package.json b/package.json index 01a5766..decbf42 100644 --- a/package.json +++ b/package.json @@ -19,28 +19,28 @@ "license": "ISC", "dependencies": { "camelcase": "1.0.2", - "co": "4.6.0", + "chalk": "1.1.3", "dotenv": "^1.1.0", "glob": "7.1.0", - "heroku-cli-util": "^6.1.17", - "heroku-client": "^1.9.1", - "inquirer": "^3.0.6", + "heroku-cli-util": "6.1.17", + "heroku-client": "1.9.1", + "inquirer": "3.0.6", "is-there": "4.0.0", "lodash": "3.3.1", "mkdirp": "^0.5.0", - "node-uuid": "^1.4.3", + "node-uuid": "1.4.3", "progress": "1.1.8", "request": "2.53.0", - "superagent": "^0.21.0", + "superagent": "0.21.0", "yamljs": "0.2.4" }, "devDependencies": { "chai": "^3.2.0", - "sinon": "^2.1.0", "depcheck": "^0.4.7", "dir-compare": "^0.0.2", "fs-extra": "^0.23.1", "mocha": "^2.2.4", + "sinon": "^2.1.0", "wrench": "^1.5.8" } } diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index 2a93c88..47cc3a3 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -24,7 +24,10 @@ describe('Sanbashi', () => { }) describe('.getJobs', () => { it('returns objects representing jobs per Dockerfile', () => { - const dockerfiles = ['./Dockerfile.web', './Nested/Dockerfile.web'] + const dockerfiles = [ + Path.join('.', 'Dockerfile.web'), + Path.join('.', 'Nested', 'Dockerfile.web') + ] const resourceRoot = 'rootfulroot' const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) expect(results.web).to.have.property('length', 2) @@ -32,7 +35,10 @@ describe('Sanbashi', () => { expect(results.web[1]).to.have.property('depth', 2, 'dockerfile', './Nested/Dockerfile.web', 'postfix', 1) }) it('filters out by process type', () => { - const dockerfiles = ['./Dockerfile.web', './Nested/Dockerfile.worker'] + const dockerfiles = [ + Path.join('.', 'Dockerfile.web'), + Path.join('.', 'Nested', 'Dockerfile.worker') + ] const resourceRoot = 'rootfulroot' const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) expect(results.web).to.have.property('length', 1) @@ -40,35 +46,47 @@ describe('Sanbashi', () => { expect(results).to.not.have.property('worker') }) it('sorts dockerfiles by directory depth, then proc type', () => { - const dockerfiles = ['./Nested/Dockerfile.worker', './Dockerfile.web', './Nested/Dockerfile'] + const dockerfiles = [ + Path.join('.', 'Nested', 'Dockerfile.worker'), + Path.join('.', 'Dockerfile.web'), + Path.join('.', 'Nested', 'Dockerfile') + ] const resourceRoot = 'rootfulroot' const results = Sanbashi.getJobs(resourceRoot, [], dockerfiles) expect(results.web).to.have.property('length', 2) - expect(results.web[0]).to.have.property('dockerfile', './Dockerfile.web') - expect(results.web[1]).to.have.property('dockerfile', './Nested/Dockerfile') - expect(results.worker[0]).to.have.property('dockerfile', './Nested/Dockerfile.worker') + expect(results.web[0]).to.have.property('dockerfile', 'Dockerfile.web') + expect(results.web[1]).to.have.property('dockerfile', 'Nested/Dockerfile') + expect(results.worker[0]).to.have.property('dockerfile', 'Nested/Dockerfile.worker') }) it('groups the jobs by process type', () => { - const dockerfiles = ['./Nested/Dockerfile.worker', './Dockerfile.web', './Nested/Dockerfile'] + const dockerfiles = [ + Path.join('.', 'Nested', 'Dockerfile.worker'), + Path.join('.', 'Dockerfile.web'), + Path.join('.', 'Nested', 'Dockerfile') + ] const resourceRoot = 'rootfulroot' const results = Sanbashi.getJobs(resourceRoot, [], dockerfiles) expect(results).to.have.keys('worker', 'web') - expect(results['worker'].map(j => j.dockerfile)).to.have.members(['./Nested/Dockerfile.worker']) - expect(results['web'].map(j => j.dockerfile)).to.have.members(['./Dockerfile.web', './Nested/Dockerfile']) + expect(results['worker'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Nested', 'Dockerfile.worker')]) + expect(results['web'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Dockerfile.web'), Path.join('.', 'Nested', 'Dockerfile')]) }) }) describe('.chooseJobs', () => { - it('returns the entry when ony one exist', () => { - const dockerfiles = ['./Nested/Dockerfile.web'] + it('returns the entry when only one exists', async () => { + const dockerfiles = [Path.join('.', 'Nested', 'Dockerfile.web')] const jobs = Sanbashi.getJobs('rootfulroot', [], dockerfiles) - let chosenJob = Sanbashi.chooseJobs(jobs) + let chosenJob = await Sanbashi.chooseJobs(jobs) expect(chosenJob[0]).to.have.property('dockerfile', dockerfiles[0]) - expect(chosenJob).to.have.property('length',1) + expect(chosenJob).to.have.property('length', 1) }) it.skip('queries the user when more than one job of a type exists', () => { //really no way to simulate user input for Inquirer Sinon.stub(Inquirer, 'prompt').resolves('something') - const dockerfiles = ['./Nested/Dockerfile.web', './OtherNested/Dockerfile.web','./AnotherNested/Dockerfile.web', './Dockerfile.web'] + const dockerfiles = [ + Path.join('.', 'Nested', 'Dockerfile.web'), + Path.join('.', 'OtherNested', 'Dockerfile.web'), + Path.join('.', 'AnotherNested', 'Dockerfile.web', './Dockerfile.web') + ] let jobs = Sanbashi.getJobs('rootfulroot', ['web'], dockerfiles) let res = Sanbashi.chooseJobs(jobs) // .then((chosen) => { @@ -80,7 +98,7 @@ describe('Sanbashi', () => { console.dir(res) }) afterEach(() => { - if(Inquirer.prompt.restore) + if (Inquirer.prompt.restore) Inquirer.prompt.restore() }) }) diff --git a/yarn.lock b/yarn.lock index 85a66e8..21a304c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -53,6 +53,10 @@ balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" +base64-js@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.2.tgz#024f0f72afa25b75f9c0ee73cd4f55ec1bed9784" + bl@~0.9.0: version "0.9.5" resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" @@ -65,6 +69,13 @@ boom@2.x.x: dependencies: hoek "2.x.x" +bops@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.6.tgz#082d1d55fa01e60dbdc2ebc2dba37f659554cf3a" + dependencies: + base64-js "0.0.2" + to-utf8 "0.0.1" + brace-expansion@^1.0.0: version "1.1.7" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" @@ -76,10 +87,6 @@ buffer-equal@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" -buffer-shims@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - camelcase@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.0.2.tgz#7912eac1d496836782c976c2d73e874dc54f2eaf" @@ -107,7 +114,7 @@ chai@^3.2.0: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@^1.0.0, chalk@^1.1.3: +chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -161,13 +168,11 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.4.8: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" +concat-stream@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.1.0.tgz#84269efd8cc650275e322f309df44867bc51c5f3" dependencies: - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" + bops "0.0.6" cookiejar@2.0.1: version "2.0.1" @@ -193,13 +198,7 @@ ctype@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" -debug@2, debug@^2.2.0: - version "2.6.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a" - dependencies: - ms "0.7.3" - -debug@2.2.0: +debug@2, debug@2.2.0, debug@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" dependencies: @@ -407,7 +406,7 @@ hawk@~2.3.0: hoek "2.x.x" sntp "1.x.x" -heroku-cli-util@^6.1.17: +heroku-cli-util@6.1.17: version "6.1.17" resolved "https://registry.yarnpkg.com/heroku-cli-util/-/heroku-cli-util-6.1.17.tgz#3d1e5eb62f2a7e73053b4768054cc6df14b4d578" dependencies: @@ -434,6 +433,19 @@ heroku-cli-util@^6.1.17: supports-color "^3.1.2" tunnel-agent "^0.4.3" +heroku-client@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-1.9.1.tgz#898e18dd09dabee9afe90cc0cf414d1a569d0d74" + dependencies: + concat-stream "~1.1.0" + inflection "~1.2.6" + lazy.js "~0.3.2" + logfmt "^1.1.2" + memjs "~0.6.0" + path-proxy "~1.0" + q "~0.9.6" + simple-encryptor "^1.0.2" + heroku-client@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-3.0.2.tgz#7e06f303ff18f7a0731725dcccbe210b76198657" @@ -442,19 +454,6 @@ heroku-client@3.0.2: is-retry-allowed "^1.0.0" tunnel-agent "^0.4.0" -heroku-client@^1.9.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-1.11.0.tgz#9ff0e041a3d1b363a72fa01ff876b316f6985773" - dependencies: - concat-stream "^1.4.8" - inflection "^1.7.0" - lazy.js "^0.4.0" - logfmt "^1.1.2" - memjs "^0.8.5" - path-proxy "^1.0" - q "^1.2.0" - simple-encryptor "^1.0.2" - hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" @@ -467,9 +466,9 @@ http-signature@~0.10.0: assert-plus "^0.1.5" ctype "0.5.3" -inflection@^1.7.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" +inflection@~1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.2.7.tgz#59db4505310a746677182ed46e155e003bfb3591" inflection@~1.3.0: version "1.3.8" @@ -482,11 +481,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.1: +inherits@2, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -inquirer@^3.0.6: +inquirer@3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" dependencies: @@ -532,10 +531,6 @@ isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - isstream@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -557,9 +552,9 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" -lazy.js@^0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/lazy.js/-/lazy.js-0.4.3.tgz#87f67a07ad36555121e4fff1520df31be66786d8" +lazy.js@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/lazy.js/-/lazy.js-0.3.2.tgz#7cc1107e5f809ae70498f511dd180e1f80b4efa9" lex@^1.7.9: version "1.7.9" @@ -645,9 +640,9 @@ lru-cache@2: version "2.7.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" -memjs@^0.8.5: - version "0.8.9" - resolved "https://registry.yarnpkg.com/memjs/-/memjs-0.8.9.tgz#578d5c5a3c31711a9d137fcccc5af41147edc5ed" +memjs@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/memjs/-/memjs-0.6.0.tgz#cdbf6d513b3059f21cfbb910e2e79f15d9b0dc03" methods@1.0.1: version "1.0.1" @@ -729,10 +724,6 @@ ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -ms@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" - mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -747,7 +738,11 @@ netrc-parser@2.0.1: dependencies: lex "^1.7.9" -node-uuid@^1.4.3, node-uuid@~1.4.0: +node-uuid@1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.3.tgz#319bb7a56e7cb63f00b5c0cd7851cd4b4ddf1df9" + +node-uuid@~1.4.0: version "1.4.8" resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" @@ -792,7 +787,7 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-proxy@^1.0: +path-proxy@~1.0: version "1.0.0" resolved "https://registry.yarnpkg.com/path-proxy/-/path-proxy-1.0.0.tgz#18e8a36859fc9d2f1a53b48dee138543c020de5e" dependencies: @@ -808,10 +803,6 @@ prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - progress@1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" @@ -820,10 +811,14 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -q@^1.0.1, q@^1.2.0: +q@^1.0.1: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" +q@~0.9.6: + version "0.9.7" + resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" + qs@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.0.tgz#ed079be28682147e6fd9a34cc2b0c1e0ec6453ee" @@ -841,18 +836,6 @@ readable-stream@1.0.27-1: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.2.2: - version "2.2.9" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" - dependencies: - buffer-shims "~1.0.0" - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~1.0.0" - util-deprecate "~1.0.1" - readable-stream@~1.0.26: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -979,12 +962,6 @@ string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -string_decoder@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" - dependencies: - buffer-shims "~1.0.0" - stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -995,7 +972,7 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -superagent@^0.21.0: +superagent@0.21.0: version "0.21.0" resolved "https://registry.yarnpkg.com/superagent/-/superagent-0.21.0.tgz#fb15027984751ee7152200e6cd21cd6e19a5de87" dependencies: @@ -1047,6 +1024,10 @@ to-iso-string@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" +to-utf8@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852" + tough-cookie@>=0.12.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" @@ -1069,10 +1050,6 @@ type-detect@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - underscore.string@~2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" @@ -1091,10 +1068,6 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - walkdir@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.7.tgz#04da0270a87a778540173cdbf0a2db499a8d9e29" From c00e78086b4dbc1b750798f940b202845a0d2e7e Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Thu, 11 May 2017 16:32:29 -0500 Subject: [PATCH 08/24] minor fixes and updates --- commands/push.js | 15 +++++++-------- index.js | 4 ++++ package.json | 19 +++++++++---------- yarn.lock | 8 ++------ 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/commands/push.js b/commands/push.js index 94f7925..a6bc14b 100644 --- a/commands/push.js +++ b/commands/push.js @@ -1,13 +1,12 @@ const cli = require('heroku-cli-util') const Sanbashi = require('../lib/sanbashi') -const Chalk = require('chalk') let usage = ` - ${Chalk.bold.underline.magenta('Usage:')} - ${ Chalk.white(' heroku container:push web')} # Pushes Dockerfile in current directory - ${ Chalk.white(' heroku container:push web worker')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory - ${ Chalk.white(' heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory or subdirectories - ${ Chalk.white(' heroku container:push --recursive')} # Pushes Dockerfile.* found in current directory or subdirectories` + ${cli.color.bold.underline.magenta('Usage:')} + ${ cli.color.white('heroku container:push web')} # Pushes Dockerfile in current directory + ${ cli.color.white('heroku container:push web worker')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory + ${ cli.color.white('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory or subdirectories + ${ cli.color.white('heroku container:push --recursive')} # Pushes Dockerfile.* found in current directory or subdirectories` module.exports = function (topic) { return { @@ -52,7 +51,7 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.log(Chalk.bold.white.bgMagenta(`\n=== Building ${job.name} (${job.dockerfile})`)) + cli.log(cli.color.bold.white.bgMagenta(`\n=== Building ${job.name} (${job.dockerfile})`)) await Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) } } @@ -64,7 +63,7 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.log(Chalk.bold.white.bgMagenta(`\n=== Pushing ${job.name} (${job.dockerfile })`)) + cli.log(cli.color.bold.white.bgMagenta(`\n=== Pushing ${job.name} (${job.dockerfile })`)) await Sanbashi.pushImage(job.resource, context.flags.verbose) } } diff --git a/index.js b/index.js index 29382ac..5d1eb3e 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,10 @@ var pkg = require('./package.json'); module.exports = { + topic: { + description: 'Use containers to build and deploy Heroku apps', + name: 'container' + }, commands: [ require('./commands/index')(pkg), require('./commands/login')(pkg.topic), diff --git a/package.json b/package.json index decbf42..cb5d989 100644 --- a/package.json +++ b/package.json @@ -19,15 +19,14 @@ "license": "ISC", "dependencies": { "camelcase": "1.0.2", - "chalk": "1.1.3", - "dotenv": "^1.1.0", + "dotenv": "1.1.0", "glob": "7.1.0", "heroku-cli-util": "6.1.17", "heroku-client": "1.9.1", "inquirer": "3.0.6", "is-there": "4.0.0", "lodash": "3.3.1", - "mkdirp": "^0.5.0", + "mkdirp": "0.5.0", "node-uuid": "1.4.3", "progress": "1.1.8", "request": "2.53.0", @@ -35,12 +34,12 @@ "yamljs": "0.2.4" }, "devDependencies": { - "chai": "^3.2.0", - "depcheck": "^0.4.7", - "dir-compare": "^0.0.2", - "fs-extra": "^0.23.1", - "mocha": "^2.2.4", - "sinon": "^2.1.0", - "wrench": "^1.5.8" + "chai": "3.2.0", + "depcheck": "0.4.7", + "dir-compare": "0.0.2", + "fs-extra": "0.23.1", + "mocha": "2.2.4", + "sinon": "2.1.0", + "wrench": "1.5.8" } } diff --git a/yarn.lock b/yarn.lock index 21a304c..3cabf77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -114,7 +114,7 @@ chai@^3.2.0: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -738,14 +738,10 @@ netrc-parser@2.0.1: dependencies: lex "^1.7.9" -node-uuid@1.4.3: +node-uuid@1.4.3, node-uuid@~1.4.0: version "1.4.3" resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.3.tgz#319bb7a56e7cb63f00b5c0cd7851cd4b4ddf1df9" -node-uuid@~1.4.0: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - oauth-sign@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.6.0.tgz#7dbeae44f6ca454e1f168451d630746735813ce3" From 99f90f8973a1f144df4478700d35e68717c3ba6d Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Fri, 12 May 2017 10:49:20 -0500 Subject: [PATCH 09/24] remove heroku-client dependency --- package.json | 1 - yarn.lock | 228 +++++++++++++++++---------------------------------- 2 files changed, 75 insertions(+), 154 deletions(-) diff --git a/package.json b/package.json index cb5d989..e625b06 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "dotenv": "1.1.0", "glob": "7.1.0", "heroku-cli-util": "6.1.17", - "heroku-client": "1.9.1", "inquirer": "3.0.6", "is-there": "4.0.0", "lodash": "3.3.1", diff --git a/yarn.lock b/yarn.lock index 3cabf77..ac935a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -53,10 +53,6 @@ balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" -base64-js@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.2.tgz#024f0f72afa25b75f9c0ee73cd4f55ec1bed9784" - bl@~0.9.0: version "0.9.5" resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" @@ -69,14 +65,7 @@ boom@2.x.x: dependencies: hoek "2.x.x" -bops@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.6.tgz#082d1d55fa01e60dbdc2ebc2dba37f659554cf3a" - dependencies: - base64-js "0.0.2" - to-utf8 "0.0.1" - -brace-expansion@^1.0.0: +brace-expansion@^1.0.0, brace-expansion@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" dependencies: @@ -106,9 +95,9 @@ caseless@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.9.0.tgz#b7b65ce6bf1413886539cfd533f0b30effa9cf88" -chai@^3.2.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" +chai@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-3.2.0.tgz#a91c06acc01057f4f4b67ed7785bd7ff4466b2fb" dependencies: assertion-error "^1.0.1" deep-eql "^0.1.3" @@ -168,12 +157,6 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.1.0.tgz#84269efd8cc650275e322f309df44867bc51c5f3" - dependencies: - bops "0.0.6" - cookiejar@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.0.1.tgz#3d12752f6adf68a892f332433492bd5812bb668f" @@ -198,11 +181,17 @@ ctype@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" -debug@2, debug@2.2.0, debug@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" +debug@2, debug@^2.2.0: + version "2.6.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a" dependencies: - ms "0.7.1" + ms "0.7.3" + +debug@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.0.0.tgz#89bd9df6732b51256bc6705342bba02ed12131ef" + dependencies: + ms "0.6.2" deep-eql@^0.1.3: version "0.1.3" @@ -218,7 +207,7 @@ delayed-stream@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" -depcheck@^0.4.7: +depcheck@0.4.7: version "0.4.7" resolved "https://registry.yarnpkg.com/depcheck/-/depcheck-0.4.7.tgz#2584e2dd05c50026f64a37f64c36e625c53a9d41" dependencies: @@ -236,15 +225,15 @@ detective@^4.0.0: acorn "^4.0.3" defined "^1.0.0" -diff@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" +diff@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.0.8.tgz#343276308ec991b7bc82267ed55bc1411f971666" diff@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" -dir-compare@^0.0.2: +dir-compare@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-0.0.2.tgz#156da5dfa7e841479d5e9d0ca857857f7faef36c" dependencies: @@ -253,19 +242,19 @@ dir-compare@^0.0.2: commander "2.5.0" minimatch "2.0.1" -dotenv@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-1.2.0.tgz#7cd73e16e07f057c8072147a5bc3a8677f0ab5c6" +dotenv@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-1.1.0.tgz#97438b62f487ff6c9b157b0f9e713b335e590b4e" duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" -escape-string-regexp@1.0.2, escape-string-regexp@^1.0.2: +escape-string-regexp@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -319,7 +308,7 @@ formidable@1.0.14: version "1.0.14" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.14.tgz#2b3f4c411cbb5fdd695c44843e2a23514a43231a" -fs-extra@^0.23.1: +fs-extra@0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.23.1.tgz#6611dba6adf2ab8dc9c69fab37cddf8818157e3d" dependencies: @@ -336,12 +325,13 @@ get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" -glob@3.2.11: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" +glob@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.3.tgz#e313eeb249c7affaa5c475286b0e115b59839467" dependencies: + graceful-fs "~2.0.0" inherits "2" - minimatch "0.3" + minimatch "~0.2.11" glob@7.1.0, glob@^7.0.5: version "7.1.0" @@ -383,9 +373,13 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" +graceful-fs@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-2.0.3.tgz#7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0" + +growl@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428" has-ansi@^2.0.0: version "2.0.0" @@ -433,19 +427,6 @@ heroku-cli-util@6.1.17: supports-color "^3.1.2" tunnel-agent "^0.4.3" -heroku-client@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-1.9.1.tgz#898e18dd09dabee9afe90cc0cf414d1a569d0d74" - dependencies: - concat-stream "~1.1.0" - inflection "~1.2.6" - lazy.js "~0.3.2" - logfmt "^1.1.2" - memjs "~0.6.0" - path-proxy "~1.0" - q "~0.9.6" - simple-encryptor "^1.0.2" - heroku-client@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/heroku-client/-/heroku-client-3.0.2.tgz#7e06f303ff18f7a0731725dcccbe210b76198657" @@ -466,14 +447,6 @@ http-signature@~0.10.0: assert-plus "^0.1.5" ctype "0.5.3" -inflection@~1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.2.7.tgz#59db4505310a746677182ed46e155e003bfb3591" - -inflection@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.3.8.tgz#cbd160da9f75b14c3cc63578d4f396784bf3014e" - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -552,10 +525,6 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" -lazy.js@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/lazy.js/-/lazy.js-0.3.2.tgz#7cc1107e5f809ae70498f511dd180e1f80b4efa9" - lex@^1.7.9: version "1.7.9" resolved "https://registry.yarnpkg.com/lex/-/lex-1.7.9.tgz#5d5636ccef574348362938b79a47f0eed8ed0d43" @@ -616,18 +585,6 @@ lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@~2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" - -logfmt@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/logfmt/-/logfmt-1.2.0.tgz#1ccc067c1cfe65f3ecf5856c09d2654f69203572" - dependencies: - lodash "~2.4.1" - split "0.2.x" - through "2.3.x" - lolex@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" @@ -640,10 +597,6 @@ lru-cache@2: version "2.7.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" -memjs@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/memjs/-/memjs-0.6.0.tgz#cdbf6d513b3059f21cfbb910e2e79f15d9b0dc03" - methods@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/methods/-/methods-1.0.1.tgz#75bc91943dffd7da037cf3eeb0ed73a0037cd14b" @@ -666,13 +619,6 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - minimatch@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.1.tgz#6c3760b45f66ed1cd5803143ee8d372488f02c37" @@ -686,10 +632,17 @@ minimatch@^2.0.1: brace-expansion "^1.0.0" minimatch@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: - brace-expansion "^1.0.0" + brace-expansion "^1.1.7" + +minimatch@~0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" + dependencies: + lru-cache "2" + sigmund "~1.0.0" minimist@0.0.8, minimist@~0.0.1: version "0.0.8" @@ -699,30 +652,33 @@ mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" -mkdirp@0.5.1, mkdirp@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" +mkdirp@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" dependencies: minimist "0.0.8" -mocha@^2.2.4: - version "2.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" +mocha@2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.2.4.tgz#192b0edc0e17e56613bc66e5fc7e81c00413a98d" dependencies: commander "2.3.0" - debug "2.2.0" - diff "1.4.0" + debug "2.0.0" + diff "1.0.8" escape-string-regexp "1.0.2" - glob "3.2.11" - growl "1.9.2" + glob "3.2.3" + growl "1.8.1" jade "0.26.3" - mkdirp "0.5.1" - supports-color "1.2.0" - to-iso-string "0.0.2" + mkdirp "0.5.0" + supports-color "~1.2.0" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" +ms@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.6.2.tgz#d89c2124c6fdc1353d65a8b77bf1aac4b193708c" + +ms@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" mute-stream@0.0.7: version "0.0.7" @@ -783,12 +739,6 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-proxy@~1.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/path-proxy/-/path-proxy-1.0.0.tgz#18e8a36859fc9d2f1a53b48dee138543c020de5e" - dependencies: - inflection "~1.3.0" - path-to-regexp@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" @@ -811,10 +761,6 @@ q@^1.0.1: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" -q@~0.9.6: - version "0.9.7" - resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" - qs@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.0.tgz#ed079be28682147e6fd9a34cc2b0c1e0ec6453ee" @@ -904,10 +850,6 @@ samsam@1.x, samsam@^1.1.3: version "1.2.1" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67" -scmp@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/scmp/-/scmp-0.0.3.tgz#3648df2d7294641e7f78673ffc29681d9bad9073" - sigmund@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -916,13 +858,7 @@ signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -simple-encryptor@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/simple-encryptor/-/simple-encryptor-1.1.0.tgz#653bb1926c8f0fc2b8d7038577cc846053263ae8" - dependencies: - scmp "0.0.3" - -sinon@^2.1.0: +sinon@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.1.0.tgz#e057a9d2bf1b32f5d6dd62628ca9ee3961b0cafb" dependencies: @@ -941,12 +877,6 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -split@0.2.x: - version "0.2.10" - resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" - dependencies: - through "2" - string-width@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" @@ -984,10 +914,6 @@ superagent@0.21.0: readable-stream "1.0.27-1" reduce-component "1.0.1" -supports-color@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -998,11 +924,15 @@ supports-color@^3.1.2: dependencies: has-flag "^1.0.0" +supports-color@~1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.1.tgz#12ee21507086cd98c1058d9ec0f4ac476b7af3b2" + text-encoding@0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" -through@2, through@2.3.x, through@^2.3.6: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1016,14 +946,6 @@ tmp@^0.0.31: dependencies: os-tmpdir "~1.0.1" -to-iso-string@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" - -to-utf8@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852" - tough-cookie@>=0.12.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" @@ -1076,9 +998,9 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -wrench@^1.5.8: - version "1.5.9" - resolved "https://registry.yarnpkg.com/wrench/-/wrench-1.5.9.tgz#411691c63a9b2531b1700267279bdeca23b2142a" +wrench@1.5.8: + version "1.5.8" + resolved "https://registry.yarnpkg.com/wrench/-/wrench-1.5.8.tgz#7a31c97f7869246d76c5cf2f5c977a1c4c8e5ab5" yamljs@0.2.4: version "0.2.4" From c940247ca4e3335139596a725adec39660bbad5e Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Fri, 19 May 2017 11:39:15 -0500 Subject: [PATCH 10/24] do not treat 'Dockerfile' as 'Dockerfile.web' --- commands/push.js | 4 +- lib/sanbashi.js | 168 +++++++++++++++++++++--------------------- test/sanbashi.test.js | 5 +- 3 files changed, 89 insertions(+), 88 deletions(-) diff --git a/commands/push.js b/commands/push.js index a6bc14b..102231d 100644 --- a/commands/push.js +++ b/commands/push.js @@ -7,7 +7,7 @@ let usage = ` ${ cli.color.white('heroku container:push web worker')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory ${ cli.color.white('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory or subdirectories ${ cli.color.white('heroku container:push --recursive')} # Pushes Dockerfile.* found in current directory or subdirectories` - + module.exports = function (topic) { return { topic: topic, @@ -36,7 +36,7 @@ module.exports = function (topic) { let push = async function (context, heroku) { const recurse = !!context.flags.recursive if (context.args.length === 0 && !recurse) { - cli.error( `Error: Requires either --recursive or one or more process types\n ${usage} `) + cli.error(`Error: Requires either --recursive or one or more process types\n ${usage} `) process.exit(1) } let herokuHost = process.env.HEROKU_HOST || 'heroku.com' diff --git a/lib/sanbashi.js b/lib/sanbashi.js index dfc5cc7..d843884 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -7,99 +7,99 @@ const Child = require('child_process') const log = require('./log') const DOCKERFILE_REGEX = /\bDockerfile(.\w*)?$/ -let Sanbashi = function(){} +let Sanbashi = function () {} - Sanbashi.getDockerfiles = function(rootdir, recursive) { - let match = recursive ? './**/Dockerfile?(.)*' : 'Dockerfile*' - let dockerfiles = Glob.sync(match, { - cwd: rootdir, - nonull: false, - nodir: true - }) - if (recursive) { - dockerfiles = dockerfiles.filter(df => df.match(/Dockerfile\.[\w]+/)) - } - return dockerfiles.map(file => Path.join(rootdir, file)) +Sanbashi.getDockerfiles = function (rootdir, recursive) { + let match = recursive ? './**/Dockerfile?(.)*' : 'Dockerfile*' + let dockerfiles = Glob.sync(match, { + cwd: rootdir, + nonull: false, + nodir: true + }) + if (recursive) { + dockerfiles = dockerfiles.filter(df => df.match(/Dockerfile\.[\w]+/)) } + return dockerfiles.map(file => Path.join(rootdir, file)) +} - Sanbashi.getJobs = function(resourceRoot, procs, dockerfiles) { - return dockerfiles - // convert all Dockerfiles into job Objects - .map((dockerfile) => { - let match = dockerfile.match(DOCKERFILE_REGEX) - if (!match) return - let proc = (match[1] || '.web').slice(1) - return { - name: proc, - resource: `${ resourceRoot }/${ proc }`, - dockerfile: dockerfile, - postfix: Path.basename(dockerfile) === 'Dockerfile' ? 0 : 1, - depth: Path.normalize(dockerfile).split(Path.sep).length - } - }) - // if process types have been specified, filter non matches out - .filter(job => { - return job && (!procs.length || procs.indexOf(job.name) !== -1) - }) - // prefer closer Dockerfiles, then prefer Dockerfile over Dockerfile.web - .sort((a, b) => { - return a.depth - b.depth || a.postfix - b.postfix - }) - // group all Dockerfiles for the same process type together - .reduce((jobs, job) => { - jobs[job.name] = jobs[job.name] || [] - jobs[job.name].push(job) - return jobs - }, {}) - } +Sanbashi.getJobs = function (resourceRoot, procs, dockerfiles) { + return dockerfiles + // convert all Dockerfiles into job Objects + .map((dockerfile) => { + let match = dockerfile.match(DOCKERFILE_REGEX) + if (!match) return + let proc = (match[1] || '.unknown').slice(1) + return { + name: proc, + resource: `${ resourceRoot }/${ proc }`, + dockerfile: dockerfile, + postfix: Path.basename(dockerfile) === 'Dockerfile' ? 0 : 1, + depth: Path.normalize(dockerfile).split(Path.sep).length + } + }) + // if process types have been specified, filter non matches out + .filter(job => { + return job && (!procs.length || procs.indexOf(job.name) !== -1) + }) + // prefer closer Dockerfiles, then prefer Dockerfile over Dockerfile.web + .sort((a, b) => { + return a.depth - b.depth || a.postfix - b.postfix + }) + // group all Dockerfiles for the same process type together + .reduce((jobs, job) => { + jobs[job.name] = jobs[job.name] || [] + jobs[job.name].push(job) + return jobs + }, {}) +} - Sanbashi.chooseJobs = async function(jobs) { - let chosenJobs = [] - for(let processType in jobs){ - let group = jobs[processType] - if (group.length > 1) { - let prompt = { - type: 'list', - name: processType, - choices: group.map(j => j.dockerfile), - message: `Found multiple Dockerfiles with process type ${processType}. Please choose one to build and push ` - } - let answer = await Inquirer.prompt(prompt) - chosenJobs.push(group.find(o => o.dockerfile === answer[processType])) - } else { - chosenJobs.push(group[0]) +Sanbashi.chooseJobs = async function (jobs) { + let chosenJobs = [] + for (let processType in jobs) { + let group = jobs[processType] + if (group.length > 1) { + let prompt = { + type: 'list', + name: processType, + choices: group.map(j => j.dockerfile), + message: `Found multiple Dockerfiles with process type ${processType}. Please choose one to build and push ` } - } - return chosenJobs + let answer = await Inquirer.prompt(prompt) + chosenJobs.push(group.find(o => o.dockerfile === answer[processType])) + } else { + chosenJobs.push(group[0]) + } } + return chosenJobs +} - Sanbashi.buildImage = function(dockerfile, resource, verbose) { - return new Promise((resolve, reject) => { - let cwd = Path.dirname(dockerfile) - let args = ['build', '-f', dockerfile, '-t', resource, cwd] - log(verbose, args) - Child.spawn('docker', args, { - stdio: 'inherit' - }) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code) - else resolve() - }) +Sanbashi.buildImage = function (dockerfile, resource, verbose) { + return new Promise((resolve, reject) => { + let cwd = Path.dirname(dockerfile) + let args = ['build', '-f', dockerfile, '-t', resource, cwd] + log(verbose, args) + Child.spawn('docker', args, { + stdio: 'inherit' }) - } - - Sanbashi.pushImage = function(resource, verbose) { - return new Promise((resolve, reject) => { - let args = ['push', resource] - log(verbose, args) - Child.spawn('docker', args, { - stdio: 'inherit' + .on('exit', (code, signal) => { + if (signal || code) reject(signal || code) + else resolve() }) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code) - else resolve() - }) + }) +} + +Sanbashi.pushImage = function (resource, verbose) { + return new Promise((resolve, reject) => { + let args = ['push', resource] + log(verbose, args) + Child.spawn('docker', args, { + stdio: 'inherit' }) - } + .on('exit', (code, signal) => { + if (signal || code) reject(signal || code) + else resolve() + }) + }) +} module.exports = Sanbashi diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index 47cc3a3..34f2484 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -34,10 +34,11 @@ describe('Sanbashi', () => { expect(results.web[0]).to.have.property('depth', 1, 'dockerfile', './Dockerfile.web', 'postfix', 1) expect(results.web[1]).to.have.property('depth', 2, 'dockerfile', './Nested/Dockerfile.web', 'postfix', 1) }) - it('filters out by process type', () => { + it.only('filters out by process type', () => { const dockerfiles = [ Path.join('.', 'Dockerfile.web'), - Path.join('.', 'Nested', 'Dockerfile.worker') + Path.join('.', 'Nested', 'Dockerfile.worker'), + Path.join('.', 'Dockerfile') ] const resourceRoot = 'rootfulroot' const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) From be01673c412c59f0f78b3ecc0d556136f511ac46 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Mon, 22 May 2017 10:50:23 -0500 Subject: [PATCH 11/24] use regular dockerfile when recurse arg omitted --- commands/push.js | 11 +++++++++-- lib/sanbashi.js | 2 +- test/sanbashi.test.js | 14 +++++++------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/commands/push.js b/commands/push.js index 102231d..3967ac1 100644 --- a/commands/push.js +++ b/commands/push.js @@ -4,7 +4,6 @@ const Sanbashi = require('../lib/sanbashi') let usage = ` ${cli.color.bold.underline.magenta('Usage:')} ${ cli.color.white('heroku container:push web')} # Pushes Dockerfile in current directory - ${ cli.color.white('heroku container:push web worker')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory ${ cli.color.white('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory or subdirectories ${ cli.color.white('heroku container:push --recursive')} # Pushes Dockerfile.* found in current directory or subdirectories` @@ -39,10 +38,18 @@ let push = async function (context, heroku) { cli.error(`Error: Requires either --recursive or one or more process types\n ${usage} `) process.exit(1) } + if(context.args.length > 1 && !recurse){ + cli.error(`Error: Please specify one target process type\n ${usage} `) + process.exit(1) + } let herokuHost = process.env.HEROKU_HOST || 'heroku.com' let registry = `registry.${ herokuHost }` let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) - let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, context.args, dockerfiles) + let processTypes = ['standard'] + if(recurse){ + processTypes = context.args + } + let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, processTypes, dockerfiles) let jobs = await Sanbashi.chooseJobs(possibleJobs) if (!jobs.length) { cli.warn('No images to push') diff --git a/lib/sanbashi.js b/lib/sanbashi.js index d843884..9bf44d7 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -28,7 +28,7 @@ Sanbashi.getJobs = function (resourceRoot, procs, dockerfiles) { .map((dockerfile) => { let match = dockerfile.match(DOCKERFILE_REGEX) if (!match) return - let proc = (match[1] || '.unknown').slice(1) + let proc = (match[1] || '.standard').slice(1) return { name: proc, resource: `${ resourceRoot }/${ proc }`, diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index 34f2484..10a5c82 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -34,7 +34,7 @@ describe('Sanbashi', () => { expect(results.web[0]).to.have.property('depth', 1, 'dockerfile', './Dockerfile.web', 'postfix', 1) expect(results.web[1]).to.have.property('depth', 2, 'dockerfile', './Nested/Dockerfile.web', 'postfix', 1) }) - it.only('filters out by process type', () => { + it('filters out by process type', () => { const dockerfiles = [ Path.join('.', 'Dockerfile.web'), Path.join('.', 'Nested', 'Dockerfile.worker'), @@ -53,10 +53,10 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, [], dockerfiles) - expect(results.web).to.have.property('length', 2) + const results = Sanbashi.getJobs(resourceRoot, ['web','standard','worker'], dockerfiles) + expect(results.web).to.have.property('length', 1) expect(results.web[0]).to.have.property('dockerfile', 'Dockerfile.web') - expect(results.web[1]).to.have.property('dockerfile', 'Nested/Dockerfile') + expect(results.standard[0]).to.have.property('dockerfile', 'Nested/Dockerfile') expect(results.worker[0]).to.have.property('dockerfile', 'Nested/Dockerfile.worker') }) it('groups the jobs by process type', () => { @@ -66,16 +66,16 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, [], dockerfiles) + const results = Sanbashi.getJobs(resourceRoot, ['web', 'worker'], dockerfiles) expect(results).to.have.keys('worker', 'web') expect(results['worker'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Nested', 'Dockerfile.worker')]) - expect(results['web'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Dockerfile.web'), Path.join('.', 'Nested', 'Dockerfile')]) + expect(results['web'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Dockerfile.web')]) }) }) describe('.chooseJobs', () => { it('returns the entry when only one exists', async () => { const dockerfiles = [Path.join('.', 'Nested', 'Dockerfile.web')] - const jobs = Sanbashi.getJobs('rootfulroot', [], dockerfiles) + const jobs = Sanbashi.getJobs('rootfulroot', ['web'], dockerfiles) let chosenJob = await Sanbashi.chooseJobs(jobs) expect(chosenJob[0]).to.have.property('dockerfile', dockerfiles[0]) expect(chosenJob).to.have.property('length', 1) From be7651f24d09c777f8b64de40d9471facae5849c Mon Sep 17 00:00:00 2001 From: jbyrum Date: Mon, 22 May 2017 09:56:15 -0700 Subject: [PATCH 12/24] Remove docker text --- commands/login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/login.js b/commands/login.js index 1f16c98..a5785a9 100644 --- a/commands/login.js +++ b/commands/login.js @@ -7,7 +7,7 @@ module.exports = function (topic) { topic: topic, command: 'login', flags: [{name: 'verbose', char: 'v', hasValue: false}], - description: 'logs in to the Heroku Docker registry', + description: 'logs in to the Heroku Container Registry', help: `Usage: heroku container:login`, needsApp: false, From 5b148f98bf617a18ffeab27e162fccf595bd242c Mon Sep 17 00:00:00 2001 From: jbyrum Date: Mon, 22 May 2017 09:57:17 -0700 Subject: [PATCH 13/24] Remove Docker text --- commands/logout.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/logout.js b/commands/logout.js index 874d2f3..e5231c2 100644 --- a/commands/logout.js +++ b/commands/logout.js @@ -7,7 +7,7 @@ module.exports = function(topic) { topic: topic, command: 'logout', flags: [{ name: 'verbose', char: 'v', hasValue: false }], - description: 'logs out from the Heroku Docker registry', + description: 'logs out from the Heroku Container Registry', help: `Usage: heroku container:logout`, needsApp: false, From fc6fc7bb067fefd8f4e095487eeb1939722c2bbd Mon Sep 17 00:00:00 2001 From: jbyrum Date: Mon, 22 May 2017 10:05:11 -0700 Subject: [PATCH 14/24] Update to usage text --- commands/push.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/push.js b/commands/push.js index 3967ac1..dcb6157 100644 --- a/commands/push.js +++ b/commands/push.js @@ -3,9 +3,9 @@ const Sanbashi = require('../lib/sanbashi') let usage = ` ${cli.color.bold.underline.magenta('Usage:')} - ${ cli.color.white('heroku container:push web')} # Pushes Dockerfile in current directory - ${ cli.color.white('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in the current directory or subdirectories - ${ cli.color.white('heroku container:push --recursive')} # Pushes Dockerfile.* found in current directory or subdirectories` + ${ cli.color.white('heroku container:push web')} # Pushes Dockerfile in current directory to web process type + ${ cli.color.white('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in current & subdirectories + ${ cli.color.white('heroku container:push --recursive')} # Pushes Dockerfile.* found in current & subdirectories` module.exports = function (topic) { return { From 632a3c85eb7bed4b775d329857a06b8b21bad872 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Mon, 22 May 2017 14:30:57 -0500 Subject: [PATCH 15/24] change headers to use cli.styledHeader --- commands/push.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/push.js b/commands/push.js index dcb6157..8f9a456 100644 --- a/commands/push.js +++ b/commands/push.js @@ -58,7 +58,7 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.log(cli.color.bold.white.bgMagenta(`\n=== Building ${job.name} (${job.dockerfile})`)) + cli.styledHeader(`Building ${job.name} (${job.dockerfile})`) await Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) } } @@ -70,7 +70,7 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.log(cli.color.bold.white.bgMagenta(`\n=== Pushing ${job.name} (${job.dockerfile })`)) + cli.styledHeader(`Pushing ${job.name} (${job.dockerfile })`) await Sanbashi.pushImage(job.resource, context.flags.verbose) } } From 832be4ec0da1498da19b9a1e488b9b51b04b183e Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Mon, 5 Jun 2017 16:28:30 -0500 Subject: [PATCH 16/24] review feedback --- commands/index.js | 8 ++++---- commands/login.js | 1 + commands/logout.js | 42 ++++++++++++++++++++---------------------- commands/push.js | 15 ++++++++------- index.js | 12 ++++++------ lib/log.js | 6 +++--- test/sanbashi.test.js | 4 ++-- 7 files changed, 44 insertions(+), 44 deletions(-) diff --git a/commands/index.js b/commands/index.js index 32c515e..75a1af1 100644 --- a/commands/index.js +++ b/commands/index.js @@ -1,11 +1,11 @@ -module.exports = function index(pkg) { +module.exports = function index (pkg) { return { topic: pkg.topic, description: pkg.description, run: showVersion - }; + } - function showVersion(context) { - console.log(pkg.version); + function showVersion (context) { + console.log(pkg.version) } } diff --git a/commands/login.js b/commands/login.js index a5785a9..a879705 100644 --- a/commands/login.js +++ b/commands/login.js @@ -27,6 +27,7 @@ async function login (context, heroku) { catch (err) { cli.error(`Error: docker login exited with ${ err }`) cli.hush(err.stack || err) + cli.exit(1) } } diff --git a/commands/logout.js b/commands/logout.js index e5231c2..15519b9 100644 --- a/commands/logout.js +++ b/commands/logout.js @@ -1,44 +1,42 @@ -const cli = require('heroku-cli-util'); -const child = require('child_process'); -const log = require('../lib/log'); +const cli = require('heroku-cli-util') +const child = require('child_process') +const log = require('../lib/log') -module.exports = function(topic) { +module.exports = function (topic) { return { topic: topic, command: 'logout', - flags: [{ name: 'verbose', char: 'v', hasValue: false }], + flags: [{name: 'verbose', char: 'v', hasValue: false}], description: 'logs out from the Heroku Container Registry', - help: `Usage: - heroku container:logout`, needsApp: false, needsAuth: false, run: cli.command(logout) - }; -}; + } +} -async function logout(context, heroku) { - let herokuHost = process.env.HEROKU_HOST || 'heroku.com'; - let registry = `registry.${ herokuHost }`; +async function logout (context, heroku) { + let herokuHost = process.env.HEROKU_HOST || 'heroku.com' + let registry = `registry.${ herokuHost }` try { - let user = await dockerLogout(registry, context.flags.verbose); + let user = await dockerLogout(registry, context.flags.verbose) } catch (err) { - cli.error(`Error: docker logout exited with ${ err }`); + cli.error(`Error: docker logout exited with ${ err }`) } } -function dockerLogout(registry, verbose) { +function dockerLogout (registry, verbose) { return new Promise((resolve, reject) => { let args = [ 'logout', registry - ]; - log(verbose, args); - child.spawn('docker', args, { stdio: 'inherit' }) + ] + log(verbose, args) + child.spawn('docker', args, {stdio: 'inherit'}) .on('exit', (code, signal) => { - if (signal || code) reject(signal || code); - else resolve(); - }); - }); + if (signal || code) reject(signal || code) + else resolve() + }) + }) } diff --git a/commands/push.js b/commands/push.js index 8f9a456..b229ade 100644 --- a/commands/push.js +++ b/commands/push.js @@ -2,10 +2,10 @@ const cli = require('heroku-cli-util') const Sanbashi = require('../lib/sanbashi') let usage = ` - ${cli.color.bold.underline.magenta('Usage:')} - ${ cli.color.white('heroku container:push web')} # Pushes Dockerfile in current directory to web process type - ${ cli.color.white('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in current & subdirectories - ${ cli.color.white('heroku container:push --recursive')} # Pushes Dockerfile.* found in current & subdirectories` + ${cli.color.bold.underline.magenta('Usage:')} + ${ cli.color.cmd('heroku container:push web')} # Pushes Dockerfile in current directory to web process type + ${ cli.color.cmd('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in current & subdirectories + ${ cli.color.cmd('heroku container:push --recursive')} # Pushes Dockerfile.* found in current & subdirectories` module.exports = function (topic) { return { @@ -33,12 +33,13 @@ module.exports = function (topic) { } let push = async function (context, heroku) { + console.dir(context.args, {colors: true, depth: null}) const recurse = !!context.flags.recursive if (context.args.length === 0 && !recurse) { cli.error(`Error: Requires either --recursive or one or more process types\n ${usage} `) process.exit(1) } - if(context.args.length > 1 && !recurse){ + if (context.args.length > 1 && !recurse) { cli.error(`Error: Please specify one target process type\n ${usage} `) process.exit(1) } @@ -46,7 +47,7 @@ let push = async function (context, heroku) { let registry = `registry.${ herokuHost }` let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) let processTypes = ['standard'] - if(recurse){ + if (recurse || (!recurse && context.args.length)) { processTypes = context.args } let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, processTypes, dockerfiles) @@ -70,7 +71,7 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.styledHeader(`Pushing ${job.name} (${job.dockerfile })`) + cli.styledHeader(`Pushing ${job.name} (${job.dockerfile })`) await Sanbashi.pushImage(job.resource, context.flags.verbose) } } diff --git a/index.js b/index.js index 5d1eb3e..51a7fa2 100644 --- a/index.js +++ b/index.js @@ -1,14 +1,14 @@ -var pkg = require('./package.json'); +var pkg = require('./package.json') module.exports = { - topic: { - description: 'Use containers to build and deploy Heroku apps', - name: 'container' - }, + topic: { + description: 'Use containers to build and deploy Heroku apps', + name: 'container' + }, commands: [ require('./commands/index')(pkg), require('./commands/login')(pkg.topic), require('./commands/logout')(pkg.topic), require('./commands/push')(pkg.topic) ] -}; +} diff --git a/lib/log.js b/lib/log.js index bb15041..04c0bc1 100644 --- a/lib/log.js +++ b/lib/log.js @@ -1,4 +1,4 @@ module.exports = (visible, args) => { - if (!visible) return; - console.log(`> docker ${ args.join(' ') }`); -}; + if (!visible) return + console.log(`> docker ${ args.join(' ') }`) +} diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index 10a5c82..3b2bbb9 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -53,10 +53,10 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, ['web','standard','worker'], dockerfiles) + const results = Sanbashi.getJobs(resourceRoot, ['web', 'standard', 'worker'], dockerfiles) expect(results.web).to.have.property('length', 1) expect(results.web[0]).to.have.property('dockerfile', 'Dockerfile.web') - expect(results.standard[0]).to.have.property('dockerfile', 'Nested/Dockerfile') + expect(results.standard[0]).to.have.property('dockerfile', 'Nested/Dockerfile') expect(results.worker[0]).to.have.property('dockerfile', 'Nested/Dockerfile.worker') }) it('groups the jobs by process type', () => { From 07734795885d17e41f4dd8359522e47ae037b81c Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Fri, 9 Jun 2017 10:04:56 -0500 Subject: [PATCH 17/24] fix pushing standard dockerfiles --- commands/push.js | 15 +++++++++++---- lib/sanbashi.js | 2 ++ test/sanbashi.test.js | 33 ++++++++------------------------- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/commands/push.js b/commands/push.js index b229ade..ab4702c 100644 --- a/commands/push.js +++ b/commands/push.js @@ -33,7 +33,6 @@ module.exports = function (topic) { } let push = async function (context, heroku) { - console.dir(context.args, {colors: true, depth: null}) const recurse = !!context.flags.recursive if (context.args.length === 0 && !recurse) { cli.error(`Error: Requires either --recursive or one or more process types\n ${usage} `) @@ -47,7 +46,7 @@ let push = async function (context, heroku) { let registry = `registry.${ herokuHost }` let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) let processTypes = ['standard'] - if (recurse || (!recurse && context.args.length)) { + if (recurse) { processTypes = context.args } let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, processTypes, dockerfiles) @@ -59,7 +58,11 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.styledHeader(`Building ${job.name} (${job.dockerfile})`) + if(job.name === 'standard'){ + cli.styledHeader(`Building for ${context.args} (${job.dockerfile })`) + }else{ + cli.styledHeader(`Building ${job.name} (${job.dockerfile})`) + } await Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) } } @@ -71,7 +74,11 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - cli.styledHeader(`Pushing ${job.name} (${job.dockerfile })`) + if(job.name === 'standard'){ + cli.styledHeader(`Pushing for ${context.args} (${job.dockerfile })`) + }else{ + cli.styledHeader(`Pushing ${job.name} (${job.dockerfile })`) + } await Sanbashi.pushImage(job.resource, context.flags.verbose) } } diff --git a/lib/sanbashi.js b/lib/sanbashi.js index 9bf44d7..dc68b93 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -18,6 +18,8 @@ Sanbashi.getDockerfiles = function (rootdir, recursive) { }) if (recursive) { dockerfiles = dockerfiles.filter(df => df.match(/Dockerfile\.[\w]+/)) + } else { + dockerfiles = dockerfiles.filter(df => df.match(/Dockerfile$/)) } return dockerfiles.map(file => Path.join(rootdir, file)) } diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index 3b2bbb9..02f6f6f 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -6,11 +6,6 @@ let Inquirer = require('inquirer') describe('Sanbashi', () => { describe('.getDockerfiles', () => { - it('can find in just the given directory', () => { - const searchpath = Path.join(process.cwd(), './test/fixtures') - let results = Sanbashi.getDockerfiles(searchpath, false) - expect(results).to.have.members([`${searchpath}/Dockerfile.web`]) - }) it('can recurse the directory', () => { const searchpath = Path.join(process.cwd(), './test/fixtures') let results = Sanbashi.getDockerfiles(searchpath, true) @@ -21,6 +16,11 @@ describe('Sanbashi', () => { let results = Sanbashi.getDockerfiles(searchpath, true) expect(results).to.not.have.members([`${searchpath}/Dockerfile`]) }) + it('returns only regular Dockerfiles when not recursing', () => { + const searchpath = Path.join(process.cwd(), './test/fixtures/Nested') + let results = Sanbashi.getDockerfiles(searchpath, false) + expect(results).to.have.members([`${searchpath}/Dockerfile`]) + }) }) describe('.getJobs', () => { it('returns objects representing jobs per Dockerfile', () => { @@ -66,10 +66,11 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, ['web', 'worker'], dockerfiles) - expect(results).to.have.keys('worker', 'web') + const results = Sanbashi.getJobs(resourceRoot, ['web', 'worker', 'standard'], dockerfiles) + expect(results).to.have.keys('worker', 'web', 'standard') expect(results['worker'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Nested', 'Dockerfile.worker')]) expect(results['web'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Dockerfile.web')]) + expect(results['standard'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Nested', 'Dockerfile')]) }) }) describe('.chooseJobs', () => { @@ -80,24 +81,6 @@ describe('Sanbashi', () => { expect(chosenJob[0]).to.have.property('dockerfile', dockerfiles[0]) expect(chosenJob).to.have.property('length', 1) }) - it.skip('queries the user when more than one job of a type exists', () => { - //really no way to simulate user input for Inquirer - Sinon.stub(Inquirer, 'prompt').resolves('something') - const dockerfiles = [ - Path.join('.', 'Nested', 'Dockerfile.web'), - Path.join('.', 'OtherNested', 'Dockerfile.web'), - Path.join('.', 'AnotherNested', 'Dockerfile.web', './Dockerfile.web') - ] - let jobs = Sanbashi.getJobs('rootfulroot', ['web'], dockerfiles) - let res = Sanbashi.chooseJobs(jobs) - // .then((chosen) => { - // console.dir(chosen, { - // colors: true, - // depth: null - // }) - // }) - console.dir(res) - }) afterEach(() => { if (Inquirer.prompt.restore) Inquirer.prompt.restore() From 4f8e25e47a5264d34b617253bbe1fef66809fa80 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Fri, 9 Jun 2017 14:30:06 -0500 Subject: [PATCH 18/24] more regression fixing --- commands/push.js | 15 +++++++++------ lib/sanbashi.js | 18 +++++++++++++----- test/sanbashi.test.js | 34 ++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/commands/push.js b/commands/push.js index ab4702c..3a11d30 100644 --- a/commands/push.js +++ b/commands/push.js @@ -45,17 +45,20 @@ let push = async function (context, heroku) { let herokuHost = process.env.HEROKU_HOST || 'heroku.com' let registry = `registry.${ herokuHost }` let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) - let processTypes = ['standard'] - if (recurse) { - processTypes = context.args + + let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, dockerfiles) + let jobs + if(recurse){ + possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args) + jobs = await Sanbashi.chooseJobs(possibleJobs) + }else{ + possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0])}) + jobs = possibleJobs.standard || [] } - let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, processTypes, dockerfiles) - let jobs = await Sanbashi.chooseJobs(possibleJobs) if (!jobs.length) { cli.warn('No images to push') process.exit(1) } - try { for (let job of jobs) { if(job.name === 'standard'){ diff --git a/lib/sanbashi.js b/lib/sanbashi.js index dc68b93..a743782 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -24,7 +24,7 @@ Sanbashi.getDockerfiles = function (rootdir, recursive) { return dockerfiles.map(file => Path.join(rootdir, file)) } -Sanbashi.getJobs = function (resourceRoot, procs, dockerfiles) { +Sanbashi.getJobs = function (resourceRoot, dockerfiles) { return dockerfiles // convert all Dockerfiles into job Objects .map((dockerfile) => { @@ -39,10 +39,6 @@ Sanbashi.getJobs = function (resourceRoot, procs, dockerfiles) { depth: Path.normalize(dockerfile).split(Path.sep).length } }) - // if process types have been specified, filter non matches out - .filter(job => { - return job && (!procs.length || procs.indexOf(job.name) !== -1) - }) // prefer closer Dockerfiles, then prefer Dockerfile over Dockerfile.web .sort((a, b) => { return a.depth - b.depth || a.postfix - b.postfix @@ -75,6 +71,15 @@ Sanbashi.chooseJobs = async function (jobs) { return chosenJobs } +Sanbashi.filterByProcessType = function(jobs, procs){ + let filteredJobs = {} + procs.forEach((processType) => { + filteredJobs[processType] = jobs[processType] + }) + return filteredJobs +} + + Sanbashi.buildImage = function (dockerfile, resource, verbose) { return new Promise((resolve, reject) => { let cwd = Path.dirname(dockerfile) @@ -91,6 +96,7 @@ Sanbashi.buildImage = function (dockerfile, resource, verbose) { } Sanbashi.pushImage = function (resource, verbose) { + console.dir(resource, { colors:true, depth: null }) return new Promise((resolve, reject) => { let args = ['push', resource] log(verbose, args) @@ -104,4 +110,6 @@ Sanbashi.pushImage = function (resource, verbose) { }) } + + module.exports = Sanbashi diff --git a/test/sanbashi.test.js b/test/sanbashi.test.js index 02f6f6f..36ba5d6 100644 --- a/test/sanbashi.test.js +++ b/test/sanbashi.test.js @@ -22,6 +22,20 @@ describe('Sanbashi', () => { expect(results).to.have.members([`${searchpath}/Dockerfile`]) }) }) + describe('.filterByProcessType', () => { + it('returns an array of jobs only of the type requested', () => { + const dockerfiles = [ + Path.join('.', 'Nested', 'Dockerfile.worker'), + Path.join('.', 'Dockerfile.web'), + Path.join('.', 'Nested', 'Dockerfile') + ] + const resourceRoot = 'rootfulroot' + const jobs = Sanbashi.getJobs(resourceRoot, dockerfiles) + const filteredJobs = Sanbashi.filterByProcessType(jobs, ['web']) + expect(filteredJobs).to.have.property('web') + expect(filteredJobs.web[0].name).to.equal('web') + }) + }) describe('.getJobs', () => { it('returns objects representing jobs per Dockerfile', () => { const dockerfiles = [ @@ -29,23 +43,11 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile.web') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) + const results = Sanbashi.getJobs(resourceRoot, dockerfiles) expect(results.web).to.have.property('length', 2) expect(results.web[0]).to.have.property('depth', 1, 'dockerfile', './Dockerfile.web', 'postfix', 1) expect(results.web[1]).to.have.property('depth', 2, 'dockerfile', './Nested/Dockerfile.web', 'postfix', 1) }) - it('filters out by process type', () => { - const dockerfiles = [ - Path.join('.', 'Dockerfile.web'), - Path.join('.', 'Nested', 'Dockerfile.worker'), - Path.join('.', 'Dockerfile') - ] - const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, ['web'], dockerfiles) - expect(results.web).to.have.property('length', 1) - expect(results.web[0]).to.have.property('name', 'web') - expect(results).to.not.have.property('worker') - }) it('sorts dockerfiles by directory depth, then proc type', () => { const dockerfiles = [ Path.join('.', 'Nested', 'Dockerfile.worker'), @@ -53,7 +55,7 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, ['web', 'standard', 'worker'], dockerfiles) + const results = Sanbashi.getJobs(resourceRoot, dockerfiles) expect(results.web).to.have.property('length', 1) expect(results.web[0]).to.have.property('dockerfile', 'Dockerfile.web') expect(results.standard[0]).to.have.property('dockerfile', 'Nested/Dockerfile') @@ -66,7 +68,7 @@ describe('Sanbashi', () => { Path.join('.', 'Nested', 'Dockerfile') ] const resourceRoot = 'rootfulroot' - const results = Sanbashi.getJobs(resourceRoot, ['web', 'worker', 'standard'], dockerfiles) + const results = Sanbashi.getJobs(resourceRoot, dockerfiles) expect(results).to.have.keys('worker', 'web', 'standard') expect(results['worker'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Nested', 'Dockerfile.worker')]) expect(results['web'].map(j => j.dockerfile)).to.have.members([Path.join('.', 'Dockerfile.web')]) @@ -76,7 +78,7 @@ describe('Sanbashi', () => { describe('.chooseJobs', () => { it('returns the entry when only one exists', async () => { const dockerfiles = [Path.join('.', 'Nested', 'Dockerfile.web')] - const jobs = Sanbashi.getJobs('rootfulroot', ['web'], dockerfiles) + const jobs = Sanbashi.getJobs('rootfulroot', dockerfiles) let chosenJob = await Sanbashi.chooseJobs(jobs) expect(chosenJob[0]).to.have.property('dockerfile', dockerfiles[0]) expect(chosenJob).to.have.property('length', 1) From 7377b6c20a57473d7729a852bb7e3188e02ba887 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Mon, 12 Jun 2017 15:18:09 -0500 Subject: [PATCH 19/24] fix recursive regression --- commands/push.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commands/push.js b/commands/push.js index 3a11d30..ded9ed8 100644 --- a/commands/push.js +++ b/commands/push.js @@ -49,7 +49,9 @@ let push = async function (context, heroku) { let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, dockerfiles) let jobs if(recurse){ - possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args) + if(context.args.length){ + possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args) + } jobs = await Sanbashi.chooseJobs(possibleJobs) }else{ possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0])}) From cbcf60e90bcc4da95c2aa6d3605f5e2ff0b466fb Mon Sep 17 00:00:00 2001 From: karatecowboy Date: Wed, 14 Jun 2017 21:59:43 -0500 Subject: [PATCH 20/24] add handling for directories w/o dockerfiles --- commands/push.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commands/push.js b/commands/push.js index ded9ed8..0ef029d 100644 --- a/commands/push.js +++ b/commands/push.js @@ -47,13 +47,13 @@ let push = async function (context, heroku) { let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse) let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, dockerfiles) - let jobs + let jobs = [] if(recurse){ if(context.args.length){ possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args) } jobs = await Sanbashi.chooseJobs(possibleJobs) - }else{ + }else if(possibleJobs.standard){ possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0])}) jobs = possibleJobs.standard || [] } From f18dae3aa534875ab1489fc3069ed0cf88603fe8 Mon Sep 17 00:00:00 2001 From: jbyrum Date: Mon, 19 Jun 2017 09:57:02 -0700 Subject: [PATCH 21/24] Made text updates to push --- commands/push.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/commands/push.js b/commands/push.js index 0ef029d..ad320fa 100644 --- a/commands/push.js +++ b/commands/push.js @@ -3,9 +3,9 @@ const Sanbashi = require('../lib/sanbashi') let usage = ` ${cli.color.bold.underline.magenta('Usage:')} - ${ cli.color.cmd('heroku container:push web')} # Pushes Dockerfile in current directory to web process type - ${ cli.color.cmd('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker found in current & subdirectories - ${ cli.color.cmd('heroku container:push --recursive')} # Pushes Dockerfile.* found in current & subdirectories` + ${ cli.color.cmd('heroku container:push web')} # Pushes Dockerfile to web process type + ${ cli.color.cmd('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker + ${ cli.color.cmd('heroku container:push --recursive')} # Pushes Dockerfile.*` module.exports = function (topic) { return { @@ -25,7 +25,8 @@ module.exports = function (topic) { { name: 'recursive', char: 'R', - hasValue: false + hasValue: false, + description: 'pushes Dockerfile. found in current and subdirectories' } ], run: cli.command(push) From df8ce5fbd533c0995d5850bd3e7b69cfd58ec2c0 Mon Sep 17 00:00:00 2001 From: jbyrum Date: Mon, 19 Jun 2017 11:04:51 -0700 Subject: [PATCH 22/24] logout/in command fix --- commands/logout.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/logout.js b/commands/logout.js index 15519b9..79e9de4 100644 --- a/commands/logout.js +++ b/commands/logout.js @@ -7,7 +7,7 @@ module.exports = function (topic) { topic: topic, command: 'logout', flags: [{name: 'verbose', char: 'v', hasValue: false}], - description: 'logs out from the Heroku Container Registry', + description: 'logout from the Heroku Container Registry', needsApp: false, needsAuth: false, run: cli.command(logout) From d744280272dd3634845821738a659158c2dfd558 Mon Sep 17 00:00:00 2001 From: jbyrum Date: Mon, 19 Jun 2017 11:05:40 -0700 Subject: [PATCH 23/24] login text change --- commands/login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/login.js b/commands/login.js index a879705..4ab12e9 100644 --- a/commands/login.js +++ b/commands/login.js @@ -7,7 +7,7 @@ module.exports = function (topic) { topic: topic, command: 'login', flags: [{name: 'verbose', char: 'v', hasValue: false}], - description: 'logs in to the Heroku Container Registry', + description: 'login to the Heroku Container Registry', help: `Usage: heroku container:login`, needsApp: false, From ec5440142b633c5b83bfc48db4d3cd5eedeae680 Mon Sep 17 00:00:00 2001 From: Matthew Origer Date: Fri, 30 Jun 2017 14:44:52 -0500 Subject: [PATCH 24/24] consolidate spawing methods into helper the same code was repeated in several places to spawn docker commands. Consolidated this into a helper method --- commands/login.js | 23 ++++++++--------------- commands/logout.js | 19 ++++++------------- commands/push.js | 14 +++++++------- index.js | 3 ++- lib/sanbashi.js | 34 ++++++++++++---------------------- yarn.lock | 40 +++++++++++++++++++++++++--------------- 6 files changed, 60 insertions(+), 73 deletions(-) diff --git a/commands/login.js b/commands/login.js index 4ab12e9..e223882 100644 --- a/commands/login.js +++ b/commands/login.js @@ -1,5 +1,4 @@ const cli = require('heroku-cli-util') -const child = require('child_process') const log = require('../lib/log') module.exports = function (topic) { @@ -32,18 +31,12 @@ async function login (context, heroku) { } function dockerLogin (registry, password, verbose) { - return new Promise((resolve, reject) => { - let args = [ - 'login', - '--username=_', - `--password=${ password }`, - registry - ] - log(verbose, args) - child.spawn('docker', args, {stdio: 'inherit'}) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code) - else resolve() - }) - }) + let args = [ + 'login', + '--username=_', + `--password=${ password }`, + registry + ] + log(verbose, args) + return Sanbashi.cmd('docker', args) } diff --git a/commands/logout.js b/commands/logout.js index 79e9de4..3090788 100644 --- a/commands/logout.js +++ b/commands/logout.js @@ -1,5 +1,4 @@ const cli = require('heroku-cli-util') -const child = require('child_process') const log = require('../lib/log') module.exports = function (topic) { @@ -27,16 +26,10 @@ async function logout (context, heroku) { } function dockerLogout (registry, verbose) { - return new Promise((resolve, reject) => { - let args = [ - 'logout', - registry - ] - log(verbose, args) - child.spawn('docker', args, {stdio: 'inherit'}) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code) - else resolve() - }) - }) + let args = [ + 'logout', + registry + ] + log(verbose, args) + return Sanbashi.cmd('docker', args) } diff --git a/commands/push.js b/commands/push.js index ad320fa..f96716b 100644 --- a/commands/push.js +++ b/commands/push.js @@ -49,12 +49,12 @@ let push = async function (context, heroku) { let possibleJobs = Sanbashi.getJobs(`${ registry }/${ context.app }`, dockerfiles) let jobs = [] - if(recurse){ - if(context.args.length){ + if (recurse) { + if (context.args.length) { possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args) } jobs = await Sanbashi.chooseJobs(possibleJobs) - }else if(possibleJobs.standard){ + } else if (possibleJobs.standard) { possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0])}) jobs = possibleJobs.standard || [] } @@ -64,9 +64,9 @@ let push = async function (context, heroku) { } try { for (let job of jobs) { - if(job.name === 'standard'){ + if (job.name === 'standard') { cli.styledHeader(`Building for ${context.args} (${job.dockerfile })`) - }else{ + } else { cli.styledHeader(`Building ${job.name} (${job.dockerfile})`) } await Sanbashi.buildImage(job.dockerfile, job.resource, context.flags.verbose) @@ -80,9 +80,9 @@ let push = async function (context, heroku) { try { for (let job of jobs) { - if(job.name === 'standard'){ + if (job.name === 'standard') { cli.styledHeader(`Pushing for ${context.args} (${job.dockerfile })`) - }else{ + } else { cli.styledHeader(`Pushing ${job.name} (${job.dockerfile })`) } await Sanbashi.pushImage(job.resource, context.flags.verbose) diff --git a/index.js b/index.js index 51a7fa2..78ce577 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,8 @@ var pkg = require('./package.json') module.exports = { topic: { description: 'Use containers to build and deploy Heroku apps', - name: 'container' + name: 'container', + help: pkg.description }, commands: [ require('./commands/index')(pkg), diff --git a/lib/sanbashi.js b/lib/sanbashi.js index a743782..55a1a7e 100644 --- a/lib/sanbashi.js +++ b/lib/sanbashi.js @@ -71,7 +71,7 @@ Sanbashi.chooseJobs = async function (jobs) { return chosenJobs } -Sanbashi.filterByProcessType = function(jobs, procs){ +Sanbashi.filterByProcessType = function (jobs, procs) { let filteredJobs = {} procs.forEach((processType) => { filteredJobs[processType] = jobs[processType] @@ -79,30 +79,22 @@ Sanbashi.filterByProcessType = function(jobs, procs){ return filteredJobs } - Sanbashi.buildImage = function (dockerfile, resource, verbose) { - return new Promise((resolve, reject) => { - let cwd = Path.dirname(dockerfile) - let args = ['build', '-f', dockerfile, '-t', resource, cwd] - log(verbose, args) - Child.spawn('docker', args, { - stdio: 'inherit' - }) - .on('exit', (code, signal) => { - if (signal || code) reject(signal || code) - else resolve() - }) - }) + let cwd = Path.dirname(dockerfile) + let args = ['build', '-f', dockerfile, '-t', resource, cwd] + log(verbose, args) + return Sanbashi.cmd('docker', args) } Sanbashi.pushImage = function (resource, verbose) { - console.dir(resource, { colors:true, depth: null }) + let args = ['push', resource] + log(verbose, args) + return Sanbashi.cmd('docker', args) +} + +Sanbashi.cmd = function (cmd, args) { return new Promise((resolve, reject) => { - let args = ['push', resource] - log(verbose, args) - Child.spawn('docker', args, { - stdio: 'inherit' - }) + Child.spawn(cmd, args, {stdio: 'inherit'}) .on('exit', (code, signal) => { if (signal || code) reject(signal || code) else resolve() @@ -110,6 +102,4 @@ Sanbashi.pushImage = function (resource, verbose) { }) } - - module.exports = Sanbashi diff --git a/yarn.lock b/yarn.lock index 4453e92..f0cb5c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,6 +14,10 @@ ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -49,9 +53,9 @@ aws-sign2@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63" -balanced-match@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" bl@~0.9.0: version "0.9.5" @@ -66,10 +70,10 @@ boom@2.x.x: hoek "2.x.x" brace-expansion@^1.0.0, brace-expansion@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" dependencies: - balanced-match "^0.4.1" + balanced-match "^1.0.0" concat-map "0.0.1" buffer-equal@0.0.1: @@ -250,11 +254,11 @@ duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" -escape-string-regexp@1.0.2: +escape-string-regexp@1.0.2, escape-string-regexp@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -450,8 +454,8 @@ http-signature@~0.10.0: ctype "0.5.3" iconv-lite@^0.4.17: - version "0.4.17" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" + version "0.4.18" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" inflight@^1.0.4: version "1.0.6" @@ -853,8 +857,8 @@ rx@^4.1.0: resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" safe-buffer@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223" + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" samsam@1.x, samsam@^1.1.3: version "1.2.1" @@ -888,11 +892,11 @@ sntp@1.x.x: hoek "2.x.x" string-width@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + version "2.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.0.tgz#030664561fc146c9423ec7d978fe2457437fe6d0" dependencies: is-fullwidth-code-point "^2.0.0" - strip-ansi "^3.0.0" + strip-ansi "^4.0.0" string_decoder@~0.10.x: version "0.10.31" @@ -908,6 +912,12 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + superagent@0.21.0: version "0.21.0" resolved "https://registry.yarnpkg.com/superagent/-/superagent-0.21.0.tgz#fb15027984751ee7152200e6cd21cd6e19a5de87"