mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-23 15:32:22 +00:00
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:
commit
e660c6ae90
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -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
61
build/utils/logger.js
Normal 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;
|
||||||
|
|
||||||
|
})();
|
@ -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)
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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
46
lib/utils/logger.coffee
Normal 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)
|
@ -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)
|
|
Loading…
Reference in New Issue
Block a user