Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #6 from heroku/multiple-dockerfiles
Browse files Browse the repository at this point in the history
Multiple dockerfiles
  • Loading branch information
KarateCowboy authored Jul 5, 2017
2 parents eb8e2ad + ec54401 commit 36cb431
Show file tree
Hide file tree
Showing 13 changed files with 605 additions and 330 deletions.
9 changes: 4 additions & 5 deletions commands/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
module.exports = function index(pkg) {
module.exports = function index (pkg) {
return {
topic: pkg.topic,
description: pkg.description,
help: pkg.description,
run: showVersion
};
}

function showVersion(context) {
console.log(pkg.version);
function showVersion (context) {
console.log(pkg.version)
}
}
61 changes: 27 additions & 34 deletions commands/login.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,42 @@
'use strict';
const cli = require('heroku-cli-util')
const log = require('../lib/log')

const cli = require('heroku-cli-util');
const co = require('co');
const child = require('child_process');

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: 'login to the Heroku Container 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.error(`Error: docker login exited with ${ err }`)
cli.hush(err.stack || err)
cli.exit(1)
}
}

function dockerLogin(registry, password, verbose) {
return new Promise((resolve, reject) => {
let args = [
'login',
'--username=_',
`--password=${ password }`,
registry
];
if (verbose) {
console.log(['> docker'].concat(args).join(' '));
}
child.spawn('docker', args, { stdio: 'inherit' })
.on('exit', (code, signal) => {
if (signal || code) reject(signal || code);
else resolve();
});
});
function dockerLogin (registry, password, verbose) {
let args = [
'login',
'--username=_',
`--password=${ password }`,
registry
]
log(verbose, args)
return Sanbashi.cmd('docker', args)
}
51 changes: 20 additions & 31 deletions commands/logout.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,35 @@
'use strict';
const cli = require('heroku-cli-util')
const log = require('../lib/log')

const cli = require('heroku-cli-util');
const co = require('co');
const child = require('child_process');

module.exports = function(topic) {
module.exports = function (topic) {
return {
topic: topic,
command: 'logout',
flags: [{ name: 'verbose', char: 'v', hasValue: false }],
description: 'Logs out from the Heroku Docker registry',
flags: [{name: 'verbose', char: 'v', hasValue: false}],
description: 'logout from the Heroku Container Registry',
needsApp: false,
needsAuth: false,
run: cli.command(co.wrap(logout))
};
};
run: cli.command(logout)
}
}

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 = yield 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) {
return new Promise((resolve, reject) => {
let args = [
'logout',
registry
];
if (verbose) {
console.log(['> docker'].concat(args).join(' '));
}
child.spawn('docker', args, { stdio: 'inherit' })
.on('exit', (code, signal) => {
if (signal || code) reject(signal || code);
else resolve();
});
});
function dockerLogout (registry, verbose) {
let args = [
'logout',
registry
]
log(verbose, args)
return Sanbashi.cmd('docker', args)
}
135 changes: 77 additions & 58 deletions commands/push.js
Original file line number Diff line number Diff line change
@@ -1,77 +1,96 @@
'use strict';
const cli = require('heroku-cli-util')
const Sanbashi = require('../lib/sanbashi')

const cli = require('heroku-cli-util');
const co = require('co');
const child = require('child_process');
let usage = `
${cli.color.bold.underline.magenta('Usage:')}
${ 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) {
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,
args: [{ name: 'process', optional: true }],
flags: [{ name: 'verbose', char: 'v', hasValue: false }],
run: cli.command(co.wrap(push))
};
};
variableArgs: true,
help: usage,
flags: [
{
name: 'verbose',
char: 'v',
hasValue: false
},
{
name: 'recursive',
char: 'R',
hasValue: false,
description: 'pushes Dockerfile.<process> found in current and subdirectories'
}
],
run: cli.command(push)
}
}

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 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} `)
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 }`, dockerfiles)
let jobs = []
if (recurse) {
if (context.args.length) {
possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args)
}
jobs = await Sanbashi.chooseJobs(possibleJobs)
} else if (possibleJobs.standard) {
possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0])})
jobs = possibleJobs.standard || []
}
if (!jobs.length) {
cli.warn('No images to push')
process.exit(1)
}
try {
let build = yield buildImage(resource, process.cwd(), context.flags.verbose);
for (let job of jobs) {
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)
}
}
catch (err) {
cli.error(`Error: docker build exited with ${ err }`);
process.exit(1);
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);
for (let job of jobs) {
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)
}
}
catch (err) {
cli.error(`Error: docker push exited with ${ err }`);
process.exit(1);
cli.error(`Error: docker push exited with ${ err }`)
cli.hush(err.stack || err)
process.exit(1)
}
}

function buildImage(resource, cwd, verbose) {
return new Promise((resolve, reject) => {
let args = [
'build',
'-t',
resource,
cwd
];
if (verbose) {
console.log(['> docker'].concat(args).join(' '));
}
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
];
if (verbose) {
console.log(['> docker'].concat(args).join(' '));
}
child.spawn('docker', args, { stdio: 'inherit' })
.on('exit', (code, signal) => {
if (signal || code) reject(signal || code);
else resolve();
});
});
}
9 changes: 7 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
var pkg = require('./package.json');
var pkg = require('./package.json')

module.exports = {
topic: {
description: 'Use containers to build and deploy Heroku apps',
name: 'container',
help: pkg.description
},
commands: [
require('./commands/index')(pkg),
require('./commands/login')(pkg.topic),
require('./commands/logout')(pkg.topic),
require('./commands/push')(pkg.topic)
]
};
}
4 changes: 4 additions & 0 deletions lib/log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = (visible, args) => {
if (!visible) return
console.log(`> docker ${ args.join(' ') }`)
}
Loading

0 comments on commit 36cb431

Please sign in to comment.