UNPKG

2.73 kBJavaScriptView Raw
1var child = require('child_process');
2var path = require('path');
3var os = require('os');
4var fs = require('fs');
5var Heroku = require('heroku-client');
6var request = require('request');
7var state = require('../lib/state');
8var docker = require('../lib/docker');
9var agent = require('superagent');
10
11process.on('uncaughtException', function(err) {
12 console.log('err:', err.stack);
13});
14
15module.exports = function(topic) {
16 return {
17 topic: topic,
18 command: 'release',
19 description: 'creates a slug tarball from the built image and releases it to your Heroku app',
20 help: `help text for ${topic}:release`,
21 needsApp: true,
22 needsAuth: true,
23 run: release
24 };
25};
26
27function release(context) {
28 var heroku = new Heroku({ token: context.auth.password });
29 var app = heroku.apps(context.app);
30
31 app.info()
32 .then(createLocalSlug)
33 .then(createRemoteSlug)
34 .then(uploadSlug)
35 .then(releaseSlug)
36 .catch(onErr);
37
38 function createLocalSlug() {
39 console.log('creating local slug...');
40 try {
41 var slugPath = os.tmpdir();
42 var imageId = state.get(context.cwd).startImageId;
43 var containerId = child.execSync(`docker run -d ${imageId} tar cfvz /tmp/slug.tgz -C / --exclude=.git --exclude=.heroku ./app`, {
44 encoding: 'utf8'
45 }).trim();
46 child.execSync(`docker wait ${containerId}`);
47 child.execSync(`docker cp ${containerId}:/tmp/slug.tgz ${slugPath}`);
48 child.execSync(`docker rm -f ${containerId}`);
49 return Promise.resolve(path.join(slugPath, 'slug.tgz'));
50 }
51 catch (e) {
52 return Promise.reject(e);
53 }
54 }
55
56 function createRemoteSlug(slugPath) {
57 console.log('local slug path:', slugPath);
58 console.log('creating remote slug...');
59 var slugInfo = app.slugs().create({
60 process_types: {
61 web: 'npm start'
62 }
63 });
64 return Promise.all([slugPath, slugInfo])
65 }
66
67 function uploadSlug(slug) {
68 console.log('uploading slug...');
69 var slugPath = slug[0];
70 var slugInfo = slug[1];
71 var size = fs.statSync(slugPath).size;
72
73 return new Promise(function(resolve, reject) {
74 var outStream = request({
75 method: 'PUT',
76 url: slugInfo.blob.url,
77 headers: {
78 'content-type': '',
79 'content-length': size
80 }
81 });
82
83 fs.createReadStream(slugPath)
84 .on('error', reject)
85 .pipe(outStream)
86 .on('error', reject)
87 .on('response', resolve.bind(this, slugInfo.id));
88 });
89 }
90
91 function releaseSlug(id) {
92 console.log('releasing slug...');
93 return app.releases().create({
94 slug: id
95 });
96 }
97
98 function onErr(err) {
99 console.log('caught err:', err.stack);
100 console.log('body:', err.body);
101 }
102}