UNPKG

3.5 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 await heroku.get(`/apps/${context.app}`)
54
55 let herokuHost = process.env.HEROKU_HOST || 'heroku.com'
56 let registry = `registry.${herokuHost}`
57 let dockerfiles = Sanbashi.getDockerfiles(process.cwd(), recurse)
58
59 let possibleJobs = Sanbashi.getJobs(`${registry}/${context.app}`, dockerfiles)
60 let jobs = []
61 if (recurse) {
62 if (context.args.length) {
63 possibleJobs = Sanbashi.filterByProcessType(possibleJobs, context.args)
64 }
65 jobs = await Sanbashi.chooseJobs(possibleJobs)
66 } else if (possibleJobs.standard) {
67 possibleJobs.standard.forEach((pj) => { pj.resource = pj.resource.replace(/standard$/, context.args[0]) })
68 jobs = possibleJobs.standard || []
69 }
70 if (!jobs.length) {
71 cli.error('No images to push', 1)
72 return
73 }
74
75 let flagsArg = context.flags.arg
76 let buildArg = (flagsArg !== undefined) ? flagsArg.split(',') : []
77 let verbose = context.flags.verbose || false
78
79 try {
80 for (let job of jobs) {
81 if (job.name === 'standard') {
82 cli.styledHeader(`Building ${context.args} (${job.dockerfile})`)
83 } else {
84 cli.styledHeader(`Building ${job.name} (${job.dockerfile})`)
85 }
86 await Sanbashi.buildImage(job.dockerfile, job.resource, verbose, buildArg)
87 }
88 } catch (err) {
89 cli.error(`Error: docker build exited with ${err}`, 1)
90 return
91 }
92
93 try {
94 for (let job of jobs) {
95 if (job.name === 'standard') {
96 cli.styledHeader(`Pushing ${context.args} (${job.dockerfile})`)
97 } else {
98 cli.styledHeader(`Pushing ${job.name} (${job.dockerfile})`)
99 }
100 await Sanbashi.pushImage(job.resource, verbose)
101 }
102 } catch (err) {
103 cli.error(`Error: docker push exited with ${err}`, 1)
104 return
105 }
106}