From afb68169cb2f5c1b96c53527ca4566af096b68ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Wed, 29 May 2024 09:22:01 +0100 Subject: [PATCH 1/2] feat: capture plugin errors during `ready` phase (#5681) --- packages/build/src/core/build.ts | 1 + packages/build/src/plugins/load.js | 24 ++-------- packages/build/src/plugins/spawn.ts | 45 ++++++++++++++++-- packages/build/src/plugins/system_log.ts | 37 ++++++++++++++ .../tests/plugins/snapshots/tests.js.snap | Bin 6009 -> 6011 bytes packages/build/tests/plugins/tests.js | 4 +- 6 files changed, 85 insertions(+), 26 deletions(-) create mode 100644 packages/build/src/plugins/system_log.ts diff --git a/packages/build/src/core/build.ts b/packages/build/src/core/build.ts index c82213bfe0..d699e8de31 100644 --- a/packages/build/src/core/build.ts +++ b/packages/build/src/core/build.ts @@ -481,6 +481,7 @@ const initAndRunBuild = async function ({ timers: timersA, featureFlags, quiet, + systemLog, systemLogFile, }) diff --git a/packages/build/src/plugins/load.js b/packages/build/src/plugins/load.js index e9cb700785..37cddd628d 100644 --- a/packages/build/src/plugins/load.js +++ b/packages/build/src/plugins/load.js @@ -5,6 +5,7 @@ import { addPluginLoadErrorStatus } from '../status/load_error.js' import { measureDuration } from '../time/main.js' import { callChild } from './ipc.js' +import { captureStandardError } from './system_log.js' const pSetTimeout = promisify(setTimeout) @@ -79,20 +80,7 @@ const loadPlugin = async function ( ) { const { childProcess } = childProcesses[index] const loadEvent = 'load' - - // A buffer for any data piped into the child process' stderr. We'll pipe - // this to system logs if we fail to load the plugin. - const bufferedStdErr = [] - - let bufferedStdListener - - if (featureFlags.netlify_build_plugin_system_log && childProcess.stderr) { - bufferedStdListener = (data) => { - bufferedStdErr.push(data.toString().trimEnd()) - } - - childProcess.stderr.on('data', bufferedStdListener) - } + const cleanup = captureStandardError(childProcess, systemLog, loadEvent, featureFlags) try { const { events } = await callChild({ @@ -115,10 +103,6 @@ const loadPlugin = async function ( if (featureFlags.netlify_build_plugin_system_log) { // Wait for stderr to be flushed. await pSetTimeout(0) - - bufferedStdErr.forEach((line) => { - systemLog(line) - }) } addErrorInfo(error, { @@ -128,8 +112,6 @@ const loadPlugin = async function ( addPluginLoadErrorStatus({ error, packageName, version, debug }) throw error } finally { - if (bufferedStdListener) { - childProcess.stderr.removeListener('data', bufferedStdListener) - } + cleanup() } } diff --git a/packages/build/src/plugins/spawn.ts b/packages/build/src/plugins/spawn.ts index 6512fb8d6c..75073ad482 100644 --- a/packages/build/src/plugins/spawn.ts +++ b/packages/build/src/plugins/spawn.ts @@ -1,10 +1,12 @@ import { createRequire } from 'module' import { fileURLToPath, pathToFileURL } from 'url' +import { promisify } from 'util' import { trace } from '@opentelemetry/api' import { ExecaChildProcess, execaNode } from 'execa' import { gte } from 'semver' +import { FeatureFlags } from '../core/feature_flags.js' import { addErrorInfo } from '../error/info.js' import { NetlifyConfig } from '../index.js' import { BufferedLogs } from '../log/logger.js' @@ -15,17 +17,19 @@ import { logOutdatedPlugins, logRuntime, } from '../log/messages/compatibility.js' +import { SystemLogger } from '../plugins_core/types.js' import { isTrustedPlugin } from '../steps/plugin.js' import { measureDuration } from '../time/main.js' import { callChild, getEventFromChild } from './ipc.js' import { PluginsOptions } from './node_version.js' import { getSpawnInfo } from './options.js' +import { captureStandardError } from './system_log.js' export type ChildProcess = ExecaChildProcess const CHILD_MAIN_FILE = fileURLToPath(new URL('child/main.js', import.meta.url)) - +const pSetTimeout = promisify(setTimeout) const require = createRequire(import.meta.url) // Start child processes used by all plugins @@ -34,7 +38,17 @@ const require = createRequire(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, quiet, systemLogFile }) { +const tStartPlugins = async function ({ + pluginsOptions, + buildDir, + childEnv, + logs, + debug, + quiet, + systemLog, + systemLogFile, + featureFlags, +}) { if (!quiet) { logRuntime(logs, pluginsOptions) logLoadingPlugins(logs, pluginsOptions, debug) @@ -46,7 +60,17 @@ const tStartPlugins = async function ({ pluginsOptions, buildDir, childEnv, logs const childProcesses = await Promise.all( pluginsOptions.map(({ pluginDir, nodePath, nodeVersion, pluginPackageJson }) => - startPlugin({ pluginDir, nodePath, nodeVersion, buildDir, childEnv, systemLogFile, pluginPackageJson }), + startPlugin({ + pluginDir, + nodePath, + nodeVersion, + buildDir, + childEnv, + systemLog, + systemLogFile, + pluginPackageJson, + featureFlags, + }), ), ) return { childProcesses } @@ -60,8 +84,10 @@ const startPlugin = async function ({ nodePath, buildDir, childEnv, + systemLog, systemLogFile, pluginPackageJson, + featureFlags, }: { nodeVersion: string nodePath: string @@ -70,7 +96,9 @@ const startPlugin = async function ({ buildDir: string childEnv: Record pluginPackageJson: Record + systemLog: SystemLogger systemLogFile: number + featureFlags: FeatureFlags }) { const ctx = trace.getActiveSpan()?.spanContext() @@ -117,14 +145,23 @@ const startPlugin = async function ({ ? ['pipe', 'pipe', 'pipe', 'ipc', systemLogFile] : undefined, }) + const readyEvent = 'ready' + const cleanup = captureStandardError(childProcess, systemLog, readyEvent, featureFlags) try { - await getEventFromChild(childProcess, 'ready') + await getEventFromChild(childProcess, readyEvent) return { childProcess } } catch (error) { + if (featureFlags.netlify_build_plugin_system_log) { + // Wait for stderr to be flushed. + await pSetTimeout(0) + } + const spawnInfo = getSpawnInfo() addErrorInfo(error, spawnInfo) throw error + } finally { + cleanup() } } diff --git a/packages/build/src/plugins/system_log.ts b/packages/build/src/plugins/system_log.ts new file mode 100644 index 0000000000..fa90a81f74 --- /dev/null +++ b/packages/build/src/plugins/system_log.ts @@ -0,0 +1,37 @@ +import type { FeatureFlags } from '../core/feature_flags.js' +import type { SystemLogger } from '../plugins_core/types.js' + +import type { ChildProcess } from './spawn.js' + +export const captureStandardError = ( + childProcess: ChildProcess, + systemLog: SystemLogger, + eventName: string, + featureFlags: FeatureFlags, +) => { + if (!featureFlags.netlify_build_plugin_system_log) { + return () => { + // no-op + } + } + + let receivedChunks = false + + const listener = (chunk: Buffer) => { + if (!receivedChunks) { + receivedChunks = true + + systemLog(`Plugin failed to initialize during the "${eventName}" phase`) + } + + systemLog(chunk.toString().trimEnd()) + } + + childProcess.stderr?.on('data', listener) + + const cleanup = () => { + childProcess.stderr?.removeListener('data', listener) + } + + return cleanup +} diff --git a/packages/build/tests/plugins/snapshots/tests.js.snap b/packages/build/tests/plugins/snapshots/tests.js.snap index d3bb62fc0d2f84dcf44b4c594eee34036cfcb889..a0e706ac7dfe3489119e32c9196ea8df24774e86 100644 GIT binary patch delta 5136 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 delta 5134 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 Date: Wed, 29 May 2024 03:41:36 -0500 Subject: [PATCH 2/2] chore: release main (#5682) --- .release-please-manifest.json | 2 +- package-lock.json | 2 +- packages/build/CHANGELOG.md | 7 +++++++ packages/build/package.json | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 5e0d774213..bddc2c5d1d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,6 +1,6 @@ { "packages/build-info": "7.13.2", - "packages/build": "29.44.0", + "packages/build": "29.45.0", "packages/edge-bundler": "12.0.1", "packages/cache-utils": "5.1.5", "packages/config": "20.12.6", diff --git a/package-lock.json b/package-lock.json index 57a477d904..0d4f88dde6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26651,7 +26651,7 @@ }, "packages/build": { "name": "@netlify/build", - "version": "29.44.0", + "version": "29.45.0", "license": "MIT", "dependencies": { "@bugsnag/js": "^7.0.0", diff --git a/packages/build/CHANGELOG.md b/packages/build/CHANGELOG.md index 5794892816..73aa15828a 100644 --- a/packages/build/CHANGELOG.md +++ b/packages/build/CHANGELOG.md @@ -105,6 +105,13 @@ * dependencies * @netlify/config bumped from ^20.8.0 to ^20.8.1 +## [29.45.0](https://github.com/netlify/build/compare/build-v29.44.0...build-v29.45.0) (2024-05-29) + + +### Features + +* capture plugin errors during `ready` phase ([#5681](https://github.com/netlify/build/issues/5681)) ([afb6816](https://github.com/netlify/build/commit/afb68169cb2f5c1b96c53527ca4566af096b68ce)) + ## [29.44.0](https://github.com/netlify/build/compare/build-v29.43.0...build-v29.44.0) (2024-05-28) diff --git a/packages/build/package.json b/packages/build/package.json index 8c3f3a5071..49e87368fa 100644 --- a/packages/build/package.json +++ b/packages/build/package.json @@ -1,6 +1,6 @@ { "name": "@netlify/build", - "version": "29.44.0", + "version": "29.45.0", "description": "Netlify build module", "type": "module", "exports": "./lib/index.js",