From 49284742a1a5f8cdab03843e860d140ef3981f4a Mon Sep 17 00:00:00 2001 From: ehmicky Date: Mon, 18 May 2020 11:33:50 +0200 Subject: [PATCH] Split statuses code into several files --- packages/build/src/core/commands.js | 3 +- packages/build/src/core/main.js | 2 +- packages/build/src/core/status.js | 134 -------------------- packages/build/src/plugins/load.js | 2 +- packages/build/src/plugins/manifest/main.js | 2 +- packages/build/src/status/add.js | 56 ++++++++ packages/build/src/status/colors.js | 25 ++++ packages/build/src/status/report.js | 57 +++++++++ 8 files changed, 142 insertions(+), 139 deletions(-) delete mode 100644 packages/build/src/core/status.js create mode 100644 packages/build/src/status/add.js create mode 100644 packages/build/src/status/colors.js create mode 100644 packages/build/src/status/report.js diff --git a/packages/build/src/core/commands.js b/packages/build/src/core/commands.js index 51037a8751..57c71fbf25 100644 --- a/packages/build/src/core/commands.js +++ b/packages/build/src/core/commands.js @@ -12,8 +12,7 @@ const { pipeOutput, unpipeOutput } = require('../log/stream') const { startTimer, endTimer } = require('../log/timer') const { EVENTS } = require('../plugins/events') const { callChild } = require('../plugins/ipc') - -const { getSuccessStatus, addStatus } = require('./status') +const { getSuccessStatus, addStatus } = require('../status/add') // Get commands for all events const getCommands = function(pluginsCommands, netlifyConfig) { diff --git a/packages/build/src/core/main.js b/packages/build/src/core/main.js index bcc43e8254..6cb172560a 100644 --- a/packages/build/src/core/main.js +++ b/packages/build/src/core/main.js @@ -21,12 +21,12 @@ const { startUtils } = require('../plugins/child/utils') const { loadPlugins } = require('../plugins/load') const { getPluginsOptions } = require('../plugins/options') const { startPlugins, stopPlugins } = require('../plugins/spawn') +const { reportStatuses } = require('../status/report') const { trackBuildComplete } = require('../telemetry/complete') const { getCommands, runCommands } = require('./commands') const { normalizeFlags, loadConfig } = require('./config') const { doDryRun } = require('./dry') -const { reportStatuses } = require('./status') /** * Netlify Build diff --git a/packages/build/src/core/status.js b/packages/build/src/core/status.js deleted file mode 100644 index a9766d4288..0000000000 --- a/packages/build/src/core/status.js +++ /dev/null @@ -1,134 +0,0 @@ -const { env } = require('process') - -const stripAnsi = require('strip-ansi') - -const { serializeErrorStatus } = require('../error/parse/serialize_status') -const { logStatuses } = require('../log/main') - -// The last event handler of a plugin (except for `onError` and `onEnd`) -// defaults to `utils.status.show({ state: 'success' })` without any `summary`. -const getSuccessStatus = function(newStatus, { commands, event, package }) { - if (newStatus === undefined && isLastMainCommand({ commands, event, package })) { - return IMPLICIT_STATUS - } - - return newStatus -} - -const isLastMainCommand = function({ commands, event, package }) { - const mainCommands = commands.filter(command => command.package === package && isMainCommand(command)) - return mainCommands.length === 0 || mainCommands[mainCommands.length - 1].event === event -} - -const isMainCommand = function({ event }) { - return event !== 'onEnd' && event !== 'onError' -} - -const IMPLICIT_STATUS = { state: 'success', implicit: true } - -// Merge plugin status to the list of plugin statuses. -const addStatus = function({ newStatus, statuses, event, package, packageJson: { version } = {} }) { - // Either: - // - `build.command` - // - no status was set - if (newStatus === undefined) { - return statuses - } - - const formerStatus = statuses.find(status => status.package === package) - if (!canOverrideStatus(formerStatus, newStatus)) { - return statuses - } - - // Overrides plugin's previous status and add more information - const newStatuses = statuses.filter(status => status !== formerStatus) - return [...newStatuses, { ...newStatus, event, package, version }] -} - -const canOverrideStatus = function(formerStatus, newStatus) { - // No previous status - if (formerStatus === undefined) { - return true - } - - // Implicit statuses can never override - if (newStatus.implicit) { - return false - } - - // Error statuses can only be overwritten by other error statuses - return formerStatus.state === 'success' || newStatus.state !== 'success' -} - -// Errors that happen during plugin loads should be reported as error statuses -const reportPluginLoadError = async function({ error, api, mode, event, package, version }) { - const errorStatus = serializeErrorStatus(error) - const statuses = [{ ...errorStatus, event, package, version }] - await reportStatuses(statuses, api, mode) -} - -const reportStatuses = async function(statuses, api, mode) { - const statusesA = removeStatusesColors(statuses) - printStatuses(statusesA, mode) - await sendStatuses(statusesA, api, mode) -} - -// Remove colors from statuses -const removeStatusesColors = function(statuses) { - return statuses.map(removeStatusColors) -} - -const removeStatusColors = function(status) { - const attributes = COLOR_ATTRIBUTES.map(attribute => removeAttrColor(status, attribute)) - return Object.assign({}, status, ...attributes) -} - -const COLOR_ATTRIBUTES = ['title', 'summary', 'text'] - -const removeAttrColor = function(status, attribute) { - const value = status[attribute] - if (value === undefined) { - return {} - } - - const valueA = stripAnsi(value) - return { [attribute]: valueA } -} - -// When not in production, print statuses to console. -// Only print successful ones, since errors are logged afterwards. -const printStatuses = function(statuses, mode) { - if (mode === 'buildbot') { - return - } - - const successStatuses = statuses.filter(shouldPrintStatus) - - if (successStatuses.length === 0) { - return - } - - logStatuses(successStatuses) -} - -const shouldPrintStatus = function({ state, summary }) { - return state === 'success' && summary !== undefined -} - -// In production, send statuses to the API -const sendStatuses = async function(statuses, api, mode) { - if ((mode !== 'buildbot' && env.NETLIFY_BUILD_TEST_STATUS !== '1') || api === undefined || !env.DEPLOY_ID) { - return - } - - await Promise.all(statuses.map(status => sendStatus(api, status))) -} - -const sendStatus = async function(api, { package, version, state, event, title, summary, text }) { - await api.createPluginRun({ - deploy_id: env.DEPLOY_ID, - body: { package, version, state, reporting_event: event, title, summary, text }, - }) -} - -module.exports = { getSuccessStatus, addStatus, reportPluginLoadError, reportStatuses } diff --git a/packages/build/src/plugins/load.js b/packages/build/src/plugins/load.js index 1815ab36af..be7abbb3d1 100644 --- a/packages/build/src/plugins/load.js +++ b/packages/build/src/plugins/load.js @@ -1,4 +1,4 @@ -const { reportPluginLoadError } = require('../core/status') +const { reportPluginLoadError } = require('../status/report') const { callChild } = require('./ipc') diff --git a/packages/build/src/plugins/manifest/main.js b/packages/build/src/plugins/manifest/main.js index 2dacd380aa..97ca56f886 100644 --- a/packages/build/src/plugins/manifest/main.js +++ b/packages/build/src/plugins/manifest/main.js @@ -1,4 +1,4 @@ -const { reportPluginLoadError } = require('../../core/status') +const { reportPluginLoadError } = require('../../status/report') const { checkInputs } = require('./check') const { loadManifest } = require('./load') diff --git a/packages/build/src/status/add.js b/packages/build/src/status/add.js new file mode 100644 index 0000000000..f1a915f1a8 --- /dev/null +++ b/packages/build/src/status/add.js @@ -0,0 +1,56 @@ +// The last event handler of a plugin (except for `onError` and `onEnd`) +// defaults to `utils.status.show({ state: 'success' })` without any `summary`. +const getSuccessStatus = function(newStatus, { commands, event, package }) { + if (newStatus === undefined && isLastMainCommand({ commands, event, package })) { + return IMPLICIT_STATUS + } + + return newStatus +} + +const isLastMainCommand = function({ commands, event, package }) { + const mainCommands = commands.filter(command => command.package === package && isMainCommand(command)) + return mainCommands.length === 0 || mainCommands[mainCommands.length - 1].event === event +} + +const isMainCommand = function({ event }) { + return event !== 'onEnd' && event !== 'onError' +} + +const IMPLICIT_STATUS = { state: 'success', implicit: true } + +// Merge plugin status to the list of plugin statuses. +const addStatus = function({ newStatus, statuses, event, package, packageJson: { version } = {} }) { + // Either: + // - `build.command` + // - no status was set + if (newStatus === undefined) { + return statuses + } + + const formerStatus = statuses.find(status => status.package === package) + if (!canOverrideStatus(formerStatus, newStatus)) { + return statuses + } + + // Overrides plugin's previous status and add more information + const newStatuses = statuses.filter(status => status !== formerStatus) + return [...newStatuses, { ...newStatus, event, package, version }] +} + +const canOverrideStatus = function(formerStatus, newStatus) { + // No previous status + if (formerStatus === undefined) { + return true + } + + // Implicit statuses can never override + if (newStatus.implicit) { + return false + } + + // Error statuses can only be overwritten by other error statuses + return formerStatus.state === 'success' || newStatus.state !== 'success' +} + +module.exports = { getSuccessStatus, addStatus } diff --git a/packages/build/src/status/colors.js b/packages/build/src/status/colors.js new file mode 100644 index 0000000000..6973f389f8 --- /dev/null +++ b/packages/build/src/status/colors.js @@ -0,0 +1,25 @@ +const stripAnsi = require('strip-ansi') + +// Remove colors from statuses +const removeStatusesColors = function(statuses) { + return statuses.map(removeStatusColors) +} + +const removeStatusColors = function(status) { + const attributes = COLOR_ATTRIBUTES.map(attribute => removeAttrColor(status, attribute)) + return Object.assign({}, status, ...attributes) +} + +const COLOR_ATTRIBUTES = ['title', 'summary', 'text'] + +const removeAttrColor = function(status, attribute) { + const value = status[attribute] + if (value === undefined) { + return {} + } + + const valueA = stripAnsi(value) + return { [attribute]: valueA } +} + +module.exports = { removeStatusesColors } diff --git a/packages/build/src/status/report.js b/packages/build/src/status/report.js new file mode 100644 index 0000000000..b5aa1862d9 --- /dev/null +++ b/packages/build/src/status/report.js @@ -0,0 +1,57 @@ +const { env } = require('process') + +const { serializeErrorStatus } = require('../error/parse/serialize_status') +const { logStatuses } = require('../log/main') + +const { removeStatusesColors } = require('./colors') + +// Errors that happen during plugin loads should be reported as error statuses +const reportPluginLoadError = async function({ error, api, mode, event, package, version }) { + const errorStatus = serializeErrorStatus(error) + const statuses = [{ ...errorStatus, event, package, version }] + await reportStatuses(statuses, api, mode) +} + +const reportStatuses = async function(statuses, api, mode) { + const statusesA = removeStatusesColors(statuses) + printStatuses(statusesA, mode) + await sendStatuses(statusesA, api, mode) +} + +// When not in production, print statuses to console. +// Only print successful ones, since errors are logged afterwards. +const printStatuses = function(statuses, mode) { + if (mode === 'buildbot') { + return + } + + const successStatuses = statuses.filter(shouldPrintStatus) + + if (successStatuses.length === 0) { + return + } + + logStatuses(successStatuses) +} + +const shouldPrintStatus = function({ state, summary }) { + return state === 'success' && summary !== undefined +} + +// In production, send statuses to the API +const sendStatuses = async function(statuses, api, mode) { + if ((mode !== 'buildbot' && env.NETLIFY_BUILD_TEST_STATUS !== '1') || api === undefined || !env.DEPLOY_ID) { + return + } + + await Promise.all(statuses.map(status => sendStatus(api, status))) +} + +const sendStatus = async function(api, { package, version, state, event, title, summary, text }) { + await api.createPluginRun({ + deploy_id: env.DEPLOY_ID, + body: { package, version, state, reporting_event: event, title, summary, text }, + }) +} + +module.exports = { reportPluginLoadError, reportStatuses }