@netlify/build 28.0.1-beta → 29.0.0-rc

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": "28.0.1-beta",
3
+ "version": "29.0.0-rc",
4
4
  "description": "Netlify build module",
5
5
  "type": "module",
6
6
  "exports": "./src/core/main.js",
@@ -56,16 +56,18 @@
56
56
  "license": "MIT",
57
57
  "dependencies": {
58
58
  "@bugsnag/js": "^7.0.0",
59
- "@netlify/edge-bundler": "^1.4.2",
59
+ "@netlify/edge-bundler": "^1.12.1",
60
60
  "@netlify/cache-utils": "^4.0.0",
61
- "@netlify/config": "^18.1.1",
62
- "@netlify/functions-utils": "^4.2.0",
61
+ "@netlify/config": "^18.1.4",
62
+ "@netlify/functions-utils": "^4.2.3",
63
63
  "@netlify/git-utils": "^4.0.0",
64
- "@netlify/plugins-list": "^6.29.0",
64
+ "@netlify/plugins-list": "^6.36.0",
65
65
  "@netlify/run-utils": "^4.0.0",
66
- "@netlify/zip-it-and-ship-it": "6.0.1-beta",
66
+ "@netlify/zip-it-and-ship-it": "5.13.4",
67
67
  "@sindresorhus/slugify": "^2.0.0",
68
68
  "@types/node": "^16.0.0",
69
+ "ajv": "^8.11.0",
70
+ "ajv-errors": "^3.0.0",
69
71
  "ansi-escapes": "^5.0.0",
70
72
  "chalk": "^5.0.0",
71
73
  "clean-stack": "^4.0.0",
@@ -0,0 +1,554 @@
1
+ import { getErrorInfo } from '../error/info.js'
2
+ import { startErrorMonitor } from '../error/monitor/start.js'
3
+ import { getBufferLogs, getSystemLogger } from '../log/logger.js'
4
+ import { logBuildStart } from '../log/messages/core.js'
5
+ import { loadPlugins } from '../plugins/load.js'
6
+ import { getPluginsOptions } from '../plugins/options.js'
7
+ import { pinPlugins } from '../plugins/pinned_version.js'
8
+ import { startPlugins, stopPlugins } from '../plugins/spawn.js'
9
+ import { addCorePlugins } from '../plugins_core/add.js'
10
+ import { reportStatuses } from '../status/report.js'
11
+ import { getDevSteps, getSteps } from '../steps/get.js'
12
+ import { runSteps } from '../steps/run_steps.js'
13
+ import { initTimers, measureDuration } from '../time/main.js'
14
+
15
+ import { getConfigOpts, loadConfig } from './config.js'
16
+ import { getConstants } from './constants.js'
17
+ import { doDryRun } from './dry.js'
18
+ import { warnOnLingeringProcesses } from './lingering.js'
19
+ import { warnOnMissingSideFiles } from './missing_side_file.js'
20
+ import { normalizeFlags } from './normalize_flags.js'
21
+
22
+ // Performed on build start. Must be kept small and unlikely to fail since it
23
+ // does not have proper error handling. Error handling relies on `errorMonitor`
24
+ // being built, which relies itself on flags being normalized.
25
+ export const startBuild = function (flags) {
26
+ const timers = initTimers()
27
+
28
+ const logs = getBufferLogs(flags)
29
+ logBuildStart(logs)
30
+
31
+ const { bugsnagKey, ...flagsA } = normalizeFlags(flags, logs)
32
+ const errorMonitor = startErrorMonitor({ flags: flagsA, logs, bugsnagKey })
33
+
34
+ return { ...flagsA, errorMonitor, logs, timers }
35
+ }
36
+
37
+ const tExecBuild = async function ({
38
+ config,
39
+ defaultConfig,
40
+ cachedConfig,
41
+ cachedConfigPath,
42
+ cwd,
43
+ repositoryRoot,
44
+ apiHost,
45
+ token,
46
+ siteId,
47
+ context,
48
+ branch,
49
+ baseRelDir,
50
+ env: envOpt,
51
+ debug,
52
+ systemLogFile,
53
+ verbose,
54
+ nodePath,
55
+ functionsDistDir,
56
+ edgeFunctionsDistDir,
57
+ cacheDir,
58
+ dry,
59
+ mode,
60
+ offline,
61
+ deployId,
62
+ buildId,
63
+ testOpts,
64
+ errorMonitor,
65
+ errorParams,
66
+ logs,
67
+ timers,
68
+ buildbotServerSocket,
69
+ sendStatus,
70
+ saveConfig,
71
+ featureFlags,
72
+ timeline,
73
+ devCommand,
74
+ }) {
75
+ const configOpts = getConfigOpts({
76
+ config,
77
+ defaultConfig,
78
+ cwd,
79
+ repositoryRoot,
80
+ apiHost,
81
+ token,
82
+ siteId,
83
+ context,
84
+ branch,
85
+ baseRelDir,
86
+ envOpt,
87
+ mode,
88
+ offline,
89
+ deployId,
90
+ buildId,
91
+ testOpts,
92
+ featureFlags,
93
+ })
94
+ const {
95
+ netlifyConfig,
96
+ configPath,
97
+ headersPath,
98
+ redirectsPath,
99
+ buildDir,
100
+ repositoryRoot: repositoryRootA,
101
+ packageJson,
102
+ userNodeVersion,
103
+ childEnv,
104
+ context: contextA,
105
+ branch: branchA,
106
+ token: tokenA,
107
+ api,
108
+ siteInfo,
109
+ timers: timersA,
110
+ } = await loadConfig({
111
+ configOpts,
112
+ cachedConfig,
113
+ cachedConfigPath,
114
+ envOpt,
115
+ debug,
116
+ logs,
117
+ nodePath,
118
+ timers,
119
+ })
120
+ const constants = await getConstants({
121
+ configPath,
122
+ buildDir,
123
+ functionsDistDir,
124
+ edgeFunctionsDistDir,
125
+ cacheDir,
126
+ netlifyConfig,
127
+ siteInfo,
128
+ apiHost,
129
+ token: tokenA,
130
+ mode,
131
+ testOpts,
132
+ })
133
+ const systemLog = getSystemLogger(logs, debug, systemLogFile)
134
+ const pluginsOptions = addCorePlugins({ netlifyConfig, constants })
135
+ // `errorParams` is purposely stateful
136
+ // eslint-disable-next-line fp/no-mutating-assign
137
+ Object.assign(errorParams, { netlifyConfig, pluginsOptions, siteInfo, childEnv, userNodeVersion })
138
+
139
+ const {
140
+ pluginsOptions: pluginsOptionsA,
141
+ netlifyConfig: netlifyConfigA,
142
+ stepsCount,
143
+ timers: timersB,
144
+ configMutations,
145
+ } = await runAndReportBuild({
146
+ pluginsOptions,
147
+ netlifyConfig,
148
+ configOpts,
149
+ siteInfo,
150
+ configPath,
151
+ headersPath,
152
+ redirectsPath,
153
+ buildDir,
154
+ repositoryRoot: repositoryRootA,
155
+ nodePath,
156
+ packageJson,
157
+ userNodeVersion,
158
+ childEnv,
159
+ context: contextA,
160
+ branch: branchA,
161
+ dry,
162
+ mode,
163
+ api,
164
+ errorMonitor,
165
+ deployId,
166
+ errorParams,
167
+ logs,
168
+ debug,
169
+ systemLog,
170
+ verbose,
171
+ timers: timersA,
172
+ sendStatus,
173
+ saveConfig,
174
+ testOpts,
175
+ buildbotServerSocket,
176
+ constants,
177
+ featureFlags,
178
+ timeline,
179
+ devCommand,
180
+ })
181
+ return {
182
+ pluginsOptions: pluginsOptionsA,
183
+ netlifyConfig: netlifyConfigA,
184
+ siteInfo,
185
+ userNodeVersion,
186
+ stepsCount,
187
+ timers: timersB,
188
+ configMutations,
189
+ }
190
+ }
191
+
192
+ export const execBuild = measureDuration(tExecBuild, 'total', { parentTag: 'build_site' })
193
+
194
+ // Runs a build then report any plugin statuses
195
+ export const runAndReportBuild = async function ({
196
+ pluginsOptions,
197
+ netlifyConfig,
198
+ configOpts,
199
+ siteInfo,
200
+ configPath,
201
+ headersPath,
202
+ redirectsPath,
203
+ buildDir,
204
+ repositoryRoot,
205
+ nodePath,
206
+ packageJson,
207
+ userNodeVersion,
208
+ childEnv,
209
+ context,
210
+ branch,
211
+ buildbotServerSocket,
212
+ constants,
213
+ dry,
214
+ mode,
215
+ api,
216
+ errorMonitor,
217
+ deployId,
218
+ errorParams,
219
+ logs,
220
+ debug,
221
+ systemLog,
222
+ verbose,
223
+ timers,
224
+ sendStatus,
225
+ saveConfig,
226
+ testOpts,
227
+ featureFlags,
228
+ timeline,
229
+ devCommand,
230
+ }) {
231
+ try {
232
+ const {
233
+ stepsCount,
234
+ netlifyConfig: netlifyConfigA,
235
+ statuses,
236
+ pluginsOptions: pluginsOptionsA,
237
+ failedPlugins,
238
+ timers: timersA,
239
+ configMutations,
240
+ } = await initAndRunBuild({
241
+ pluginsOptions,
242
+ netlifyConfig,
243
+ configOpts,
244
+ siteInfo,
245
+ configPath,
246
+ headersPath,
247
+ redirectsPath,
248
+ buildDir,
249
+ repositoryRoot,
250
+ nodePath,
251
+ packageJson,
252
+ userNodeVersion,
253
+ childEnv,
254
+ context,
255
+ branch,
256
+ dry,
257
+ mode,
258
+ api,
259
+ errorMonitor,
260
+ deployId,
261
+ errorParams,
262
+ logs,
263
+ debug,
264
+ systemLog,
265
+ verbose,
266
+ timers,
267
+ sendStatus,
268
+ saveConfig,
269
+ testOpts,
270
+ buildbotServerSocket,
271
+ constants,
272
+ featureFlags,
273
+ timeline,
274
+ devCommand,
275
+ })
276
+ await Promise.all([
277
+ reportStatuses({
278
+ statuses,
279
+ childEnv,
280
+ api,
281
+ mode,
282
+ pluginsOptions: pluginsOptionsA,
283
+ netlifyConfig: netlifyConfigA,
284
+ errorMonitor,
285
+ deployId,
286
+ logs,
287
+ debug,
288
+ sendStatus,
289
+ testOpts,
290
+ }),
291
+ pinPlugins({
292
+ pluginsOptions: pluginsOptionsA,
293
+ failedPlugins,
294
+ api,
295
+ siteInfo,
296
+ childEnv,
297
+ mode,
298
+ netlifyConfig: netlifyConfigA,
299
+ errorMonitor,
300
+ logs,
301
+ debug,
302
+ testOpts,
303
+ sendStatus,
304
+ }),
305
+ ])
306
+
307
+ return {
308
+ pluginsOptions: pluginsOptionsA,
309
+ netlifyConfig: netlifyConfigA,
310
+ stepsCount,
311
+ timers: timersA,
312
+ configMutations,
313
+ }
314
+ } catch (error) {
315
+ const [{ statuses }] = getErrorInfo(error)
316
+ await reportStatuses({
317
+ statuses,
318
+ childEnv,
319
+ api,
320
+ mode,
321
+ pluginsOptions,
322
+ netlifyConfig,
323
+ errorMonitor,
324
+ deployId,
325
+ logs,
326
+ debug,
327
+ sendStatus,
328
+ testOpts,
329
+ })
330
+ throw error
331
+ }
332
+ }
333
+
334
+ // Initialize plugin processes then runs a build
335
+ const initAndRunBuild = async function ({
336
+ pluginsOptions,
337
+ netlifyConfig,
338
+ configOpts,
339
+ siteInfo,
340
+ configPath,
341
+ headersPath,
342
+ redirectsPath,
343
+ buildDir,
344
+ repositoryRoot,
345
+ nodePath,
346
+ packageJson,
347
+ userNodeVersion,
348
+ childEnv,
349
+ context,
350
+ branch,
351
+ dry,
352
+ mode,
353
+ api,
354
+ errorMonitor,
355
+ deployId,
356
+ errorParams,
357
+ logs,
358
+ debug,
359
+ systemLog,
360
+ verbose,
361
+ sendStatus,
362
+ saveConfig,
363
+ timers,
364
+ testOpts,
365
+ buildbotServerSocket,
366
+ constants,
367
+ featureFlags,
368
+ timeline,
369
+ devCommand,
370
+ }) {
371
+ const { pluginsOptions: pluginsOptionsA, timers: timersA } = await getPluginsOptions({
372
+ pluginsOptions,
373
+ netlifyConfig,
374
+ siteInfo,
375
+ buildDir,
376
+ nodePath,
377
+ packageJson,
378
+ userNodeVersion,
379
+ mode,
380
+ api,
381
+ logs,
382
+ debug,
383
+ sendStatus,
384
+ timers,
385
+ testOpts,
386
+ featureFlags,
387
+ })
388
+ // eslint-disable-next-line fp/no-mutation, no-param-reassign
389
+ errorParams.pluginsOptions = pluginsOptionsA
390
+
391
+ const { childProcesses, timers: timersB } = await startPlugins({
392
+ pluginsOptions: pluginsOptionsA,
393
+ buildDir,
394
+ childEnv,
395
+ logs,
396
+ debug,
397
+ timers: timersA,
398
+ })
399
+
400
+ try {
401
+ const {
402
+ stepsCount,
403
+ netlifyConfig: netlifyConfigA,
404
+ statuses,
405
+ failedPlugins,
406
+ timers: timersC,
407
+ configMutations,
408
+ } = await runBuild({
409
+ childProcesses,
410
+ pluginsOptions: pluginsOptionsA,
411
+ netlifyConfig,
412
+ configOpts,
413
+ packageJson,
414
+ configPath,
415
+ headersPath,
416
+ redirectsPath,
417
+ buildDir,
418
+ repositoryRoot,
419
+ nodePath,
420
+ childEnv,
421
+ context,
422
+ branch,
423
+ dry,
424
+ buildbotServerSocket,
425
+ constants,
426
+ mode,
427
+ api,
428
+ errorMonitor,
429
+ deployId,
430
+ errorParams,
431
+ logs,
432
+ debug,
433
+ systemLog,
434
+ verbose,
435
+ saveConfig,
436
+ timers: timersB,
437
+ testOpts,
438
+ featureFlags,
439
+ timeline,
440
+ devCommand,
441
+ })
442
+
443
+ await Promise.all([
444
+ warnOnMissingSideFiles({ buildDir, netlifyConfig: netlifyConfigA, logs }),
445
+ warnOnLingeringProcesses({ mode, logs, testOpts }),
446
+ ])
447
+
448
+ return {
449
+ stepsCount,
450
+ netlifyConfig: netlifyConfigA,
451
+ statuses,
452
+ pluginsOptions: pluginsOptionsA,
453
+ failedPlugins,
454
+ timers: timersC,
455
+ configMutations,
456
+ }
457
+ } finally {
458
+ stopPlugins(childProcesses)
459
+ }
460
+ }
461
+
462
+ // Load plugin main files, retrieve their event handlers then runs them,
463
+ // together with the build command
464
+ const runBuild = async function ({
465
+ childProcesses,
466
+ pluginsOptions,
467
+ netlifyConfig,
468
+ configOpts,
469
+ packageJson,
470
+ configPath,
471
+ headersPath,
472
+ redirectsPath,
473
+ buildDir,
474
+ repositoryRoot,
475
+ nodePath,
476
+ childEnv,
477
+ context,
478
+ branch,
479
+ dry,
480
+ buildbotServerSocket,
481
+ constants,
482
+ mode,
483
+ api,
484
+ errorMonitor,
485
+ deployId,
486
+ errorParams,
487
+ logs,
488
+ debug,
489
+ systemLog,
490
+ verbose,
491
+ saveConfig,
492
+ timers,
493
+ testOpts,
494
+ featureFlags,
495
+ timeline,
496
+ devCommand,
497
+ }) {
498
+ const { pluginsSteps, timers: timersA } = await loadPlugins({
499
+ pluginsOptions,
500
+ childProcesses,
501
+ packageJson,
502
+ timers,
503
+ logs,
504
+ debug,
505
+ verbose,
506
+ })
507
+
508
+ const { steps, events } = timeline === 'dev' ? getDevSteps(devCommand, pluginsSteps) : getSteps(pluginsSteps)
509
+
510
+ if (dry) {
511
+ await doDryRun({ buildDir, steps, netlifyConfig, constants, buildbotServerSocket, logs })
512
+ return { netlifyConfig }
513
+ }
514
+
515
+ const {
516
+ stepsCount,
517
+ netlifyConfig: netlifyConfigA,
518
+ statuses,
519
+ failedPlugins,
520
+ timers: timersB,
521
+ configMutations,
522
+ } = await runSteps({
523
+ steps,
524
+ buildbotServerSocket,
525
+ events,
526
+ configPath,
527
+ headersPath,
528
+ redirectsPath,
529
+ buildDir,
530
+ repositoryRoot,
531
+ nodePath,
532
+ childEnv,
533
+ context,
534
+ branch,
535
+ constants,
536
+ mode,
537
+ api,
538
+ errorMonitor,
539
+ deployId,
540
+ errorParams,
541
+ netlifyConfig,
542
+ configOpts,
543
+ logs,
544
+ debug,
545
+ systemLog,
546
+ verbose,
547
+ saveConfig,
548
+ timers: timersA,
549
+ testOpts,
550
+ featureFlags,
551
+ })
552
+
553
+ return { stepsCount, netlifyConfig: netlifyConfigA, statuses, failedPlugins, timers: timersB, configMutations }
554
+ }
@@ -0,0 +1,31 @@
1
+ import { handleBuildError } from '../error/handle.js'
2
+
3
+ import { execBuild, startBuild } from './build.js'
4
+ import { getSeverity } from './severity.js'
5
+
6
+ export const startDev = async (devCommand, flags = {}) => {
7
+ const { errorMonitor, mode, logs, debug, testOpts, ...normalizedFlags } = startBuild(flags)
8
+ const errorParams = { errorMonitor, mode, logs, debug, testOpts }
9
+
10
+ try {
11
+ const { netlifyConfig: netlifyConfigA, configMutations } = await execBuild({
12
+ ...normalizedFlags,
13
+ errorMonitor,
14
+ errorParams,
15
+ mode,
16
+ logs,
17
+ debug,
18
+ testOpts,
19
+ timeline: 'dev',
20
+ devCommand,
21
+ })
22
+ const { success, severityCode } = getSeverity('success')
23
+
24
+ return { success, severityCode, netlifyConfig: netlifyConfigA, logs, configMutations }
25
+ } catch (error) {
26
+ const { severity, message, stack } = await handleBuildError(error, errorParams)
27
+ const { success, severityCode } = getSeverity(severity)
28
+
29
+ return { success, severityCode, logs, error: { message, stack } }
30
+ }
31
+ }
@@ -18,4 +18,5 @@ export const DEFAULT_FEATURE_FLAGS = {
18
18
  buildbot_zisi_esbuild_parser: false,
19
19
  edge_functions_cache_cli: false,
20
20
  edge_functions_produce_eszip: false,
21
+ edge_functions_system_logger: false,
21
22
  }
package/src/core/flags.js CHANGED
@@ -145,6 +145,11 @@ Default: false`,
145
145
  describe: 'Print user-facing debugging information',
146
146
  hidden: true,
147
147
  },
148
+ systemLogFile: {
149
+ type: 'number',
150
+ describe: 'File descriptor to where system logs should be piped',
151
+ hidden: true,
152
+ },
148
153
  verbose: {
149
154
  boolean: true,
150
155
  describe: 'Print internal debugging information',
@@ -191,4 +196,9 @@ Default: false`,
191
196
  boolean: true,
192
197
  describe: 'Buffer output instead of printing it',
193
198
  },
199
+ timeline: {
200
+ string: true,
201
+ describe: 'The sequence of lifecycle events to run',
202
+ hidden: true,
203
+ },
194
204
  }