@netlify/build 20.2.0 → 21.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/build",
3
- "version": "20.2.0",
3
+ "version": "21.0.0",
4
4
  "description": "Netlify build module",
5
5
  "main": "src/core/main.js",
6
6
  "types": "types/index.d.ts",
@@ -59,7 +59,7 @@
59
59
  "@netlify/functions-utils": "^3.0.0",
60
60
  "@netlify/git-utils": "^3.0.0",
61
61
  "@netlify/plugin-edge-handlers": "^3.0.0",
62
- "@netlify/plugins-list": "^6.0.1",
62
+ "@netlify/plugins-list": "^6.2.0",
63
63
  "@netlify/run-utils": "^3.0.0",
64
64
  "@netlify/zip-it-and-ship-it": "^5.2.0",
65
65
  "@sindresorhus/slugify": "^1.1.0",
package/src/core/flags.js CHANGED
@@ -134,7 +134,12 @@ Default: false`,
134
134
  },
135
135
  debug: {
136
136
  boolean: true,
137
- describe: 'Print debugging information',
137
+ describe: 'Print user-facing debugging information',
138
+ hidden: true,
139
+ },
140
+ verbose: {
141
+ boolean: true,
142
+ describe: 'Print internal debugging information',
138
143
  hidden: true,
139
144
  },
140
145
  sendStatus: {
package/src/core/main.js CHANGED
@@ -163,6 +163,7 @@ const tExecBuild = async function ({
163
163
  baseRelDir,
164
164
  env: envOpt,
165
165
  debug,
166
+ verbose,
166
167
  nodePath,
167
168
  functionsDistDir,
168
169
  cacheDir,
@@ -273,6 +274,7 @@ const tExecBuild = async function ({
273
274
  errorParams,
274
275
  logs,
275
276
  debug,
277
+ verbose,
276
278
  timers: timersA,
277
279
  sendStatus,
278
280
  saveConfig,
@@ -321,6 +323,7 @@ const runAndReportBuild = async function ({
321
323
  errorParams,
322
324
  logs,
323
325
  debug,
326
+ verbose,
324
327
  timers,
325
328
  sendStatus,
326
329
  saveConfig,
@@ -360,6 +363,7 @@ const runAndReportBuild = async function ({
360
363
  errorParams,
361
364
  logs,
362
365
  debug,
366
+ verbose,
363
367
  timers,
364
368
  sendStatus,
365
369
  saveConfig,
@@ -451,6 +455,7 @@ const initAndRunBuild = async function ({
451
455
  errorParams,
452
456
  logs,
453
457
  debug,
458
+ verbose,
454
459
  sendStatus,
455
460
  saveConfig,
456
461
  timers,
@@ -521,6 +526,7 @@ const initAndRunBuild = async function ({
521
526
  errorParams,
522
527
  logs,
523
528
  debug,
529
+ verbose,
524
530
  saveConfig,
525
531
  timers: timersB,
526
532
  testOpts,
@@ -573,6 +579,7 @@ const runBuild = async function ({
573
579
  errorParams,
574
580
  logs,
575
581
  debug,
582
+ verbose,
576
583
  saveConfig,
577
584
  timers,
578
585
  testOpts,
@@ -583,7 +590,9 @@ const runBuild = async function ({
583
590
  childProcesses,
584
591
  packageJson,
585
592
  timers,
593
+ logs,
586
594
  debug,
595
+ verbose,
587
596
  })
588
597
 
589
598
  const { steps, events } = getSteps(pluginsSteps)
@@ -623,6 +632,7 @@ const runBuild = async function ({
623
632
  configOpts,
624
633
  logs,
625
634
  debug,
635
+ verbose,
626
636
  saveConfig,
627
637
  timers: timersA,
628
638
  testOpts,
@@ -41,6 +41,7 @@ const getDefaultFlags = function ({ env: envOpt = {} }, combinedEnv) {
41
41
  mode: REQUIRE_MODE,
42
42
  offline: false,
43
43
  telemetry: false,
44
+ verbose: Boolean(combinedEnv.NETLIFY_BUILD_DEBUG),
44
45
  functionsDistDir: DEFAULT_FUNCTIONS_DIST,
45
46
  cacheDir: DEFAULT_CACHE_DIR,
46
47
  deployId: combinedEnv.DEPLOY_ID,
@@ -0,0 +1,50 @@
1
+ 'use strict'
2
+
3
+ const { log } = require('../logger')
4
+
5
+ const logVerbose = function (logs, verbose, message) {
6
+ if (!verbose) {
7
+ return
8
+ }
9
+
10
+ log(logs, message)
11
+ }
12
+
13
+ const logSendingEventToChild = function (logs, verbose) {
14
+ logVerbose(logs, verbose, 'Step starting.')
15
+ }
16
+
17
+ const logSentEventToChild = function (logs, verbose) {
18
+ logVerbose(logs, verbose, 'Step started.')
19
+ }
20
+
21
+ const logPluginMethodStart = function (verbose) {
22
+ logVerbose(undefined, verbose, 'Plugin logic started.')
23
+ }
24
+
25
+ const logPluginMethodEnd = function (verbose) {
26
+ logVerbose(undefined, verbose, 'Plugin logic ended.')
27
+ }
28
+
29
+ const logSendingEventToParent = function (verbose, error) {
30
+ const message = error instanceof Error ? `Step erroring.\n${error.stack}` : 'Stop closing.'
31
+ logVerbose(undefined, verbose, message)
32
+ }
33
+
34
+ const logReceivedEventFromChild = function (logs, verbose) {
35
+ logVerbose(logs, verbose, 'Step ended.')
36
+ }
37
+
38
+ const logStepCompleted = function (logs, verbose) {
39
+ logVerbose(logs, verbose, 'Step completed.')
40
+ }
41
+
42
+ module.exports = {
43
+ logSendingEventToChild,
44
+ logSentEventToChild,
45
+ logPluginMethodStart,
46
+ logPluginMethodEnd,
47
+ logSendingEventToParent,
48
+ logReceivedEventFromChild,
49
+ logStepCompleted,
50
+ }
@@ -8,11 +8,11 @@ const { normalizeError } = require('../../error/parse/normalize')
8
8
  const { sendEventToParent } = require('../ipc')
9
9
 
10
10
  // Handle any top-level error and communicate it back to parent
11
- const handleError = async function (error) {
11
+ const handleError = async function (error, verbose) {
12
12
  const errorA = normalizeError(error)
13
13
  addDefaultErrorInfo(errorA, { type: 'pluginInternal' })
14
14
  const errorPayload = errorToJson(errorA)
15
- await sendEventToParent('error', errorPayload)
15
+ await sendEventToParent('error', errorPayload, verbose, errorA)
16
16
  }
17
17
 
18
18
  // On uncaught exceptions and unhandled rejections, print the stack trace.
@@ -11,7 +11,7 @@ const { validatePlugin } = require('./validate')
11
11
  // This also validates the plugin.
12
12
  // Do it when parent requests it using the `load` event.
13
13
  // Also figure out the list of plugin steps. This is also passed to the parent.
14
- const load = async function ({ pluginPath, inputs, packageJson }) {
14
+ const load = async function ({ pluginPath, inputs, packageJson, verbose }) {
15
15
  const tsNodeService = registerTypeScript(pluginPath)
16
16
  const logic = await getLogic({ pluginPath, inputs, tsNodeService })
17
17
 
@@ -21,7 +21,7 @@ const load = async function ({ pluginPath, inputs, packageJson }) {
21
21
  const events = Object.keys(methods)
22
22
 
23
23
  // Context passed to every event handler
24
- const context = { methods, inputs, packageJson }
24
+ const context = { methods, inputs, packageJson, verbose }
25
25
 
26
26
  return { events, context }
27
27
  }
@@ -9,33 +9,42 @@ const { run } = require('./run')
9
9
 
10
10
  // Boot plugin child process.
11
11
  const bootPlugin = async function () {
12
+ const state = { context: { verbose: false } }
13
+
12
14
  try {
13
15
  handleProcessErrors()
14
16
  setInspectColors()
15
17
 
16
- const state = {}
17
18
  // We need to fire them in parallel because `process.send()` can be slow
18
19
  // to await, i.e. parent might send `load` event before child `ready` event
19
20
  // returns.
20
- await Promise.all([handleEvents(state), sendEventToParent('ready')])
21
+ await Promise.all([handleEvents(state), sendEventToParent('ready', {}, false)])
21
22
  } catch (error) {
22
- await handleError(error)
23
+ await handleError(error, state.context.verbose)
23
24
  }
24
25
  }
25
26
 
26
27
  // Wait for events from parent to perform plugin methods
27
28
  const handleEvents = async function (state) {
28
- await getEventsFromParent((callId, eventName, payload) => handleEvent(callId, eventName, payload, state))
29
+ await getEventsFromParent((callId, eventName, payload) => handleEvent({ callId, eventName, payload, state }))
29
30
  }
30
31
 
31
32
  // Each event can pass `context` information to the next event
32
- const handleEvent = async function (callId, eventName, payload, state) {
33
+ const handleEvent = async function ({
34
+ callId,
35
+ eventName,
36
+ payload,
37
+ state,
38
+ state: {
39
+ context: { verbose },
40
+ },
41
+ }) {
33
42
  try {
34
43
  const { context, ...response } = await EVENTS[eventName](payload, state.context)
35
44
  state.context = { ...state.context, ...context }
36
- await sendEventToParent(callId, response)
45
+ await sendEventToParent(callId, response, verbose)
37
46
  } catch (error) {
38
- await handleError(error)
47
+ await handleError(error, verbose)
39
48
  }
40
49
  }
41
50
 
@@ -1,20 +1,28 @@
1
1
  'use strict'
2
2
 
3
3
  const { getNewEnvChanges, setEnvChanges } = require('../../env/changes')
4
+ const { logPluginMethodStart, logPluginMethodEnd } = require('../../log/messages/ipc')
4
5
 
5
6
  const { cloneNetlifyConfig, getConfigMutations } = require('./diff')
6
7
  const { getUtils } = require('./utils')
7
8
 
8
9
  // Run a specific plugin event handler
9
- const run = async function ({ event, error, constants, envChanges, netlifyConfig }, { methods, inputs, packageJson }) {
10
+ const run = async function (
11
+ { event, error, constants, envChanges, netlifyConfig },
12
+ { methods, inputs, packageJson, verbose },
13
+ ) {
10
14
  const method = methods[event]
11
15
  const runState = {}
12
- const utils = getUtils({ event, constants, runState })
16
+ const utils = await getUtils({ event, constants, runState })
13
17
  const netlifyConfigCopy = cloneNetlifyConfig(netlifyConfig)
14
18
  const runOptions = { utils, constants, inputs, netlifyConfig: netlifyConfigCopy, packageJson, error }
15
19
 
16
20
  const envBefore = setEnvChanges(envChanges)
21
+
22
+ logPluginMethodStart(verbose)
17
23
  await method(runOptions)
24
+ logPluginMethodEnd(verbose)
25
+
18
26
  const newEnvChanges = getNewEnvChanges(envBefore, netlifyConfig, netlifyConfigCopy)
19
27
 
20
28
  const configMutations = getConfigMutations(netlifyConfig, netlifyConfigCopy, event)
@@ -1,20 +1,29 @@
1
1
  'use strict'
2
2
 
3
+ const { bindOpts: cacheBindOpts } = require('@netlify/cache-utils')
4
+ const { add: functionsAdd, list: functionsList, listAll: functionsListAll } = require('@netlify/functions-utils')
5
+ const getGitUtils = require('@netlify/git-utils')
6
+
3
7
  const { failBuild, failPlugin, cancelBuild, failPluginWithWarning } = require('../error')
4
8
  const { isSoftFailEvent } = require('../events')
5
9
 
6
10
  const { addLazyProp } = require('./lazy')
7
11
  const { show } = require('./status')
8
12
 
13
+ const runUtilsPromise = import('@netlify/run-utils')
14
+
9
15
  // Retrieve the `utils` argument.
10
- const getUtils = function ({ event, constants: { FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC, CACHE_DIR }, runState }) {
16
+ const getUtils = async function ({ event, constants: { FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC, CACHE_DIR }, runState }) {
17
+ const { run, runCommand } = await runUtilsPromise
18
+ // eslint-disable-next-line fp/no-mutation
19
+ run.command = runCommand
20
+
11
21
  const build = getBuildUtils(event)
12
- const utils = { build }
13
- addLazyProp(utils, 'git', getGitUtils)
14
- addLazyProp(utils, 'cache', getCacheUtils.bind(null, CACHE_DIR))
15
- addLazyProp(utils, 'run', getRunUtils)
16
- addLazyProp(utils, 'functions', getFunctionsUtils.bind(null, FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC))
17
- addLazyProp(utils, 'status', getStatusUtils.bind(null, runState))
22
+ const cache = getCacheUtils(CACHE_DIR)
23
+ const functions = getFunctionsUtils(FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC)
24
+ const status = getStatusUtils(runState)
25
+ const utils = { build, cache, run, functions, status }
26
+ addLazyProp(utils, 'git', () => getGitUtils())
18
27
  return utils
19
28
  }
20
29
 
@@ -30,29 +39,15 @@ const getBuildUtils = function (event) {
30
39
  return { failBuild, failPlugin, cancelBuild }
31
40
  }
32
41
 
33
- const getGitUtils = function () {
34
- // eslint-disable-next-line node/global-require
35
- return require('@netlify/git-utils')()
36
- }
37
-
38
42
  const getCacheUtils = function (CACHE_DIR) {
39
- // eslint-disable-next-line node/global-require
40
- const cacheUtils = require('@netlify/cache-utils')
41
- return cacheUtils.bindOpts({ cacheDir: CACHE_DIR })
42
- }
43
-
44
- const getRunUtils = function () {
45
- // eslint-disable-next-line node/global-require
46
- return require('@netlify/run-utils')
43
+ return cacheBindOpts({ cacheDir: CACHE_DIR })
47
44
  }
48
45
 
49
46
  const getFunctionsUtils = function (FUNCTIONS_SRC, INTERNAL_FUNCTIONS_SRC) {
50
47
  const functionsDirectories = [INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC].filter(Boolean)
51
- // eslint-disable-next-line node/global-require
52
- const functionsUtils = require('@netlify/functions-utils')
53
- const add = (src) => functionsUtils.add(src, INTERNAL_FUNCTIONS_SRC, { fail: failBuild })
54
- const list = functionsUtils.list.bind(null, functionsDirectories, { fail: failBuild })
55
- const listAll = functionsUtils.listAll.bind(null, functionsDirectories, { fail: failBuild })
48
+ const add = (src) => functionsAdd(src, INTERNAL_FUNCTIONS_SRC, { fail: failBuild })
49
+ const list = functionsList.bind(null, functionsDirectories, { fail: failBuild })
50
+ const listAll = functionsListAll.bind(null, functionsDirectories, { fail: failBuild })
56
51
  return { add, list, listAll }
57
52
  }
58
53
 
@@ -8,16 +8,23 @@ const { v4: uuidv4 } = require('uuid')
8
8
 
9
9
  const { jsonToError, errorToJson } = require('../error/build')
10
10
  const { addErrorInfo } = require('../error/info')
11
+ const {
12
+ logSendingEventToChild,
13
+ logSentEventToChild,
14
+ logReceivedEventFromChild,
15
+ logSendingEventToParent,
16
+ } = require('../log/messages/ipc')
11
17
 
12
18
  // Send event from child to parent process then wait for response
13
19
  // We need to fire them in parallel because `process.send()` can be slow
14
20
  // to await, i.e. child might send response before parent start listening for it
15
- const callChild = async function (childProcess, eventName, payload) {
21
+ const callChild = async function ({ childProcess, eventName, payload, logs, verbose }) {
16
22
  const callId = uuidv4()
17
23
  const [response] = await Promise.all([
18
24
  getEventFromChild(childProcess, callId),
19
- sendEventToChild(childProcess, callId, eventName, payload),
25
+ sendEventToChild({ childProcess, callId, eventName, payload, logs, verbose }),
20
26
  ])
27
+ logReceivedEventFromChild(logs, verbose)
21
28
  return response
22
29
  }
23
30
 
@@ -84,9 +91,13 @@ Plugin methods should instead:
84
91
  - on failure: call utils.build.failPlugin() or utils.build.failBuild()`
85
92
 
86
93
  // Send event from parent to child process
87
- const sendEventToChild = async function (childProcess, callId, eventName, payload) {
94
+ const sendEventToChild = async function ({ childProcess, callId, eventName, payload, logs, verbose }) {
95
+ logSendingEventToChild(logs, verbose)
96
+
88
97
  const payloadA = serializePayload(payload)
89
98
  await promisify(childProcess.send.bind(childProcess))([callId, eventName, payloadA])
99
+
100
+ logSentEventToChild(logs, verbose)
90
101
  }
91
102
 
92
103
  // Respond to events from parent to child process.
@@ -109,7 +120,8 @@ const getEventsFromParent = function (callback) {
109
120
  }
110
121
 
111
122
  // Send event from child to parent process
112
- const sendEventToParent = async function (callId, payload) {
123
+ const sendEventToParent = async function (callId, payload, verbose, error) {
124
+ logSendingEventToParent(verbose, error)
113
125
  await promisify(process.send.bind(process))([callId, payload])
114
126
  }
115
127
 
@@ -8,16 +8,16 @@ const { callChild } = require('./ipc')
8
8
 
9
9
  // Retrieve all plugins steps
10
10
  // Can use either a module name or a file path to the plugin.
11
- const loadPlugins = async function ({ pluginsOptions, childProcesses, packageJson, timers, debug }) {
11
+ const loadPlugins = async function ({ pluginsOptions, childProcesses, packageJson, timers, logs, debug, verbose }) {
12
12
  return pluginsOptions.length === 0
13
13
  ? { pluginsSteps: [], timers }
14
- : await loadAllPlugins({ pluginsOptions, childProcesses, packageJson, timers, debug })
14
+ : await loadAllPlugins({ pluginsOptions, childProcesses, packageJson, timers, logs, debug, verbose })
15
15
  }
16
16
 
17
- const tLoadAllPlugins = async function ({ pluginsOptions, childProcesses, packageJson, debug }) {
17
+ const tLoadAllPlugins = async function ({ pluginsOptions, childProcesses, packageJson, logs, debug, verbose }) {
18
18
  const pluginsSteps = await Promise.all(
19
19
  pluginsOptions.map((pluginOptions, index) =>
20
- loadPlugin(pluginOptions, { childProcesses, index, packageJson, debug }),
20
+ loadPlugin(pluginOptions, { childProcesses, index, packageJson, logs, debug, verbose }),
21
21
  ),
22
22
  )
23
23
  const pluginsStepsA = pluginsSteps.flat()
@@ -31,13 +31,19 @@ const loadAllPlugins = measureDuration(tLoadAllPlugins, 'load_plugins')
31
31
  // Do it by executing the plugin `load` event handler.
32
32
  const loadPlugin = async function (
33
33
  { packageName, pluginPackageJson, pluginPackageJson: { version } = {}, pluginPath, inputs, loadedFrom, origin },
34
- { childProcesses, index, packageJson, debug },
34
+ { childProcesses, index, packageJson, logs, debug, verbose },
35
35
  ) {
36
36
  const { childProcess } = childProcesses[index]
37
37
  const loadEvent = 'load'
38
38
 
39
39
  try {
40
- const { events } = await callChild(childProcess, 'load', { pluginPath, inputs, packageJson })
40
+ const { events } = await callChild({
41
+ childProcess,
42
+ eventName: 'load',
43
+ payload: { pluginPath, inputs, packageJson, verbose },
44
+ logs,
45
+ verbose: false,
46
+ })
41
47
  const pluginSteps = events.map((event) => ({
42
48
  event,
43
49
  packageName,
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { addErrorInfo } = require('../error/info')
4
+ const { logStepCompleted } = require('../log/messages/ipc')
4
5
  const { pipePluginOutput, unpipePluginOutput } = require('../log/stream')
5
6
  const { callChild } = require('../plugins/ipc')
6
7
  const { getSuccessStatus } = require('../status/success')
@@ -28,6 +29,7 @@ const firePluginStep = async function ({
28
29
  error,
29
30
  logs,
30
31
  debug,
32
+ verbose,
31
33
  }) {
32
34
  const listeners = pipePluginOutput(childProcess, logs)
33
35
 
@@ -37,12 +39,12 @@ const firePluginStep = async function ({
37
39
  newEnvChanges,
38
40
  configMutations: newConfigMutations,
39
41
  status,
40
- } = await callChild(childProcess, 'run', {
41
- event,
42
- error,
43
- envChanges,
44
- netlifyConfig,
45
- constants,
42
+ } = await callChild({
43
+ childProcess,
44
+ eventName: 'run',
45
+ payload: { event, error, envChanges, netlifyConfig, constants },
46
+ logs,
47
+ verbose,
46
48
  })
47
49
  const {
48
50
  netlifyConfig: netlifyConfigA,
@@ -80,6 +82,7 @@ const firePluginStep = async function ({
80
82
  return { newError }
81
83
  } finally {
82
84
  await unpipePluginOutput(childProcess, logs, listeners)
85
+ logStepCompleted(logs, verbose)
83
86
  }
84
87
  }
85
88
 
@@ -50,6 +50,7 @@ const runStep = async function ({
50
50
  redirectsPath,
51
51
  logs,
52
52
  debug,
53
+ verbose,
53
54
  saveConfig,
54
55
  timers,
55
56
  testOpts,
@@ -110,6 +111,7 @@ const runStep = async function ({
110
111
  error,
111
112
  logs,
112
113
  debug,
114
+ verbose,
113
115
  saveConfig,
114
116
  timers,
115
117
  errorParams,
@@ -237,6 +239,7 @@ const tFireStep = function ({
237
239
  error,
238
240
  logs,
239
241
  debug,
242
+ verbose,
240
243
  saveConfig,
241
244
  errorParams,
242
245
  configOpts,
@@ -293,6 +296,7 @@ const tFireStep = function ({
293
296
  error,
294
297
  logs,
295
298
  debug,
299
+ verbose,
296
300
  })
297
301
  }
298
302
 
@@ -36,6 +36,7 @@ const runSteps = async function ({
36
36
  configOpts,
37
37
  logs,
38
38
  debug,
39
+ verbose,
39
40
  saveConfig,
40
41
  timers,
41
42
  testOpts,
@@ -128,6 +129,7 @@ const runSteps = async function ({
128
129
  redirectsPath: redirectsPathA,
129
130
  logs,
130
131
  debug,
132
+ verbose,
131
133
  saveConfig,
132
134
  timers: timersA,
133
135
  testOpts,