UNPKG

3.46 kBJavaScriptView Raw
1const cli = require('heroku-cli-util')
2const Sanbashi = require('../lib/sanbashi')
3
4let usage = `
5 ${cli.color.bold.underline.magenta('Usage:')}
6 ${cli.color.cmd('heroku container:push web')} # Pushes Dockerfile to web process type
7 ${cli.color.cmd('heroku container:push worker')} # Pushes Dockerfile to worker process type
8 ${cli.color.cmd('heroku container:push web worker --recursive')} # Pushes Dockerfile.web and Dockerfile.worker
9 ${cli.color.cmd('heroku container:push --recursive')} # Pushes Dockerfile.*
10 ${cli.color.cmd('heroku container:push web --arg ENV=live,HTTPS=on')} # Build-time variables`
11
12module.exports = function (topic) {
13 return {
14 topic: topic,
15 command: 'push',
16 description: 'builds, then pushes Docker images to deploy your Heroku app',
17 needsApp: true,
18 needsAuth: true,
19 variableArgs: true,
20 help: usage,
21 flags: [
22 {
23 name: 'verbose',
24 char: 'v',
25 hasValue: false
26 },
27 {
28 name: 'recursive',
29 char: 'R',
30 hasValue: false,
31 description: 'pushes Dockerfile.<process> found in current and subdirectories'
32 },
33 {
34 name: 'arg',
35 hasValue: true,
36 description: 'set build-time variables'
37 }
38 ],
39 run: cli.command(push)
40 }
41}
42
43let push = async function (context, heroku) {
44 const recurse = !!context.flags.recursive
45 if (context.args.length === 0 && !recurse) {
46 cli.error(`Error: Requires either --recursive or one or more process types\n ${usage} `, 1)
47 return
48 }
49 if (context.args.length > 1 && !recurse) {
50 cli.error(`Error: Requires exactly one target process type, or --recursive option\n ${usage} `, 1)
51 return
52 }
53 let herokuHost = process.env.HEROKU_HOST || 'heroku.com'
54 let registry = `registry.${herokuHost}`
55 let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse)
56
57 let possibleJobs = Sanbashi.getJobs(`${registry}/${context.app}`, dockerfiles)
58 let jobs = []
59 if (recurse) {
60 if (context.args.length) {
61 possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args)
62 }
63 jobs = await Sanbashi.chooseJobs(possibleJobs)
64 } else if (possibleJobs.standard) {
65 possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0]) })
66 jobs = possibleJobs.standard || []
67 }
68 if (!jobs.length) {
69 cli.error('No images to push', 1)
70 return
71 }
72
73 let flagsArg = context.flags.arg
74 let buildArg = (flagsArg !== undefined) ? flagsArg.split(',') : []
75 let verbose = context.flags.verbose || false
76
77 try {
78 for (let job of jobs) {
79 if (job.name === 'standard') {
80 cli.styledHeader(`Building ${context.args} (${job.dockerfile})`)
81 } else {
82 cli.styledHeader(`Building ${job.name} (${job.dockerfile})`)
83 }
84 await Sanbashi.buildImage(job.dockerfile, job.resource, verbose, buildArg)
85 }
86 } catch (err) {
87 cli.error(`Error: docker build exited with ${err}`, 1)
88 return
89 }
90
91 try {
92 for (let job of jobs) {
93 if (job.name === 'standard') {
94 cli.styledHeader(`Pushing ${context.args} (${job.dockerfile})`)
95 } else {
96 cli.styledHeader(`Pushing ${job.name} (${job.dockerfile})`)
97 }
98 await Sanbashi.pushImage(job.resource, verbose)
99 }
100 } catch (err) {
101 cli.error(`Error: docker push exited with ${err}`, 1)
102 return
103 }
104}