UNPKG

briareus

Version:

Briareus assists with Feature Branch deploys to ECS

200 lines (162 loc) 5.53 kB
'use static' const readline = require('readline'); const moment = require('moment'); const colors = require('colors/safe'); const indent = require('indent'); const EventEmitter = require('events'); const DeploymentRenderer = require('../../node_modules/ecs-deployment-monitor/lib/renderer'); const indentWidth = 4; var _spinner; class Renderer { /** * watch * * Watch a deployment and render information about state changes to output stream. * * @param {object} variant A task object * @param {stream} output A stream. If process.stdout then tty is assumed and * it will be sent decorative output */ constructor(variant, output) { this.variant = variant; this.output = output; this.hasShownInfoBanner = false; // If output is a tty then force color output if (this.output instanceof require('tty').WriteStream) colors.enable(); variant.on('event', (data) => this._eventProcess(data)); } /** * _showWaitingMessage * * Show a temporary waiting message while state is in progress. */ _showWaitingMessage(msg) { // Only shown if output is a tty (process.stdout). if (!(this.output instanceof require('tty').WriteStream)) return; let spinnerSymbols = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷']; let i = 0; _spinner = setInterval(() => { readline.clearLine(this.output); readline.cursorTo(this.output, indentWidth - 2); this.output.write(colors.cyan(spinnerSymbols[i % spinnerSymbols.length])); this.output.write(' ' + colors.gray(msg)); i++; }, 1000); } /** * _removeWaitingMessage * * Remove the waiting message */ _removeWaitingMessage() { clearInterval(_spinner); readline.clearLine(this.output); readline.cursorTo(this.output, 0); } /** * _getStateDurationText * * Get the duration the current state has been in progress for in * descriptive text form. * * @param {integer} durationSeconds Duration in seconds * @return {string} */ _getStateDurationText(durationSeconds) { let duration = moment.duration(durationSeconds, 'seconds'); let durationText = `${duration.seconds()} seconds`; if (duration.minutes()) { durationText = `${duration.minutes()} minutes ${durationText}` } if (duration.hours()) { durationText = `${duration.hours()} hours ${durationText}` } return durationText; } /** * _eventProcess * * Process an event change on a deployment * * @param {string} event The event */ _eventProcess(event) { switch (event.name) { case 'exec:start': this._showInfoBanner(event); break; case 'phase:start': this._startPhase(event); break; case 'action:start': this._startAction(event); break; case 'action:error': this._errorAction(event); break; case 'action:complete': this._completeAction(event); break; case 'deploy:end': this._showDeployCompleteBanner(event) break; } } _showInfoBanner(event) { if (this.hasShownInfoBanner) return false; let screenWidth = 80; let textColor = 'gray'; let borderColor = 'gray'; let borderChar = '+'; function drawTextLine(text) { return colors[borderColor](borderChar) + " " + colors[textColor](text); } let banner = ` ${colors[borderColor]("".padStart(screenWidth, borderChar))} ${' Slug: ' + this.variant.data.slug} ${' HashedSlug: ' + this.variant.data.hashedSlug} ${' Endpoint: ' + this.variant.data.endpoint.url} ${colors[borderColor]("".padStart(screenWidth, borderChar))} ` this.output.write(banner + "\n"); this.hasShownInfoBanner = true } _startPhase(event) { this.output.write(colors.cyan(`${event.data.phase.message} \n`)); this.output.write(colors.cyan("=".repeat(event.data.phase.message.length)) + "\n"); this.output.write("\n"); } _startAction(event) { this.output.write(colors.cyan(`-> ${event.data.action.id} \n`)); if (event.data.action.message) { this._showWaitingMessage(event.data.action.message); } } _errorAction(event) { this._removeWaitingMessage(); this.output.write(colors.red(`-> ${event.data.action.id} \n`)); this.output.write(indent(colors.red(event.data.action.message), indentWidth) + "\n"); if (event.data.action.extra) { this.output.write(indent(colors.red(event.data.action.extra), indentWidth) + "\n"); } } _completeAction(event) { this._removeWaitingMessage(); let message = indent(colors.green('✓') + " " + colors.gray(event.data.action.message), indentWidth - 2); if (event.data.monitor) { if (event.data.monitor.isSteady) message = indent(colors.green(event.data.action.message), indentWidth) if (event.data.monitor.isFailure) message = indent(colors.red(event.data.action.message), indentWidth) } this.output.write(message + "\n"); if (event.data.action.id !== 'Steady') { this.output.write(indent(colors.gray(`Step took ${this._getStateDurationText(event.data.action.duration)} to complete`), indentWidth) + "\n"); } this.output.write("\n"); } _showDeployCompleteBanner(event) { // Don't show banner if we have an error if (event.data.error) return; this.output.write(colors.green(`Briareus has successfully deployed the build to ${this.variant.data.endpoint.url}\n`)) } } module.exports = Renderer;