diff --git a/packages/build/src/core/build.ts b/packages/build/src/core/build.ts index e45e9de7c2..3b84ac34af 100644 --- a/packages/build/src/core/build.ts +++ b/packages/build/src/core/build.ts @@ -27,7 +27,10 @@ export const startBuild = function (flags: Partial) { const timers = initTimers() const logs = getBufferLogs(flags) - logBuildStart(logs) + + if (!flags.quiet) { + logBuildStart(logs) + } const { bugsnagKey, ...flagsA } = normalizeFlags(flags, logs) const errorMonitor = startErrorMonitor({ flags: flagsA, logs, bugsnagKey }) @@ -72,6 +75,7 @@ const tExecBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) { const configOpts = getConfigOpts({ config, @@ -117,6 +121,7 @@ const tExecBuild = async function ({ logs, nodePath, timers, + quiet, }) const constants = await getConstants({ configPath, @@ -177,6 +182,7 @@ const tExecBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) return { pluginsOptions: pluginsOptionsA, @@ -227,6 +233,7 @@ export const runAndReportBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) { try { const { @@ -272,6 +279,7 @@ export const runAndReportBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) await Promise.all([ reportStatuses({ @@ -367,6 +375,7 @@ const initAndRunBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) { const { pluginsOptions: pluginsOptionsA, timers: timersA } = await getPluginsOptions({ pluginsOptions, @@ -396,6 +405,7 @@ const initAndRunBuild = async function ({ debug, timers: timersA, featureFlags, + quiet, }) try { @@ -439,6 +449,7 @@ const initAndRunBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) await Promise.all([ @@ -500,6 +511,7 @@ const runBuild = async function ({ featureFlags, timeline, devCommand, + quiet, }) { const { pluginsSteps, timers: timersA } = await loadPlugins({ pluginsOptions, @@ -554,6 +566,7 @@ const runBuild = async function ({ timers: timersA, testOpts, featureFlags, + quiet, }) return { stepsCount, netlifyConfig: netlifyConfigA, statuses, failedPlugins, timers: timersB, configMutations } diff --git a/packages/build/src/core/config.js b/packages/build/src/core/config.js index fe20cc6f05..fe75bc46f6 100644 --- a/packages/build/src/core/config.js +++ b/packages/build/src/core/config.js @@ -59,7 +59,16 @@ export const getConfigOpts = function ({ } // Retrieve configuration object -const tLoadConfig = async function ({ configOpts, cachedConfig, cachedConfigPath, envOpt, debug, logs, nodePath }) { +const tLoadConfig = async function ({ + configOpts, + cachedConfig, + cachedConfigPath, + envOpt, + debug, + logs, + nodePath, + quiet, +}) { const { configPath, headersPath, @@ -74,7 +83,10 @@ const tLoadConfig = async function ({ configOpts, cachedConfig, cachedConfigPath siteInfo, env, } = await resolveInitialConfig(configOpts, cachedConfig, cachedConfigPath) - logConfigInfo({ logs, configPath, buildDir, netlifyConfig, context: contextA, debug }) + + if (!quiet) { + logConfigInfo({ logs, configPath, buildDir, netlifyConfig, context: contextA, debug }) + } const apiA = addApiErrorHandlers(api) const envValues = mapObj(env, (key, { value }) => [key, value]) diff --git a/packages/build/src/core/normalize_flags.ts b/packages/build/src/core/normalize_flags.ts index 552cb8ea4f..ff4b3070b4 100644 --- a/packages/build/src/core/normalize_flags.ts +++ b/packages/build/src/core/normalize_flags.ts @@ -61,7 +61,9 @@ export const normalizeFlags = function (flags: Partial, logs): Re } const normalizedFlags = removeFalsy(mergedFlags) as any - logFlags(logs, rawFlags, normalizedFlags) + if (!flags.quiet) { + logFlags(logs, rawFlags, normalizedFlags) + } return normalizedFlags } @@ -90,6 +92,7 @@ const getDefaultFlags = function ({ env: envOpt = {} }, combinedEnv) { featureFlags: DEFAULT_FEATURE_FLAGS, statsd: { port: DEFAULT_STATSD_PORT }, timeline: 'build', + quiet: false, } } diff --git a/packages/build/src/core/types.ts b/packages/build/src/core/types.ts index 2502a5e011..e4d4839976 100644 --- a/packages/build/src/core/types.ts +++ b/packages/build/src/core/types.ts @@ -28,6 +28,11 @@ export type BuildCLIFlags = { cwd?: string /** A list of all the feature flags passed to netlify/build */ featureFlags: Record + /** + * Print only essential/error output + * @default false + */ + quiet?: boolean } export type BuildResult = { diff --git a/packages/build/src/plugins/spawn.ts b/packages/build/src/plugins/spawn.ts index 7fd076acf0..30e7320991 100644 --- a/packages/build/src/plugins/spawn.ts +++ b/packages/build/src/plugins/spawn.ts @@ -22,9 +22,12 @@ const CHILD_MAIN_FILE = fileURLToPath(new URL('child/main.js', import.meta.url)) // (for both security and safety reasons) // - logs can be buffered which allows manipulating them for log shipping, // transforming and parallel plugins -const tStartPlugins = async function ({ pluginsOptions, buildDir, childEnv, logs, debug, featureFlags }) { - logRuntime(logs, pluginsOptions) - logLoadingPlugins(logs, pluginsOptions, debug) +const tStartPlugins = async function ({ pluginsOptions, buildDir, childEnv, logs, debug, featureFlags, quiet }) { + if (!quiet) { + logRuntime(logs, pluginsOptions) + logLoadingPlugins(logs, pluginsOptions, debug) + } + logOutdatedPlugins(logs, pluginsOptions) logIncompatiblePlugins(logs, pluginsOptions) diff --git a/packages/build/src/steps/return.js b/packages/build/src/steps/return.js index 90eb485d31..a1ea9fd1cf 100644 --- a/packages/build/src/steps/return.js +++ b/packages/build/src/steps/return.js @@ -27,6 +27,7 @@ export const getStepReturn = function ({ durationNs, testOpts, systemLog, + quiet, }) { if (newError !== undefined) { return handleStepError({ @@ -45,9 +46,11 @@ export const getStepReturn = function ({ }) } - logStepSuccess(logs) + if (!quiet) { + logStepSuccess(logs) - logTimer(logs, durationNs, timerName, systemLog) + logTimer(logs, durationNs, timerName, systemLog) + } return { newEnvChanges, netlifyConfig, configMutations, headersPath, redirectsPath, newStatus, timers } } diff --git a/packages/build/src/steps/run_step.ts b/packages/build/src/steps/run_step.ts index 1e91ba3228..fd6c0b76a9 100644 --- a/packages/build/src/steps/run_step.ts +++ b/packages/build/src/steps/run_step.ts @@ -54,6 +54,7 @@ export const runStep = async function ({ timers, testOpts, featureFlags, + quiet, }) { const constantsA = await addMutableConstants({ constants, buildDir, netlifyConfig }) @@ -73,7 +74,9 @@ export const runStep = async function ({ return {} } - logStepStart({ logs, event, packageName, coreStepDescription, index, error, netlifyConfig }) + if (!quiet) { + logStepStart({ logs, event, packageName, coreStepDescription, index, error, netlifyConfig }) + } const fireStep = getFireStep(packageName, coreStepId, event) const { @@ -147,6 +150,7 @@ export const runStep = async function ({ durationNs, testOpts, systemLog, + quiet, }) return { ...newValues, newIndex: index + 1 } } diff --git a/packages/build/src/steps/run_steps.js b/packages/build/src/steps/run_steps.js index 46a5bf8e9e..9543fc9fde 100644 --- a/packages/build/src/steps/run_steps.js +++ b/packages/build/src/steps/run_steps.js @@ -39,6 +39,7 @@ export const runSteps = async function ({ timers, testOpts, featureFlags, + quiet, }) { const { index: stepsCount, @@ -133,6 +134,7 @@ export const runSteps = async function ({ timers: timersA, testOpts, featureFlags, + quiet, }) const statusesA = addStatus({ newStatus, statuses, event, packageName, pluginPackageJson }) return { diff --git a/packages/build/tests/plugins_events/fixtures/dev_with_error/manifest.yml b/packages/build/tests/plugins_events/fixtures/dev_with_error/manifest.yml new file mode 100644 index 0000000000..a3512f0259 --- /dev/null +++ b/packages/build/tests/plugins_events/fixtures/dev_with_error/manifest.yml @@ -0,0 +1,2 @@ +name: test +inputs: [] diff --git a/packages/build/tests/plugins_events/fixtures/dev_with_error/netlify.toml b/packages/build/tests/plugins_events/fixtures/dev_with_error/netlify.toml new file mode 100644 index 0000000000..4b06556c85 --- /dev/null +++ b/packages/build/tests/plugins_events/fixtures/dev_with_error/netlify.toml @@ -0,0 +1,2 @@ +[[plugins]] +package = "./plugin.js" diff --git a/packages/build/tests/plugins_events/fixtures/dev_with_error/plugin.js b/packages/build/tests/plugins_events/fixtures/dev_with_error/plugin.js new file mode 100644 index 0000000000..476bdd8a96 --- /dev/null +++ b/packages/build/tests/plugins_events/fixtures/dev_with_error/plugin.js @@ -0,0 +1,33 @@ +export const onPreDev = function ({ constants }) { + console.log('onPreDev:', constants) + + throw new Error('Houston, we have a problem.') +} + +export const onDev = function ({ constants }) { + console.log('onDev:', constants) +} + +export const onPreBuild = function ({ constants }) { + console.log('onPreBuild:', constants) +} + +export const onBuild = function ({ constants }) { + console.log('onBuild:', constants) +} + +export const onPostBuild = function ({ constants }) { + console.log('onPostBuild:', constants) +} + +export const onSuccess = function ({ constants }) { + console.log('onSuccess:', constants) +} + +export const onError = function ({ constants }) { + console.log('onError:', constants) +} + +export const onEnd = function ({ constants }) { + console.log('onEnd:', constants) +} diff --git a/packages/build/tests/plugins_events/snapshots/tests.js.md b/packages/build/tests/plugins_events/snapshots/tests.js.md index bc56db0304..2740293b7b 100644 --- a/packages/build/tests/plugins_events/snapshots/tests.js.md +++ b/packages/build/tests/plugins_events/snapshots/tests.js.md @@ -1640,3 +1640,86 @@ Generated by [AVA](https://avajs.dev). ␊ ␊ (dev1.0.0command completed in 1ms)` + +## Keeps output to a minimum in the `startDev` entrypoint when `quiet: true` + +> Snapshot 1 + + `onPreDev: {␊ + CONFIG_PATH: 'netlify.toml',␊ + FUNCTIONS_DIST: '.netlify/functions/',␊ + EDGE_FUNCTIONS_DIST: '.netlify/edge-functions-dist/',␊ + CACHE_DIR: '.netlify/cache',␊ + IS_LOCAL: true,␊ + NETLIFY_BUILD_VERSION: '1.0.0',␊ + SITE_ID: undefined,␊ + NETLIFY_API_TOKEN: undefined,␊ + NETLIFY_API_HOST: 'api.netlify.com',␊ + INTERNAL_FUNCTIONS_SRC: '.netlify/functions-internal',␊ + INTERNAL_EDGE_FUNCTIONS_SRC: '.netlify/edge-functions',␊ + PUBLISH_DIR: '.',␊ + FUNCTIONS_SRC: undefined,␊ + EDGE_FUNCTIONS_SRC: undefined␊ + }␊ + onDev: {␊ + CONFIG_PATH: 'netlify.toml',␊ + FUNCTIONS_DIST: '.netlify/functions/',␊ + EDGE_FUNCTIONS_DIST: '.netlify/edge-functions-dist/',␊ + CACHE_DIR: '.netlify/cache',␊ + IS_LOCAL: true,␊ + NETLIFY_BUILD_VERSION: '1.0.0',␊ + SITE_ID: undefined,␊ + NETLIFY_API_TOKEN: undefined,␊ + NETLIFY_API_HOST: 'api.netlify.com',␊ + INTERNAL_FUNCTIONS_SRC: '.netlify/functions-internal',␊ + INTERNAL_EDGE_FUNCTIONS_SRC: '.netlify/edge-functions',␊ + PUBLISH_DIR: '.',␊ + FUNCTIONS_SRC: undefined,␊ + EDGE_FUNCTIONS_SRC: undefined␊ + }` + +## Shows error information in the `startDev` entrypoint even when `quiet: true` + +> Snapshot 1 + + `onPreDev: {␊ + CONFIG_PATH: 'netlify.toml',␊ + FUNCTIONS_DIST: '.netlify/functions/',␊ + EDGE_FUNCTIONS_DIST: '.netlify/edge-functions-dist/',␊ + CACHE_DIR: '.netlify/cache',␊ + IS_LOCAL: true,␊ + NETLIFY_BUILD_VERSION: '1.0.0',␊ + SITE_ID: undefined,␊ + NETLIFY_API_TOKEN: undefined,␊ + NETLIFY_API_HOST: 'api.netlify.com',␊ + INTERNAL_FUNCTIONS_SRC: '.netlify/functions-internal',␊ + INTERNAL_EDGE_FUNCTIONS_SRC: '.netlify/edge-functions',␊ + PUBLISH_DIR: '.',␊ + FUNCTIONS_SRC: undefined,␊ + EDGE_FUNCTIONS_SRC: undefined␊ + }␊ + ␊ + Plugin "./plugin.js" internal error ␊ + ────────────────────────────────────────────────────────────────␊ + ␊ + Error message␊ + Error: Houston, we have a problem.␊ + ␊ + Plugin details␊ + Package: ./plugin.js␊ + Version: 1.0.0␊ + Repository: git+https://github.com/netlify/build.git␊ + Report issues: https://github.com/netlify/build/issues␊ + ␊ + Error location␊ + In "onPreDev" event in "./plugin.js" from netlify.toml␊ + STACK TRACE␊ + ␊ + Resolved config␊ + build:␊ + publish: packages/build/tests/plugins_events/fixtures/dev_with_error␊ + publishOrigin: default␊ + plugins:␊ + - inputs: {}␊ + origin: config␊ + package: ./plugin.js` diff --git a/packages/build/tests/plugins_events/snapshots/tests.js.snap b/packages/build/tests/plugins_events/snapshots/tests.js.snap index ec4ce5dea0..f044ed3290 100644 Binary files a/packages/build/tests/plugins_events/snapshots/tests.js.snap and b/packages/build/tests/plugins_events/snapshots/tests.js.snap differ diff --git a/packages/build/tests/plugins_events/tests.js b/packages/build/tests/plugins_events/tests.js index d22baa47da..b82a7f7a8e 100644 --- a/packages/build/tests/plugins_events/tests.js +++ b/packages/build/tests/plugins_events/tests.js @@ -112,3 +112,25 @@ test('Runs the `*Dev` events and not the `*Build` events on the dev timeline', a t.is(devCommand.callCount, 1) }) + +test('Keeps output to a minimum in the `startDev` entrypoint when `quiet: true`', async (t) => { + const devCommand = sinon.stub().resolves() + + const output = await new Fixture('./fixtures/dev_and_build') + .withFlags({ debug: false, quiet: true, timeline: 'dev' }) + .runDev(devCommand) + t.snapshot(normalizeOutput(output)) + + t.is(devCommand.callCount, 1) +}) + +test('Shows error information in the `startDev` entrypoint even when `quiet: true`', async (t) => { + const devCommand = sinon.stub().resolves() + + const output = await new Fixture('./fixtures/dev_with_error') + .withFlags({ debug: false, quiet: true, timeline: 'dev' }) + .runDev(devCommand) + t.snapshot(normalizeOutput(output)) + + t.is(devCommand.callCount, 0) +})