Merge pull request #557 from resin-io/539-fix-clearLine

Fix issue when using resin deploy with non-standard stdin
This commit is contained in:
Tim Perry 2017-06-28 20:30:48 +02:00 committed by GitHub
commit e660c6ae90
10 changed files with 195 additions and 169 deletions

View File

@ -7,6 +7,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix issue where emulated builds broke Docker `ARG` commands - Fix issue where emulated builds broke Docker `ARG` commands
### Added
- Fix issue when using resin deploy with non-standard stdin (e.g. git bash on windows)
## [6.0.0] - 2017-06-26 ## [6.0.0] - 2017-06-26
### Added ### Added

View File

@ -43,8 +43,8 @@ module.exports = {
} }
]), ]),
action: function(params, options, done) { action: function(params, options, done) {
var logging; var Logger;
logging = require('../utils/logging'); Logger = require('../utils/logger');
return dockerUtils.runBuild(params, options, getBundleInfo, logging.getLogStreams()).asCallback(done); return dockerUtils.runBuild(params, options, getBundleInfo, new Logger()).asCallback(done);
} }
}; };

View File

@ -1,5 +1,5 @@
// Generated by CoffeeScript 1.12.6 // Generated by CoffeeScript 1.12.6
var Promise, dockerUtils, formatImageName, getBuilderLogPushEndpoint, getBuilderPushEndpoint, getBundleInfo, parseInput, performUpload, renderProgress, showPushProgress, updatePushProgress, uploadLogs, uploadToPromise; var Promise, dockerUtils, formatImageName, getBuilderLogPushEndpoint, getBuilderPushEndpoint, getBundleInfo, parseInput, performUpload, showPushProgress, uploadLogs, uploadToPromise;
Promise = require('bluebird'); Promise = require('bluebird');
@ -51,36 +51,14 @@ parseInput = Promise.method(function(params, options) {
return [appName, options.build, source, image]; return [appName, options.build, source, image];
}); });
renderProgress = function(percentage, stepCount) { showPushProgress = function(message) {
var _, bar, barCount, spaceCount; var progressBar, visuals;
if (stepCount == null) { visuals = require('resin-cli-visuals');
stepCount = 50; progressBar = new visuals.Progress(message);
} progressBar.update({
_ = require('lodash'); percentage: 0
percentage = Math.max(0, Math.min(percentage, 100)); });
barCount = Math.floor(stepCount * percentage / 100); return progressBar;
spaceCount = stepCount - barCount;
bar = "[" + (_.repeat('=', barCount)) + ">" + (_.repeat(' ', spaceCount)) + "]";
return bar + " " + (percentage.toFixed(1)) + "%";
};
showPushProgress = function(logStreams) {
var logging;
logging = require('../utils/logging');
return logging.logInfo(logStreams, renderProgress(0));
};
updatePushProgress = function(percentage, logStreams) {
var ansiEscapes, logging;
logging = require('../utils/logging');
ansiEscapes = require('ansi-escapes');
if (percentage >= 100) {
percentage = 100;
}
process.stdout.write(ansiEscapes.cursorUp(1));
process.stdout.clearLine();
process.stdout.cursorTo(0);
return logging.logInfo(logStreams, renderProgress(percentage));
}; };
getBundleInfo = function(options) { getBundleInfo = function(options) {
@ -91,19 +69,23 @@ getBundleInfo = function(options) {
}); });
}; };
performUpload = function(imageStream, token, username, url, appName, logStreams) { performUpload = function(imageStream, token, username, url, appName, logger) {
var progressStream, request, streamWithProgress, uploadRequest, zlib; var progressBar, progressMessage, progressStream, request, streamWithProgress, uploadRequest, zlib;
request = require('request'); request = require('request');
progressStream = require('progress-stream'); progressStream = require('progress-stream');
zlib = require('zlib'); zlib = require('zlib');
showPushProgress(logStreams); progressMessage = logger.formatMessage('info', 'Deploying').slice(0, -1);
progressBar = showPushProgress(progressMessage);
streamWithProgress = imageStream.pipe(progressStream({ streamWithProgress = imageStream.pipe(progressStream({
time: 500, time: 500,
length: imageStream.length length: imageStream.length
}, function(arg) { }, function(arg) {
var percentage; var eta, percentage;
percentage = arg.percentage; percentage = arg.percentage, eta = arg.eta;
return updatePushProgress(percentage, logStreams); return progressBar.update({
percentage: Math.min(percentage, 100),
eta: eta
});
})); }));
uploadRequest = request.post({ uploadRequest = request.post({
url: getBuilderPushEndpoint(url, username, appName), url: getBuilderPushEndpoint(url, username, appName),
@ -117,7 +99,7 @@ performUpload = function(imageStream, token, username, url, appName, logStreams)
level: 6 level: 6
})) }))
}); });
return uploadToPromise(uploadRequest, logStreams); return uploadToPromise(uploadRequest, logger);
}; };
uploadLogs = function(logs, token, url, buildId, username, appName) { uploadLogs = function(logs, token, url, buildId, username, appName) {
@ -133,20 +115,18 @@ uploadLogs = function(logs, token, url, buildId, username, appName) {
}); });
}; };
uploadToPromise = function(uploadRequest, logStreams) { uploadToPromise = function(uploadRequest, logger) {
var logging;
logging = require('../utils/logging');
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var handleMessage; var handleMessage;
handleMessage = function(data) { handleMessage = function(data) {
var e, obj; var e, obj;
data = data.toString(); data = data.toString();
logging.logDebug(logStreams, "Received data: " + data); logger.logDebug("Received data: " + data);
try { try {
obj = JSON.parse(data); obj = JSON.parse(data);
} catch (error) { } catch (error) {
e = error; e = error;
logging.logError(logStreams, 'Error parsing reply from remote side'); logger.logError('Error parsing reply from remote side');
reject(e); reject(e);
return; return;
} }
@ -157,7 +137,7 @@ uploadToPromise = function(uploadRequest, logStreams) {
case 'success': case 'success':
return resolve(obj); return resolve(obj);
case 'status': case 'status':
return logging.logInfo(logStreams, "Remote: " + obj.message); return logger.logInfo("Remote: " + obj.message);
default: default:
return reject(new Error("Received unexpected reply from remote: " + data)); return reject(new Error("Received unexpected reply from remote: " + data));
} }
@ -192,13 +172,13 @@ module.exports = {
} }
]), ]),
action: function(params, options, done) { action: function(params, options, done) {
var _, logStreams, logging, logs, resin, tmp, tmpNameAsync, upload; var Logger, _, logger, logs, resin, tmp, tmpNameAsync, upload;
_ = require('lodash'); _ = require('lodash');
tmp = require('tmp'); tmp = require('tmp');
tmpNameAsync = Promise.promisify(tmp.tmpName); tmpNameAsync = Promise.promisify(tmp.tmpName);
resin = require('resin-sdk-preconfigured'); resin = require('resin-sdk-preconfigured');
logging = require('../utils/logging'); Logger = require('../utils/logger');
logStreams = logging.getLogStreams(); logger = new Logger();
tmp.setGracefulCleanup(); tmp.setGracefulCleanup();
logs = ''; logs = '';
upload = function(token, username, url) { upload = function(token, username, url) {
@ -215,7 +195,7 @@ module.exports = {
}); });
return Promise["try"](function() { return Promise["try"](function() {
if (build) { if (build) {
return dockerUtils.runBuild(params, options, getBundleInfo, logStreams); return dockerUtils.runBuild(params, options, getBundleInfo, logger);
} else { } else {
return { return {
image: imageName, image: imageName,
@ -225,9 +205,9 @@ module.exports = {
}).then(function(arg1) { }).then(function(arg1) {
var buildLogs, imageName; var buildLogs, imageName;
imageName = arg1.image, buildLogs = arg1.log; imageName = arg1.image, buildLogs = arg1.log;
logging.logInfo(logStreams, 'Initializing deploy...'); logger.logInfo('Initializing deploy...');
logs = buildLogs; logs = buildLogs;
return Promise.all([dockerUtils.bufferImage(docker, imageName, bufferFile), token, username, url, params.appName, logStreams]).spread(performUpload); return Promise.all([dockerUtils.bufferImage(docker, imageName, bufferFile), token, username, url, params.appName, logger]).spread(performUpload);
})["finally"](function() { })["finally"](function() {
return Promise["try"](function() { return Promise["try"](function() {
return require('mz/fs').unlink(bufferFile); return require('mz/fs').unlink(bufferFile);
@ -237,7 +217,7 @@ module.exports = {
}).tap(function(arg) { }).tap(function(arg) {
var buildId, imageName; var buildId, imageName;
imageName = arg.image, buildId = arg.buildId; imageName = arg.image, buildId = arg.buildId;
logging.logSuccess(logStreams, "Successfully deployed image: " + (formatImageName(imageName))); logger.logSuccess("Successfully deployed image: " + (formatImageName(imageName)));
return buildId; return buildId;
}).then(function(arg) { }).then(function(arg) {
var buildId, imageName; var buildId, imageName;
@ -245,11 +225,11 @@ module.exports = {
if (logs === '' || (options.nologupload != null)) { if (logs === '' || (options.nologupload != null)) {
return ''; return '';
} }
logging.logInfo(logStreams, 'Uploading logs to dashboard...'); logger.logInfo('Uploading logs to dashboard...');
return Promise.join(logs, token, url, buildId, username, params.appName, uploadLogs)["return"]('Successfully uploaded logs'); return Promise.join(logs, token, url, buildId, username, params.appName, uploadLogs)["return"]('Successfully uploaded logs');
}).then(function(msg) { }).then(function(msg) {
if (msg !== '') { if (msg !== '') {
return logging.logSuccess(logStreams, msg); return logger.logSuccess(msg);
} }
}).asCallback(done); }).asCallback(done);
}); });

View File

@ -171,8 +171,8 @@ parseBuildArgs = function(args, onError) {
return buildArgs; return buildArgs;
}; };
exports.runBuild = function(params, options, getBundleInfo, logStreams) { exports.runBuild = function(params, options, getBundleInfo, logger) {
var Promise, dockerBuild, doodles, es, logging, logs, path, qemuPath, resolver, transpose; var Promise, dockerBuild, doodles, es, logs, path, qemuPath, resolver, transpose;
Promise = require('bluebird'); Promise = require('bluebird');
dockerBuild = require('resin-docker-build'); dockerBuild = require('resin-docker-build');
resolver = require('resin-bundle-resolve'); resolver = require('resin-bundle-resolve');
@ -180,7 +180,6 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) {
doodles = require('resin-doodles'); doodles = require('resin-doodles');
transpose = require('docker-qemu-transpose'); transpose = require('docker-qemu-transpose');
path = require('path'); path = require('path');
logging = require('../utils/logging');
if (params.source == null) { if (params.source == null) {
params.source = '.'; params.source = '.';
} }
@ -192,7 +191,7 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) {
} }
return hasQemu().then(function(present) { return hasQemu().then(function(present) {
if (!present) { if (!present) {
logging.logInfo(logStreams, 'Installing qemu for ARM emulation...'); logger.logInfo('Installing qemu for ARM emulation...');
return installQemu(); return installQemu();
} }
}).then(function() { }).then(function() {
@ -224,18 +223,18 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) {
buildStream: function(stream) { buildStream: function(stream) {
var buildThroughStream, logThroughStream, newStream; var buildThroughStream, logThroughStream, newStream;
if (options.emulated) { if (options.emulated) {
logging.logInfo(logStreams, 'Running emulated build'); logger.logInfo('Running emulated build');
} }
getBundleInfo(options).then(function(info) { getBundleInfo(options).then(function(info) {
var arch, bundle, deviceType; var arch, bundle, deviceType;
if (info == null) { if (info == null) {
logging.logWarn(logStreams, 'Warning: No architecture/device type or application information provided.\n Dockerfile/project pre-processing will not be performed.'); logger.logWarn('Warning: No architecture/device type or application information provided.\n Dockerfile/project pre-processing will not be performed.');
return tarStream; return tarStream;
} else { } else {
arch = info[0], deviceType = info[1]; arch = info[0], deviceType = info[1];
bundle = new resolver.Bundle(tarStream, deviceType, arch); bundle = new resolver.Bundle(tarStream, deviceType, arch);
return resolver.resolveBundle(bundle, resolver.getDefaultResolvers()).then(function(resolved) { return resolver.resolveBundle(bundle, resolver.getDefaultResolvers()).then(function(resolved) {
logging.logInfo(logStreams, "Building " + resolved.projectType + " project"); logger.logInfo("Building " + resolved.projectType + " project");
return resolved.tarStream; return resolved.tarStream;
}); });
} }
@ -264,13 +263,13 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) {
} else { } else {
newStream = stream; newStream = stream;
} }
return newStream.pipe(logThroughStream).pipe(cacheHighlightStream()).pipe(logStreams.build); return newStream.pipe(logThroughStream).pipe(cacheHighlightStream()).pipe(logger.streams.build);
} }
}; };
return generateConnectOpts(options).then(function(connectOpts) { return generateConnectOpts(options).then(function(connectOpts) {
var builder, opts; var builder, opts;
logging.logDebug(logStreams, 'Connecting with the following options:'); logger.logDebug('Connecting with the following options:');
logging.logDebug(logStreams, JSON.stringify(connectOpts, null, ' ')); logger.logDebug(JSON.stringify(connectOpts, null, ' '));
builder = new dockerBuild.Builder(connectOpts); builder = new dockerBuild.Builder(connectOpts);
opts = {}; opts = {};
if (options.tag != null) { if (options.tag != null) {
@ -281,7 +280,7 @@ exports.runBuild = function(params, options, getBundleInfo, logStreams) {
} }
if (options.buildArg != null) { if (options.buildArg != null) {
opts['buildargs'] = parseBuildArgs(options.buildArg, function(arg) { opts['buildargs'] = parseBuildArgs(options.buildArg, function(arg) {
return logging.logWarn(logStreams, "Could not parse variable: '" + arg + "'"); return logger.logWarn("Could not parse variable: '" + arg + "'");
}); });
} }
if (options.squash != null) { if (options.squash != null) {

61
build/utils/logger.js Normal file
View File

@ -0,0 +1,61 @@
// Generated by CoffeeScript 1.12.6
var Logger, eol;
eol = require('os').EOL;
module.exports = Logger = (function() {
function Logger() {
var StreamLogger, _, colors, logger;
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]'));
logger.addPrefix('error', colors.red('[Error]'));
this.streams = {
build: logger.createLogStream('build'),
info: logger.createLogStream('info'),
debug: logger.createLogStream('debug'),
success: logger.createLogStream('success'),
warn: logger.createLogStream('warn'),
error: logger.createLogStream('error')
};
_.mapKeys(this.streams, function(stream, key) {
if (key !== 'debug') {
return stream.pipe(process.stdout);
} else {
if (process.env.DEBUG != null) {
return stream.pipe(process.stdout);
}
}
});
this.formatMessage = logger.formatWithPrefix.bind(logger);
}
Logger.prototype.logInfo = function(msg) {
return this.streams.info.write(msg + eol);
};
Logger.prototype.logDebug = function(msg) {
return this.streams.debug.write(msg + eol);
};
Logger.prototype.logSuccess = function(msg) {
return this.streams.success.write(msg + eol);
};
Logger.prototype.logWarn = function(msg) {
return this.streams.warn.write(msg + eol);
};
Logger.prototype.logError = function(msg) {
return this.streams.error.write(msg + eol);
};
return Logger;
})();

View File

@ -58,7 +58,7 @@ module.exports =
}, },
] ]
action: (params, options, done) -> action: (params, options, done) ->
logging = require('../utils/logging') Logger = require('../utils/logger')
dockerUtils.runBuild(params, options, getBundleInfo, logging.getLogStreams()) dockerUtils.runBuild(params, options, getBundleInfo, new Logger())
.asCallback(done) .asCallback(done)

View File

@ -31,30 +31,11 @@ parseInput = Promise.method (params, options) ->
return [appName, options.build, source, image] return [appName, options.build, source, image]
# Builds and returns a Docker-like progress bar like this: showPushProgress = (message) ->
# [==================================> ] 64% visuals = require('resin-cli-visuals')
renderProgress = (percentage, stepCount = 50) -> progressBar = new visuals.Progress(message)
_ = require('lodash') progressBar.update({ percentage: 0 })
percentage = Math.max(0, Math.min(percentage, 100)) return progressBar
barCount = stepCount * percentage // 100
spaceCount = stepCount - barCount
bar = "[#{_.repeat('=', barCount)}>#{_.repeat(' ', spaceCount)}]"
return "#{bar} #{percentage.toFixed(1)}%"
showPushProgress = (logStreams) ->
logging = require('../utils/logging')
logging.logInfo(logStreams, renderProgress(0))
updatePushProgress = (percentage, logStreams) ->
logging = require('../utils/logging')
ansiEscapes = require('ansi-escapes')
if percentage >= 100
percentage = 100
process.stdout.write(ansiEscapes.cursorUp(1))
process.stdout.clearLine()
process.stdout.cursorTo(0)
logging.logInfo(logStreams, renderProgress(percentage))
getBundleInfo = (options) -> getBundleInfo = (options) ->
helpers = require('../utils/helpers') helpers = require('../utils/helpers')
@ -63,16 +44,21 @@ getBundleInfo = (options) ->
.then (app) -> .then (app) ->
[app.arch, app.device_type] [app.arch, app.device_type]
performUpload = (imageStream, token, username, url, appName, logStreams) -> performUpload = (imageStream, token, username, url, appName, logger) ->
request = require('request') request = require('request')
progressStream = require('progress-stream') progressStream = require('progress-stream')
zlib = require('zlib') zlib = require('zlib')
showPushProgress(logStreams) # Need to strip off the newline
streamWithProgress = imageStream.pipe(progressStream({ progressMessage = logger.formatMessage('info', 'Deploying').slice(0, -1)
progressBar = showPushProgress(progressMessage)
streamWithProgress = imageStream.pipe progressStream
time: 500, time: 500,
length: imageStream.length length: imageStream.length
}, ({ percentage }) -> updatePushProgress(percentage, logStreams))) , ({ percentage, eta }) ->
progressBar.update
percentage: Math.min(percentage, 100)
eta: eta
uploadRequest = request.post uploadRequest = request.post
url: getBuilderPushEndpoint(url, username, appName) url: getBuilderPushEndpoint(url, username, appName)
@ -84,7 +70,7 @@ performUpload = (imageStream, token, username, url, appName, logStreams) ->
level: 6 level: 6
})) }))
uploadToPromise(uploadRequest, logStreams) uploadToPromise(uploadRequest, logger)
uploadLogs = (logs, token, url, buildId, username, appName) -> uploadLogs = (logs, token, url, buildId, username, appName) ->
request = require('request') request = require('request')
@ -95,19 +81,17 @@ uploadLogs = (logs, token, url, buildId, username, appName) ->
bearer: token bearer: token
body: Buffer.from(logs) body: Buffer.from(logs)
uploadToPromise = (uploadRequest, logStreams) -> uploadToPromise = (uploadRequest, logger) ->
logging = require('../utils/logging')
new Promise (resolve, reject) -> new Promise (resolve, reject) ->
handleMessage = (data) -> handleMessage = (data) ->
data = data.toString() data = data.toString()
logging.logDebug(logStreams, "Received data: #{data}") logger.logDebug("Received data: #{data}")
try try
obj = JSON.parse(data) obj = JSON.parse(data)
catch e catch e
logging.logError(logStreams, 'Error parsing reply from remote side') logger.logError('Error parsing reply from remote side')
reject(e) reject(e)
return return
@ -115,7 +99,7 @@ uploadToPromise = (uploadRequest, logStreams) ->
switch obj.type switch obj.type
when 'error' then reject(new Error("Remote error: #{obj.error}")) when 'error' then reject(new Error("Remote error: #{obj.error}"))
when 'success' then resolve(obj) when 'success' then resolve(obj)
when 'status' then logging.logInfo(logStreams, "Remote: #{obj.message}") when 'status' then logger.logInfo("Remote: #{obj.message}")
else reject(new Error("Received unexpected reply from remote: #{data}")) else reject(new Error("Received unexpected reply from remote: #{data}"))
else else
reject(new Error("Received unexpected reply from remote: #{data}")) reject(new Error("Received unexpected reply from remote: #{data}"))
@ -165,9 +149,8 @@ module.exports =
tmpNameAsync = Promise.promisify(tmp.tmpName) tmpNameAsync = Promise.promisify(tmp.tmpName)
resin = require('resin-sdk-preconfigured') resin = require('resin-sdk-preconfigured')
logging = require('../utils/logging') Logger = require('../utils/logger')
logger = new Logger()
logStreams = logging.getLogStreams()
# Ensure the tmp files gets deleted # Ensure the tmp files gets deleted
tmp.setGracefulCleanup() tmp.setGracefulCleanup()
@ -189,11 +172,11 @@ module.exports =
Promise.try -> Promise.try ->
if build if build
dockerUtils.runBuild(params, options, getBundleInfo, logStreams) dockerUtils.runBuild(params, options, getBundleInfo, logger)
else else
{ image: imageName, log: '' } { image: imageName, log: '' }
.then ({ image: imageName, log: buildLogs }) -> .then ({ image: imageName, log: buildLogs }) ->
logging.logInfo(logStreams, 'Initializing deploy...') logger.logInfo('Initializing deploy...')
logs = buildLogs logs = buildLogs
Promise.all [ Promise.all [
@ -202,7 +185,7 @@ module.exports =
username username
url url
params.appName params.appName
logStreams logger
] ]
.spread(performUpload) .spread(performUpload)
.finally -> .finally ->
@ -213,13 +196,13 @@ module.exports =
require('mz/fs').unlink(bufferFile) require('mz/fs').unlink(bufferFile)
.catch(_.noop) .catch(_.noop)
.tap ({ image: imageName, buildId }) -> .tap ({ image: imageName, buildId }) ->
logging.logSuccess(logStreams, "Successfully deployed image: #{formatImageName(imageName)}") logger.logSuccess("Successfully deployed image: #{formatImageName(imageName)}")
return buildId return buildId
.then ({ image: imageName, buildId }) -> .then ({ image: imageName, buildId }) ->
if logs is '' or options.nologupload? if logs is '' or options.nologupload?
return '' return ''
logging.logInfo(logStreams, 'Uploading logs to dashboard...') logger.logInfo('Uploading logs to dashboard...')
Promise.join( Promise.join(
logs logs
@ -232,7 +215,7 @@ module.exports =
) )
.return('Successfully uploaded logs') .return('Successfully uploaded logs')
.then (msg) -> .then (msg) ->
logging.logSuccess(logStreams, msg) if msg isnt '' logger.logSuccess(msg) if msg isnt ''
.asCallback(done) .asCallback(done)
Promise.join( Promise.join(

View File

@ -174,7 +174,7 @@ parseBuildArgs = (args, onError) ->
# Pass in the command line parameters and options and also # Pass in the command line parameters and options and also
# a function which will return the information about the bundle # a function which will return the information about the bundle
exports.runBuild = (params, options, getBundleInfo, logStreams) -> exports.runBuild = (params, options, getBundleInfo, logger) ->
Promise = require('bluebird') Promise = require('bluebird')
dockerBuild = require('resin-docker-build') dockerBuild = require('resin-docker-build')
@ -184,8 +184,6 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) ->
transpose = require('docker-qemu-transpose') transpose = require('docker-qemu-transpose')
path = require('path') path = require('path')
logging = require('../utils/logging')
# The default build context is the current directory # The default build context is the current directory
params.source ?= '.' params.source ?= '.'
logs = '' logs = ''
@ -198,7 +196,7 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) ->
hasQemu() hasQemu()
.then (present) -> .then (present) ->
if !present if !present
logging.logInfo(logStreams, 'Installing qemu for ARM emulation...') logger.logInfo('Installing qemu for ARM emulation...')
installQemu() installQemu()
.then -> .then ->
# Copy the qemu binary into the build context # Copy the qemu binary into the build context
@ -226,12 +224,12 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) ->
buildFailure: reject buildFailure: reject
buildStream: (stream) -> buildStream: (stream) ->
if options.emulated if options.emulated
logging.logInfo(logStreams, 'Running emulated build') logger.logInfo('Running emulated build')
getBundleInfo(options) getBundleInfo(options)
.then (info) -> .then (info) ->
if !info? if !info?
logging.logWarn logStreams, ''' logger.logWarn '''
Warning: No architecture/device type or application information provided. Warning: No architecture/device type or application information provided.
Dockerfile/project pre-processing will not be performed. Dockerfile/project pre-processing will not be performed.
''' '''
@ -242,7 +240,7 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) ->
bundle = new resolver.Bundle(tarStream, deviceType, arch) bundle = new resolver.Bundle(tarStream, deviceType, arch)
resolver.resolveBundle(bundle, resolver.getDefaultResolvers()) resolver.resolveBundle(bundle, resolver.getDefaultResolvers())
.then (resolved) -> .then (resolved) ->
logging.logInfo(logStreams, "Building #{resolved.projectType} project") logger.logInfo("Building #{resolved.projectType} project")
return resolved.tarStream return resolved.tarStream
.then (buildStream) -> .then (buildStream) ->
@ -275,15 +273,15 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) ->
newStream newStream
.pipe(logThroughStream) .pipe(logThroughStream)
.pipe(cacheHighlightStream()) .pipe(cacheHighlightStream())
.pipe(logStreams.build) .pipe(logger.streams.build)
# Create a builder # Create a builder
generateConnectOpts(options) generateConnectOpts(options)
.then (connectOpts) -> .then (connectOpts) ->
# Allow degugging output, hidden behind an env var # Allow degugging output, hidden behind an env var
logging.logDebug(logStreams, 'Connecting with the following options:') logger.logDebug('Connecting with the following options:')
logging.logDebug(logStreams, JSON.stringify(connectOpts, null, ' ')) logger.logDebug(JSON.stringify(connectOpts, null, ' '))
builder = new dockerBuild.Builder(connectOpts) builder = new dockerBuild.Builder(connectOpts)
opts = {} opts = {}
@ -294,7 +292,7 @@ exports.runBuild = (params, options, getBundleInfo, logStreams) ->
opts['nocache'] = true opts['nocache'] = true
if options.buildArg? if options.buildArg?
opts['buildargs'] = parseBuildArgs options.buildArg, (arg) -> opts['buildargs'] = parseBuildArgs options.buildArg, (arg) ->
logging.logWarn(logStreams, "Could not parse variable: '#{arg}'") logger.logWarn("Could not parse variable: '#{arg}'")
if options.squash? if options.squash?
opts['squash'] = true opts['squash'] = true

46
lib/utils/logger.coffee Normal file
View File

@ -0,0 +1,46 @@
eol = require('os').EOL
module.exports = class Logger
constructor: ->
{ 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]'))
logger.addPrefix('error', colors.red('[Error]'))
@streams =
build: logger.createLogStream('build'),
info: logger.createLogStream('info'),
debug: logger.createLogStream('debug'),
success: logger.createLogStream('success'),
warn: logger.createLogStream('warn'),
error: logger.createLogStream('error')
_.mapKeys @streams, (stream, key) ->
if key isnt 'debug'
stream.pipe(process.stdout)
else
stream.pipe(process.stdout) if process.env.DEBUG?
@formatMessage = logger.formatWithPrefix.bind(logger)
logInfo: (msg) ->
@streams.info.write(msg + eol)
logDebug: (msg) ->
@streams.debug.write(msg + eol)
logSuccess: (msg) ->
@streams.success.write(msg + eol)
logWarn: (msg) ->
@streams.warn.write(msg + eol)
logError: (msg) ->
@streams.error.write(msg + eol)

View File

@ -1,45 +0,0 @@
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]'))
logger.addPrefix('error', colors.red('[Error]'))
streams =
build: logger.createLogStream('build'),
info: logger.createLogStream('info'),
debug: logger.createLogStream('debug'),
success: logger.createLogStream('success'),
warn: logger.createLogStream('warn'),
error: logger.createLogStream('error')
_.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)
exports.logError = (logStreams, msg) ->
logStreams.error.write(msg + eol)