mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-19 13:47:52 +00:00
Merge pull request #498 from resin-io/prettify-build
Add cloud-builder builder output parity to build and deploy
This commit is contained in:
commit
65884c81a4
@ -43,6 +43,8 @@ module.exports = {
|
||||
}
|
||||
]),
|
||||
action: function(params, options, done) {
|
||||
return dockerUtils.runBuild(params, options, getBundleInfo).asCallback(done);
|
||||
var logging;
|
||||
logging = require('../utils/logging');
|
||||
return dockerUtils.runBuild(params, options, getBundleInfo, logging.getLogStreams()).asCallback(done);
|
||||
}
|
||||
};
|
||||
|
@ -37,12 +37,14 @@ parseInput = Promise.method(function(params, options) {
|
||||
return [appName, options.build, source, image];
|
||||
});
|
||||
|
||||
pushProgress = function(imageSize, request, timeout) {
|
||||
var progressReporter;
|
||||
pushProgress = function(imageSize, request, logStreams, timeout) {
|
||||
var ansiEscapes, logging, progressReporter;
|
||||
if (timeout == null) {
|
||||
timeout = 250;
|
||||
}
|
||||
process.stdout.write('Initialising...');
|
||||
logging = require('../utils/logging');
|
||||
ansiEscapes = require('ansi-escapes');
|
||||
logging.logInfo(logStreams, 'Initialising...');
|
||||
return progressReporter = setInterval(function() {
|
||||
var percent, sent;
|
||||
sent = request.req.connection._bytesDispatched;
|
||||
@ -51,12 +53,10 @@ pushProgress = function(imageSize, request, timeout) {
|
||||
clearInterval(progressReporter);
|
||||
percent = 100;
|
||||
}
|
||||
process.stdout.write(ansiEscapes.cursorUp(1));
|
||||
process.stdout.clearLine();
|
||||
process.stdout.cursorTo(0);
|
||||
process.stdout.write("Uploaded " + (percent.toFixed(1)) + "%");
|
||||
if (percent === 100) {
|
||||
return console.log();
|
||||
}
|
||||
return logging.logInfo(logStreams, "Uploaded " + (percent.toFixed(1)) + "%");
|
||||
}, timeout);
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@ getBundleInfo = function(options) {
|
||||
});
|
||||
};
|
||||
|
||||
performUpload = function(image, token, username, url, size, appName) {
|
||||
performUpload = function(image, token, username, url, size, appName, logStreams) {
|
||||
var post, request;
|
||||
request = require('request');
|
||||
url = url || process.env.RESINRC_RESIN_URL;
|
||||
@ -79,18 +79,18 @@ performUpload = function(image, token, username, url, size, appName) {
|
||||
},
|
||||
body: image
|
||||
});
|
||||
return uploadToPromise(post, size);
|
||||
return uploadToPromise(post, size, logStreams);
|
||||
};
|
||||
|
||||
uploadToPromise = function(request, size) {
|
||||
uploadToPromise = function(request, size, logStreams) {
|
||||
var logging;
|
||||
logging = require('../utils/logging');
|
||||
return new Promise(function(resolve, reject) {
|
||||
var handleMessage;
|
||||
handleMessage = function(data) {
|
||||
var obj;
|
||||
data = data.toString();
|
||||
if (process.env.DEBUG) {
|
||||
console.log("Received data: " + data);
|
||||
}
|
||||
logging.logDebug(logStreams, "Received data: " + data);
|
||||
obj = JSON.parse(data);
|
||||
if (obj.type != null) {
|
||||
switch (obj.type) {
|
||||
@ -99,7 +99,7 @@ uploadToPromise = function(request, size) {
|
||||
case 'success':
|
||||
return resolve(obj.image);
|
||||
case 'status':
|
||||
return console.log("Remote: " + obj.message);
|
||||
return logging.logInfo(logStreams, "Remote: " + obj.message);
|
||||
default:
|
||||
return reject(new Error("Received unexpected reply from remote: " + data));
|
||||
}
|
||||
@ -108,7 +108,7 @@ uploadToPromise = function(request, size) {
|
||||
}
|
||||
};
|
||||
request.on('error', reject).on('data', handleMessage);
|
||||
return pushProgress(size, request);
|
||||
return pushProgress(size, request, logStreams);
|
||||
});
|
||||
};
|
||||
|
||||
@ -131,11 +131,13 @@ module.exports = {
|
||||
}
|
||||
]),
|
||||
action: function(params, options, done) {
|
||||
var _, docker, resin, tmp, tmpNameAsync;
|
||||
var _, docker, logStreams, logging, resin, tmp, tmpNameAsync;
|
||||
_ = require('lodash');
|
||||
tmp = require('tmp');
|
||||
tmpNameAsync = Promise.promisify(tmp.tmpName);
|
||||
resin = require('resin-sdk-preconfigured');
|
||||
logging = require('../utils/logging');
|
||||
logStreams = logging.getLogStreams();
|
||||
tmp.setGracefulCleanup();
|
||||
docker = dockerUtils.getDocker(options);
|
||||
return parseInput(params, options).then(function(arg) {
|
||||
@ -150,18 +152,18 @@ module.exports = {
|
||||
});
|
||||
return Promise["try"](function() {
|
||||
if (build) {
|
||||
return dockerUtils.runBuild(params, options, getBundleInfo);
|
||||
return dockerUtils.runBuild(params, options, getBundleInfo, logStreams);
|
||||
} else {
|
||||
return imageName;
|
||||
}
|
||||
}).then(function(imageName) {
|
||||
return Promise.join(dockerUtils.bufferImage(docker, imageName, tmpPath), resin.auth.getToken(), resin.auth.whoami(), resin.settings.get('resinUrl'), dockerUtils.getImageSize(docker, imageName), params.appName, performUpload);
|
||||
return Promise.join(dockerUtils.bufferImage(docker, imageName, tmpPath), resin.auth.getToken(), resin.auth.whoami(), resin.settings.get('resinUrl'), dockerUtils.getImageSize(docker, imageName), params.appName, logStreams, performUpload);
|
||||
})["finally"](function() {
|
||||
return require('fs').unlink(tmpPath);
|
||||
});
|
||||
});
|
||||
}).then(function(imageName) {
|
||||
return console.log("Successfully deployed image: " + (formatImageName(imageName)));
|
||||
return logging.logSuccess(logStreams, "Successfully deployed image: " + (formatImageName(imageName)));
|
||||
}).asCallback(done);
|
||||
}
|
||||
};
|
||||
|
@ -98,11 +98,12 @@ exports.tarDirectory = tarDirectory = function(dir) {
|
||||
});
|
||||
};
|
||||
|
||||
exports.runBuild = function(params, options, getBundleInfo) {
|
||||
var Promise, dockerBuild, resolver;
|
||||
exports.runBuild = function(params, options, getBundleInfo, logStreams) {
|
||||
var Promise, dockerBuild, logging, resolver;
|
||||
Promise = require('bluebird');
|
||||
dockerBuild = require('resin-docker-build');
|
||||
resolver = require('resin-bundle-resolve');
|
||||
logging = require('../utils/logging');
|
||||
if (params.source == null) {
|
||||
params.source = '.';
|
||||
}
|
||||
@ -121,25 +122,23 @@ exports.runBuild = function(params, options, getBundleInfo) {
|
||||
getBundleInfo(options).then(function(info) {
|
||||
var arch, bundle, deviceType;
|
||||
if (info == null) {
|
||||
console.log('Warning: No architecture/device type or application information provided.\n Dockerfile/project pre-processing will not be performed.');
|
||||
logging.logWarn(logStreams, 'Warning: No architecture/device type or application information provided.\n Dockerfile/project pre-processing will not be performed.');
|
||||
return tarStream.pipe(stream);
|
||||
} else {
|
||||
arch = info[0], deviceType = info[1];
|
||||
bundle = new resolver.Bundle(tarStream, deviceType, arch);
|
||||
return resolver.resolveBundle(bundle, resolver.getDefaultResolvers()).then(function(resolved) {
|
||||
console.log("Building " + resolved.projectType + " project");
|
||||
logging.logInfo(logStreams, "Building " + resolved.projectType + " project");
|
||||
return resolved.tarStream.pipe(stream);
|
||||
});
|
||||
}
|
||||
})["catch"](reject);
|
||||
return stream.pipe(process.stdout);
|
||||
return stream.pipe(logStreams.build);
|
||||
}
|
||||
};
|
||||
connectOpts = generateConnectOpts(options);
|
||||
if (process.env.DEBUG != null) {
|
||||
console.log('Connecting with the following options:');
|
||||
console.log(JSON.stringify(connectOpts, null, ' '));
|
||||
}
|
||||
logging.logDebug(logStreams, 'Connecting with the following options:');
|
||||
logging.logDebug(logStreams, JSON.stringify(connectOpts, null, ' '));
|
||||
builder = new dockerBuild.Builder(connectOpts);
|
||||
opts = {};
|
||||
if (options.tag != null) {
|
||||
|
50
build/utils/logging.js
Normal file
50
build/utils/logging.js
Normal file
@ -0,0 +1,50 @@
|
||||
// Generated by CoffeeScript 1.12.5
|
||||
var eol;
|
||||
|
||||
eol = require('os').EOL;
|
||||
|
||||
exports.getLogStreams = function() {
|
||||
var StreamLogger, _, colors, logger, streams;
|
||||
StreamLogger = require('resin-stream-logger').StreamLogger;
|
||||
colors = require('colors');
|
||||
_ = require('lodash');
|
||||
logger = new StreamLogger();
|
||||
logger.addPrefix('build', colors.blue('[Build]'));
|
||||
logger.addPrefix('info', colors.cyan('[Info]'));
|
||||
logger.addPrefix('debug', colors.magenta('[Debug]'));
|
||||
logger.addPrefix('success', colors.green('[Success]'));
|
||||
logger.addPrefix('warn', colors.yellow('[Warn]'));
|
||||
streams = {
|
||||
build: logger.createLogStream('build'),
|
||||
info: logger.createLogStream('info'),
|
||||
debug: logger.createLogStream('debug'),
|
||||
success: logger.createLogStream('success'),
|
||||
warn: logger.createLogStream('warn')
|
||||
};
|
||||
_.mapKeys(streams, function(stream, key) {
|
||||
if (key !== 'debug') {
|
||||
return stream.pipe(process.stdout);
|
||||
} else {
|
||||
if (process.env.DEBUG != null) {
|
||||
return stream.pipe(process.stdout);
|
||||
}
|
||||
}
|
||||
});
|
||||
return streams;
|
||||
};
|
||||
|
||||
exports.logInfo = function(logStreams, msg) {
|
||||
return logStreams.info.write(msg + eol);
|
||||
};
|
||||
|
||||
exports.logDebug = function(logStreams, msg) {
|
||||
return logStreams.debug.write(msg + eol);
|
||||
};
|
||||
|
||||
exports.logSuccess = function(logStreams, msg) {
|
||||
return logStreams.success.write(msg + eol);
|
||||
};
|
||||
|
||||
exports.logWarn = function(logStreams, msg) {
|
||||
return logStreams.warn.write(msg + eol);
|
||||
};
|
@ -58,6 +58,7 @@ module.exports =
|
||||
},
|
||||
]
|
||||
action: (params, options, done) ->
|
||||
dockerUtils.runBuild(params, options, getBundleInfo)
|
||||
logging = require('../utils/logging')
|
||||
dockerUtils.runBuild(params, options, getBundleInfo, logging.getLogStreams())
|
||||
.asCallback(done)
|
||||
|
||||
|
@ -26,18 +26,21 @@ parseInput = Promise.method (params, options) ->
|
||||
|
||||
return [appName, options.build, source, image]
|
||||
|
||||
pushProgress = (imageSize, request, timeout = 250) ->
|
||||
process.stdout.write('Initialising...')
|
||||
pushProgress = (imageSize, request, logStreams, timeout = 250) ->
|
||||
logging = require('../utils/logging')
|
||||
ansiEscapes = require('ansi-escapes')
|
||||
|
||||
logging.logInfo(logStreams, 'Initialising...')
|
||||
progressReporter = setInterval ->
|
||||
sent = request.req.connection._bytesDispatched
|
||||
percent = (sent / imageSize) * 100
|
||||
if percent >= 100
|
||||
clearInterval(progressReporter)
|
||||
percent = 100
|
||||
process.stdout.write(ansiEscapes.cursorUp(1))
|
||||
process.stdout.clearLine()
|
||||
process.stdout.cursorTo(0)
|
||||
process.stdout.write("Uploaded #{percent.toFixed(1)}%")
|
||||
console.log() if percent == 100
|
||||
logging.logInfo(logStreams, "Uploaded #{percent.toFixed(1)}%")
|
||||
, timeout
|
||||
|
||||
getBundleInfo = (options) ->
|
||||
@ -47,7 +50,7 @@ getBundleInfo = (options) ->
|
||||
.then (app) ->
|
||||
[app.arch, app.device_type]
|
||||
|
||||
performUpload = (image, token, username, url, size, appName) ->
|
||||
performUpload = (image, token, username, url, size, appName, logStreams) ->
|
||||
request = require('request')
|
||||
url = url || process.env.RESINRC_RESIN_URL
|
||||
post = request.post
|
||||
@ -56,22 +59,22 @@ performUpload = (image, token, username, url, size, appName) ->
|
||||
bearer: token
|
||||
body: image
|
||||
|
||||
uploadToPromise(post, size)
|
||||
uploadToPromise(post, size, logStreams)
|
||||
|
||||
uploadToPromise = (request, size) ->
|
||||
uploadToPromise = (request, size, logStreams) ->
|
||||
logging = require('../utils/logging')
|
||||
new Promise (resolve, reject) ->
|
||||
|
||||
handleMessage = (data) ->
|
||||
data = data.toString()
|
||||
if process.env.DEBUG
|
||||
console.log("Received data: #{data}")
|
||||
logging.logDebug(logStreams, "Received data: #{data}")
|
||||
|
||||
obj = JSON.parse(data)
|
||||
if obj.type?
|
||||
switch obj.type
|
||||
when 'error' then reject(new Error("Remote error: #{obj.error}"))
|
||||
when 'success' then resolve(obj.image)
|
||||
when 'status' then console.log("Remote: #{obj.message}")
|
||||
when 'status' then logging.logInfo(logStreams, "Remote: #{obj.message}")
|
||||
else reject(new Error("Received unexpected reply from remote: #{data}"))
|
||||
else
|
||||
reject(new Error("Received unexpected reply from remote: #{data}"))
|
||||
@ -81,7 +84,7 @@ uploadToPromise = (request, size) ->
|
||||
.on('data', handleMessage)
|
||||
|
||||
# Set up upload reporting
|
||||
pushProgress(size, request)
|
||||
pushProgress(size, request, logStreams)
|
||||
|
||||
|
||||
module.exports =
|
||||
@ -120,6 +123,10 @@ module.exports =
|
||||
tmpNameAsync = Promise.promisify(tmp.tmpName)
|
||||
resin = require('resin-sdk-preconfigured')
|
||||
|
||||
logging = require('../utils/logging')
|
||||
|
||||
logStreams = logging.getLogStreams()
|
||||
|
||||
# Ensure the tmp files gets deleted
|
||||
tmp.setGracefulCleanup()
|
||||
|
||||
@ -136,7 +143,7 @@ module.exports =
|
||||
|
||||
Promise.try ->
|
||||
if build
|
||||
dockerUtils.runBuild(params, options, getBundleInfo)
|
||||
dockerUtils.runBuild(params, options, getBundleInfo, logStreams)
|
||||
else
|
||||
imageName
|
||||
.then (imageName) ->
|
||||
@ -147,10 +154,11 @@ module.exports =
|
||||
resin.settings.get('resinUrl')
|
||||
dockerUtils.getImageSize(docker, imageName)
|
||||
params.appName
|
||||
logStreams
|
||||
performUpload
|
||||
)
|
||||
.finally ->
|
||||
require('fs').unlink(tmpPath)
|
||||
.then (imageName) ->
|
||||
console.log("Successfully deployed image: #{formatImageName(imageName)}")
|
||||
logging.logSuccess(logStreams, "Successfully deployed image: #{formatImageName(imageName)}")
|
||||
.asCallback(done)
|
||||
|
@ -112,10 +112,12 @@ exports.tarDirectory = tarDirectory = (dir) ->
|
||||
|
||||
# Pass in the command line parameters and options and also
|
||||
# a function which will return the information about the bundle
|
||||
exports.runBuild = (params, options, getBundleInfo) ->
|
||||
exports.runBuild = (params, options, getBundleInfo, logStreams) ->
|
||||
|
||||
Promise = require('bluebird')
|
||||
dockerBuild = require('resin-docker-build')
|
||||
resolver = require('resin-bundle-resolve')
|
||||
logging = require('../utils/logging')
|
||||
|
||||
# The default build context is the current directory
|
||||
params.source ?= '.'
|
||||
@ -134,7 +136,7 @@ exports.runBuild = (params, options, getBundleInfo) ->
|
||||
getBundleInfo(options)
|
||||
.then (info) ->
|
||||
if !info?
|
||||
console.log '''
|
||||
logging.logWarn logStreams, '''
|
||||
Warning: No architecture/device type or application information provided.
|
||||
Dockerfile/project pre-processing will not be performed.
|
||||
'''
|
||||
@ -145,21 +147,19 @@ exports.runBuild = (params, options, getBundleInfo) ->
|
||||
bundle = new resolver.Bundle(tarStream, deviceType, arch)
|
||||
resolver.resolveBundle(bundle, resolver.getDefaultResolvers())
|
||||
.then (resolved) ->
|
||||
console.log("Building #{resolved.projectType} project")
|
||||
logging.logInfo(logStreams, "Building #{resolved.projectType} project")
|
||||
# Send the resolved tar stream to the docker daemon
|
||||
resolved.tarStream.pipe(stream)
|
||||
.catch(reject)
|
||||
|
||||
# And print the output
|
||||
stream.pipe(process.stdout)
|
||||
stream.pipe(logStreams.build)
|
||||
|
||||
# Create a builder
|
||||
connectOpts = generateConnectOpts(options)
|
||||
|
||||
# Allow degugging output, hidden behind an env var
|
||||
if process.env.DEBUG?
|
||||
console.log('Connecting with the following options:')
|
||||
console.log(JSON.stringify(connectOpts, null, ' '))
|
||||
logging.logDebug(logStreams, 'Connecting with the following options:')
|
||||
logging.logDebug(logStreams, JSON.stringify(connectOpts, null, ' '))
|
||||
|
||||
builder = new dockerBuild.Builder(connectOpts)
|
||||
opts = {}
|
||||
|
40
lib/utils/logging.coffee
Normal file
40
lib/utils/logging.coffee
Normal file
@ -0,0 +1,40 @@
|
||||
eol = require('os').EOL
|
||||
|
||||
exports.getLogStreams = ->
|
||||
{ StreamLogger } = require('resin-stream-logger')
|
||||
colors = require('colors')
|
||||
_ = require('lodash')
|
||||
|
||||
logger = new StreamLogger()
|
||||
logger.addPrefix('build', colors.blue('[Build]'))
|
||||
logger.addPrefix('info', colors.cyan('[Info]'))
|
||||
logger.addPrefix('debug', colors.magenta('[Debug]'))
|
||||
logger.addPrefix('success', colors.green('[Success]'))
|
||||
logger.addPrefix('warn', colors.yellow('[Warn]'))
|
||||
|
||||
streams =
|
||||
build: logger.createLogStream('build'),
|
||||
info: logger.createLogStream('info'),
|
||||
debug: logger.createLogStream('debug'),
|
||||
success: logger.createLogStream('success'),
|
||||
warn: logger.createLogStream('warn')
|
||||
|
||||
_.mapKeys streams, (stream, key) ->
|
||||
if key isnt 'debug'
|
||||
stream.pipe(process.stdout)
|
||||
else
|
||||
stream.pipe(process.stdout) if process.env.DEBUG?
|
||||
|
||||
streams
|
||||
|
||||
exports.logInfo = (logStreams, msg) ->
|
||||
logStreams.info.write(msg + eol)
|
||||
|
||||
exports.logDebug = (logStreams, msg) ->
|
||||
logStreams.debug.write(msg + eol)
|
||||
|
||||
exports.logSuccess = (logStreams, msg) ->
|
||||
logStreams.success.write(msg + eol)
|
||||
|
||||
exports.logWarn = (logStreams, msg) ->
|
||||
logStreams.warn.write(msg + eol)
|
@ -33,6 +33,7 @@
|
||||
"gulp-shell": "^0.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^2.0.0",
|
||||
"any-promise": "^1.3.0",
|
||||
"babel-preset-es2015": "^6.16.0",
|
||||
"babel-register": "^6.16.3",
|
||||
@ -58,11 +59,10 @@
|
||||
"president": "^2.0.1",
|
||||
"prettyjson": "^1.1.3",
|
||||
"raven": "^1.2.0",
|
||||
"resin-cli-auth": "^1.1.3",
|
||||
"reconfix": "^0.0.3",
|
||||
"request": "^2.81.0",
|
||||
"resin-bundle-resolve": "^0.0.2",
|
||||
"resin-cli-auth": "^1.0.0",
|
||||
"resin-cli-auth": "^1.1.3",
|
||||
"resin-cli-errors": "^1.2.0",
|
||||
"resin-cli-form": "^1.4.1",
|
||||
"resin-cli-visuals": "^1.3.0",
|
||||
@ -73,6 +73,7 @@
|
||||
"resin-image-fs": "^2.1.2",
|
||||
"resin-image-manager": "^4.1.1",
|
||||
"resin-sdk-preconfigured": "^6.0.0",
|
||||
"resin-stream-logger": "^0.0.4",
|
||||
"resin-sync": "^7.0.0",
|
||||
"rimraf": "^2.4.3",
|
||||
"rindle": "^1.0.0",
|
||||
|
Loading…
Reference in New Issue
Block a user