@netlify/build 28.0.0-beta → 28.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.
Files changed (258) hide show
  1. package/bin.js +5 -0
  2. package/lib/core/bin.js +66 -0
  3. package/lib/core/build.js +355 -0
  4. package/lib/core/config.js +121 -0
  5. package/lib/core/constants.js +116 -0
  6. package/lib/core/dev.js +27 -0
  7. package/lib/core/dry.js +21 -0
  8. package/lib/core/feature_flags.js +19 -0
  9. package/lib/core/flags.js +201 -0
  10. package/lib/core/lingering.js +68 -0
  11. package/lib/core/main.js +123 -0
  12. package/lib/core/missing_side_file.js +17 -0
  13. package/lib/core/normalize_flags.js +59 -0
  14. package/lib/core/severity.js +20 -0
  15. package/lib/core/user_node_version.js +32 -0
  16. package/lib/env/changes.js +43 -0
  17. package/lib/env/main.js +14 -0
  18. package/lib/env/metadata.js +68 -0
  19. package/lib/error/api.js +37 -0
  20. package/lib/error/build.js +36 -0
  21. package/{src → lib}/error/cancel.js +5 -6
  22. package/lib/error/colors.js +9 -0
  23. package/lib/error/handle.js +46 -0
  24. package/lib/error/info.js +37 -0
  25. package/lib/error/monitor/location.js +16 -0
  26. package/lib/error/monitor/normalize.js +86 -0
  27. package/lib/error/monitor/print.js +20 -0
  28. package/lib/error/monitor/report.js +120 -0
  29. package/lib/error/monitor/start.js +58 -0
  30. package/lib/error/parse/clean_stack.js +70 -0
  31. package/lib/error/parse/location.js +50 -0
  32. package/lib/error/parse/normalize.js +24 -0
  33. package/lib/error/parse/parse.js +67 -0
  34. package/lib/error/parse/plugin.js +55 -0
  35. package/lib/error/parse/properties.js +16 -0
  36. package/lib/error/parse/serialize_log.js +34 -0
  37. package/lib/error/parse/serialize_status.js +18 -0
  38. package/lib/error/parse/stack.js +34 -0
  39. package/lib/error/type.js +171 -0
  40. package/lib/install/functions.js +20 -0
  41. package/lib/install/local.js +45 -0
  42. package/lib/install/main.js +67 -0
  43. package/lib/install/missing.js +54 -0
  44. package/{src → lib}/log/colors.js +15 -22
  45. package/lib/log/description.js +21 -0
  46. package/lib/log/header.js +14 -0
  47. package/lib/log/header_func.js +13 -0
  48. package/lib/log/logger.js +130 -0
  49. package/lib/log/messages/compatibility.js +120 -0
  50. package/lib/log/messages/config.js +91 -0
  51. package/lib/log/messages/core.js +50 -0
  52. package/lib/log/messages/core_steps.js +75 -0
  53. package/lib/log/messages/dry.js +41 -0
  54. package/lib/log/messages/install.js +25 -0
  55. package/lib/log/messages/ipc.js +29 -0
  56. package/lib/log/messages/mutations.js +62 -0
  57. package/{src → lib}/log/messages/plugins.js +18 -32
  58. package/lib/log/messages/status.js +14 -0
  59. package/lib/log/messages/steps.js +18 -0
  60. package/lib/log/old_version.js +32 -0
  61. package/lib/log/serialize.js +10 -0
  62. package/lib/log/stream.js +68 -0
  63. package/lib/log/theme.js +25 -0
  64. package/lib/plugins/child/diff.js +46 -0
  65. package/lib/plugins/child/error.js +26 -0
  66. package/lib/plugins/child/lazy.js +15 -0
  67. package/lib/plugins/child/load.js +22 -0
  68. package/lib/plugins/child/logic.js +57 -0
  69. package/lib/plugins/child/main.js +37 -0
  70. package/lib/plugins/child/run.js +19 -0
  71. package/lib/plugins/child/status.js +63 -0
  72. package/lib/plugins/child/typescript.js +28 -0
  73. package/lib/plugins/child/utils.js +42 -0
  74. package/lib/plugins/child/validate.js +31 -0
  75. package/lib/plugins/compatibility.js +104 -0
  76. package/{src → lib}/plugins/error.js +31 -35
  77. package/{src → lib}/plugins/events.js +7 -12
  78. package/lib/plugins/expected_version.js +81 -0
  79. package/lib/plugins/ipc.js +120 -0
  80. package/lib/plugins/list.js +73 -0
  81. package/lib/plugins/load.js +50 -0
  82. package/lib/plugins/manifest/check.js +85 -0
  83. package/lib/plugins/manifest/load.js +38 -0
  84. package/lib/plugins/manifest/main.js +17 -0
  85. package/lib/plugins/manifest/path.js +24 -0
  86. package/lib/plugins/manifest/validate.js +91 -0
  87. package/lib/plugins/node_version.js +30 -0
  88. package/lib/plugins/options.js +55 -0
  89. package/lib/plugins/pinned_version.js +83 -0
  90. package/lib/plugins/resolve.js +110 -0
  91. package/lib/plugins/spawn.js +54 -0
  92. package/lib/plugins_core/add.js +35 -0
  93. package/lib/plugins_core/build_command.js +50 -0
  94. package/lib/plugins_core/deploy/buildbot_client.js +87 -0
  95. package/lib/plugins_core/deploy/index.js +49 -0
  96. package/{src → lib}/plugins_core/deploy/manifest.yml +0 -0
  97. package/lib/plugins_core/edge_functions/index.js +79 -0
  98. package/lib/plugins_core/edge_functions/lib/error.js +17 -0
  99. package/lib/plugins_core/edge_functions/lib/internal_manifest.js +50 -0
  100. package/lib/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +75 -0
  101. package/lib/plugins_core/functions/error.js +123 -0
  102. package/lib/plugins_core/functions/feature_flags.js +6 -0
  103. package/lib/plugins_core/functions/index.js +114 -0
  104. package/lib/plugins_core/functions/utils.js +45 -0
  105. package/lib/plugins_core/functions/zisi.js +39 -0
  106. package/{src → lib}/plugins_core/functions_install/index.js +8 -11
  107. package/{src → lib}/plugins_core/functions_install/manifest.yml +0 -0
  108. package/lib/plugins_core/list.js +20 -0
  109. package/lib/status/add.js +30 -0
  110. package/lib/status/colors.js +18 -0
  111. package/lib/status/load_error.js +10 -0
  112. package/lib/status/report.js +83 -0
  113. package/lib/status/success.js +14 -0
  114. package/lib/steps/core_step.js +57 -0
  115. package/lib/steps/error.js +65 -0
  116. package/lib/steps/get.js +43 -0
  117. package/lib/steps/plugin.js +55 -0
  118. package/lib/steps/return.js +25 -0
  119. package/lib/steps/run_core_steps.js +147 -0
  120. package/lib/steps/run_step.js +188 -0
  121. package/lib/steps/run_steps.js +96 -0
  122. package/lib/steps/update_config.js +66 -0
  123. package/lib/telemetry/main.js +97 -0
  124. package/lib/time/aggregate.js +120 -0
  125. package/lib/time/main.js +37 -0
  126. package/lib/time/measure.js +18 -0
  127. package/lib/time/report.js +47 -0
  128. package/lib/utils/errors.js +13 -0
  129. package/lib/utils/json.js +15 -0
  130. package/{src → lib}/utils/omit.js +3 -4
  131. package/lib/utils/package.js +22 -0
  132. package/lib/utils/remove_falsy.js +8 -0
  133. package/lib/utils/resolve.js +41 -0
  134. package/lib/utils/runtime.js +5 -0
  135. package/lib/utils/semver.js +28 -0
  136. package/package.json +39 -20
  137. package/types/config/netlify_config.d.ts +4 -4
  138. package/types/netlify_plugin_constants.d.ts +8 -8
  139. package/src/core/bin.js +0 -83
  140. package/src/core/config.js +0 -186
  141. package/src/core/constants.js +0 -156
  142. package/src/core/dry.js +0 -39
  143. package/src/core/feature_flags.js +0 -21
  144. package/src/core/flags.js +0 -194
  145. package/src/core/lingering.js +0 -85
  146. package/src/core/main.js +0 -692
  147. package/src/core/missing_side_file.js +0 -29
  148. package/src/core/normalize_flags.js +0 -69
  149. package/src/core/severity.js +0 -22
  150. package/src/core/user_node_version.js +0 -41
  151. package/src/env/changes.js +0 -52
  152. package/src/env/main.js +0 -19
  153. package/src/env/metadata.js +0 -81
  154. package/src/error/api.js +0 -46
  155. package/src/error/build.js +0 -50
  156. package/src/error/colors.js +0 -11
  157. package/src/error/handle.js +0 -57
  158. package/src/error/info.js +0 -46
  159. package/src/error/monitor/location.js +0 -21
  160. package/src/error/monitor/normalize.js +0 -77
  161. package/src/error/monitor/print.js +0 -42
  162. package/src/error/monitor/report.js +0 -133
  163. package/src/error/monitor/start.js +0 -69
  164. package/src/error/parse/clean_stack.js +0 -87
  165. package/src/error/parse/location.js +0 -58
  166. package/src/error/parse/normalize.js +0 -29
  167. package/src/error/parse/parse.js +0 -97
  168. package/src/error/parse/plugin.js +0 -70
  169. package/src/error/parse/properties.js +0 -23
  170. package/src/error/parse/serialize_log.js +0 -42
  171. package/src/error/parse/serialize_status.js +0 -23
  172. package/src/error/parse/stack.js +0 -43
  173. package/src/error/type.js +0 -182
  174. package/src/install/functions.js +0 -28
  175. package/src/install/local.js +0 -62
  176. package/src/install/main.js +0 -81
  177. package/src/install/missing.js +0 -67
  178. package/src/log/description.js +0 -26
  179. package/src/log/header.js +0 -16
  180. package/src/log/header_func.js +0 -17
  181. package/src/log/logger.js +0 -107
  182. package/src/log/messages/compatibility.js +0 -164
  183. package/src/log/messages/config.js +0 -105
  184. package/src/log/messages/core.js +0 -70
  185. package/src/log/messages/core_steps.js +0 -104
  186. package/src/log/messages/dry.js +0 -63
  187. package/src/log/messages/install.js +0 -20
  188. package/src/log/messages/ipc.js +0 -38
  189. package/src/log/messages/mutations.js +0 -82
  190. package/src/log/messages/status.js +0 -16
  191. package/src/log/messages/steps.js +0 -22
  192. package/src/log/old_version.js +0 -41
  193. package/src/log/serialize.js +0 -13
  194. package/src/log/stream.js +0 -85
  195. package/src/log/theme.js +0 -26
  196. package/src/plugins/child/diff.js +0 -55
  197. package/src/plugins/child/error.js +0 -32
  198. package/src/plugins/child/lazy.js +0 -18
  199. package/src/plugins/child/load.js +0 -29
  200. package/src/plugins/child/logic.js +0 -57
  201. package/src/plugins/child/main.js +0 -51
  202. package/src/plugins/child/run.js +0 -28
  203. package/src/plugins/child/status.js +0 -67
  204. package/src/plugins/child/typescript.js +0 -45
  205. package/src/plugins/child/utils.js +0 -56
  206. package/src/plugins/child/validate.js +0 -34
  207. package/src/plugins/compatibility.js +0 -128
  208. package/src/plugins/expected_version.js +0 -119
  209. package/src/plugins/ipc.js +0 -145
  210. package/src/plugins/list.js +0 -86
  211. package/src/plugins/load.js +0 -70
  212. package/src/plugins/manifest/check.js +0 -106
  213. package/src/plugins/manifest/load.js +0 -41
  214. package/src/plugins/manifest/main.js +0 -22
  215. package/src/plugins/manifest/path.js +0 -31
  216. package/src/plugins/manifest/validate.js +0 -108
  217. package/src/plugins/node_version.js +0 -50
  218. package/src/plugins/options.js +0 -88
  219. package/src/plugins/pinned_version.js +0 -131
  220. package/src/plugins/resolve.js +0 -152
  221. package/src/plugins/spawn.js +0 -66
  222. package/src/plugins_core/add.js +0 -49
  223. package/src/plugins_core/build_command.js +0 -75
  224. package/src/plugins_core/deploy/buildbot_client.js +0 -102
  225. package/src/plugins_core/deploy/index.js +0 -73
  226. package/src/plugins_core/edge_functions/index.js +0 -107
  227. package/src/plugins_core/edge_functions/lib/internal_manifest.js +0 -54
  228. package/src/plugins_core/functions/error.js +0 -163
  229. package/src/plugins_core/functions/feature_flags.js +0 -6
  230. package/src/plugins_core/functions/index.js +0 -160
  231. package/src/plugins_core/functions/utils.js +0 -66
  232. package/src/plugins_core/functions/zisi.js +0 -53
  233. package/src/plugins_core/list.js +0 -27
  234. package/src/status/add.js +0 -36
  235. package/src/status/colors.js +0 -23
  236. package/src/status/load_error.js +0 -11
  237. package/src/status/report.js +0 -128
  238. package/src/status/success.js +0 -18
  239. package/src/steps/core_step.js +0 -90
  240. package/src/steps/error.js +0 -102
  241. package/src/steps/get.js +0 -32
  242. package/src/steps/plugin.js +0 -85
  243. package/src/steps/return.js +0 -52
  244. package/src/steps/run_core_steps.js +0 -194
  245. package/src/steps/run_step.js +0 -300
  246. package/src/steps/run_steps.js +0 -179
  247. package/src/steps/update_config.js +0 -93
  248. package/src/telemetry/main.js +0 -136
  249. package/src/time/aggregate.js +0 -146
  250. package/src/time/main.js +0 -48
  251. package/src/time/measure.js +0 -22
  252. package/src/time/report.js +0 -59
  253. package/src/utils/errors.js +0 -12
  254. package/src/utils/json.js +0 -19
  255. package/src/utils/package.js +0 -23
  256. package/src/utils/remove_falsy.js +0 -10
  257. package/src/utils/resolve.js +0 -46
  258. package/src/utils/semver.js +0 -34
@@ -0,0 +1,39 @@
1
+ import { join, resolve } from 'path';
2
+ import mapObject from 'map-obj';
3
+ import { getZisiFeatureFlags } from './feature_flags.js';
4
+ export const getZisiParameters = ({ buildDir, childEnv, featureFlags, functionsConfig, functionsDist, internalFunctionsSrc, isRunningLocally, repositoryRoot, }) => {
5
+ const nodeVersion = childEnv.AWS_LAMBDA_JS_RUNTIME;
6
+ const manifest = join(functionsDist, 'manifest.json');
7
+ const config = mapObject(functionsConfig, (expression, object) => [
8
+ expression,
9
+ normalizeFunctionConfig({ buildDir, featureFlags, functionConfig: object, isRunningLocally, nodeVersion }),
10
+ ]);
11
+ const zisiFeatureFlags = getZisiFeatureFlags(featureFlags);
12
+ // Only internal functions are allowed to have a json config file
13
+ const configFileDirectories = [resolve(internalFunctionsSrc)];
14
+ return { basePath: buildDir, config, manifest, featureFlags: zisiFeatureFlags, repositoryRoot, configFileDirectories };
15
+ };
16
+ // The function configuration keys returned by @netlify/config are not an exact
17
+ // match to the properties that @netlify/zip-it-and-ship-it expects. We do that
18
+ // translation here.
19
+ export const normalizeFunctionConfig = ({ buildDir, functionConfig = {}, isRunningLocally, nodeVersion }) => ({
20
+ externalNodeModules: functionConfig.external_node_modules,
21
+ includedFiles: functionConfig.included_files,
22
+ includedFilesBasePath: buildDir,
23
+ ignoredNodeModules: functionConfig.ignored_node_modules,
24
+ nodeVersion,
25
+ schedule: functionConfig.schedule,
26
+ // When the user selects esbuild as the Node bundler, we still want to use
27
+ // the legacy ZISI bundler as a fallback. Rather than asking the user to
28
+ // make this decision, we abstract that complexity away by injecting the
29
+ // fallback behavior ourselves. We do this by transforming the value
30
+ // `esbuild` into `esbuild_zisi`, which zip-it-and-ship-it understands.
31
+ nodeBundler: functionConfig.node_bundler === 'esbuild' ? 'esbuild_zisi' : functionConfig.node_bundler,
32
+ // If the build is running in buildbot, we set the Rust target directory to a
33
+ // path that will get cached in between builds, allowing us to speed up the
34
+ // build process.
35
+ rustTargetDirectory: isRunningLocally ? undefined : resolve(buildDir, '.netlify', 'rust-functions-cache', '[name]'),
36
+ // Go functions should be zipped only when building locally. When running in
37
+ // buildbot, the Go API client will handle the zipping.
38
+ zipGo: isRunningLocally ? true : undefined,
39
+ });
@@ -1,13 +1,10 @@
1
- import { pathExists } from 'path-exists'
2
-
3
- import { installFunctionDependencies } from '../../install/functions.js'
4
-
1
+ import { pathExists } from 'path-exists';
2
+ import { installFunctionDependencies } from '../../install/functions.js';
5
3
  // Plugin to package Netlify functions with @netlify/zip-it-and-ship-it
6
4
  export const onPreBuild = async function ({ constants: { FUNCTIONS_SRC, IS_LOCAL } }) {
7
- if (!(await pathExists(FUNCTIONS_SRC))) {
8
- return {}
9
- }
10
-
11
- await installFunctionDependencies(FUNCTIONS_SRC, IS_LOCAL)
12
- return {}
13
- }
5
+ if (!(await pathExists(FUNCTIONS_SRC))) {
6
+ return {};
7
+ }
8
+ await installFunctionDependencies(FUNCTIONS_SRC, IS_LOCAL);
9
+ return {};
10
+ };
@@ -0,0 +1,20 @@
1
+ import { fileURLToPath } from 'url';
2
+ import { LOCAL_INSTALL_PLUGIN_NAME } from '../install/local.js';
3
+ const FUNCTIONS_INSTALL_PLUGIN = fileURLToPath(new URL('functions_install/index.js', import.meta.url));
4
+ // List of core plugin names
5
+ const FUNCTIONS_INSTALL_PLUGIN_NAME = '@netlify/plugin-functions-install-core';
6
+ const CORE_PLUGINS = new Set([FUNCTIONS_INSTALL_PLUGIN_NAME, LOCAL_INSTALL_PLUGIN_NAME]);
7
+ // Plugins that are installed and enabled by default
8
+ export const listCorePlugins = function ({ FUNCTIONS_SRC }) {
9
+ const functionsInstallPlugin = getFunctionsInstallPlugin(FUNCTIONS_SRC);
10
+ return [functionsInstallPlugin].filter(Boolean);
11
+ };
12
+ const getFunctionsInstallPlugin = function (FUNCTIONS_SRC) {
13
+ if (FUNCTIONS_SRC === undefined) {
14
+ return;
15
+ }
16
+ return { package: FUNCTIONS_INSTALL_PLUGIN_NAME, pluginPath: FUNCTIONS_INSTALL_PLUGIN, optional: true };
17
+ };
18
+ export const isCorePlugin = function (packageName) {
19
+ return CORE_PLUGINS.has(packageName);
20
+ };
@@ -0,0 +1,30 @@
1
+ // Merge plugin status to the list of plugin statuses.
2
+ export const addStatus = function ({ newStatus, statuses, event, packageName, pluginPackageJson: { version } = {} }) {
3
+ // Either:
4
+ // - `build.command`
5
+ // - no status was set
6
+ if (newStatus === undefined) {
7
+ return statuses;
8
+ }
9
+ const formerStatus = statuses.find((status) => status.packageName === packageName);
10
+ if (!canOverrideStatus(formerStatus, newStatus)) {
11
+ return statuses;
12
+ }
13
+ // Overrides plugin's previous status and add more information
14
+ const newStatuses = statuses.filter((status) => status !== formerStatus);
15
+ return [...newStatuses, { ...newStatus, event, packageName, version }];
16
+ };
17
+ const canOverrideStatus = function (formerStatus, newStatus) {
18
+ // No previous status
19
+ if (formerStatus === undefined) {
20
+ return true;
21
+ }
22
+ // Implicit statuses can never override
23
+ if (newStatus.implicit) {
24
+ return false;
25
+ }
26
+ // Error statuses can only be overwritten by more severe error statuses
27
+ return STATES.indexOf(formerStatus.state) <= STATES.indexOf(newStatus.state);
28
+ };
29
+ // Possible status states, ordered by severity.
30
+ const STATES = ['success', 'canceled_plugin', 'failed_plugin', 'failed_build'];
@@ -0,0 +1,18 @@
1
+ import stripAnsi from 'strip-ansi';
2
+ // Remove colors from statuses
3
+ export const removeStatusesColors = function (statuses) {
4
+ return statuses.map(removeStatusColors);
5
+ };
6
+ const removeStatusColors = function (status) {
7
+ const attributes = COLOR_ATTRIBUTES.map((attribute) => removeAttrColor(status, attribute));
8
+ return Object.assign({}, status, ...attributes);
9
+ };
10
+ const COLOR_ATTRIBUTES = ['title', 'summary', 'text'];
11
+ const removeAttrColor = function (status, attribute) {
12
+ const value = status[attribute];
13
+ if (value === undefined) {
14
+ return {};
15
+ }
16
+ const valueA = stripAnsi(value);
17
+ return { [attribute]: valueA };
18
+ };
@@ -0,0 +1,10 @@
1
+ import { addErrorInfo } from '../error/info.js';
2
+ import { getFullErrorInfo } from '../error/parse/parse.js';
3
+ import { serializeErrorStatus } from '../error/parse/serialize_status.js';
4
+ // Errors that happen during plugin loads should be reported as error statuses
5
+ export const addPluginLoadErrorStatus = function ({ error, packageName, version, debug }) {
6
+ const fullErrorInfo = getFullErrorInfo({ error, colors: false, debug });
7
+ const errorStatus = serializeErrorStatus({ fullErrorInfo, state: 'failed_build' });
8
+ const statuses = [{ ...errorStatus, event: 'load', packageName, version }];
9
+ addErrorInfo(error, { statuses });
10
+ };
@@ -0,0 +1,83 @@
1
+ import { handleBuildError } from '../error/handle.js';
2
+ import { logStatuses } from '../log/messages/status.js';
3
+ import { removeStatusesColors } from './colors.js';
4
+ // Report plugin statuses to the console and API
5
+ export const reportStatuses = async function ({ statuses, childEnv, api, mode, pluginsOptions, netlifyConfig, errorMonitor, deployId, logs, debug, sendStatus, testOpts, }) {
6
+ const finalStatuses = getFinalStatuses({ statuses, pluginsOptions });
7
+ if (finalStatuses.length === 0) {
8
+ return;
9
+ }
10
+ const statusesA = removeStatusesColors(finalStatuses);
11
+ printStatuses({ statuses: statusesA, mode, logs });
12
+ await sendApiStatuses({
13
+ statuses: statusesA,
14
+ childEnv,
15
+ api,
16
+ mode,
17
+ netlifyConfig,
18
+ errorMonitor,
19
+ deployId,
20
+ logs,
21
+ debug,
22
+ sendStatus,
23
+ testOpts,
24
+ });
25
+ };
26
+ // Some plugins might not have completed due to a build error.
27
+ // In that case, we add a dummy plugin run with state "skipped".
28
+ // This allows the API to know both plugins that have completed and only started
29
+ const getFinalStatuses = function ({ statuses = [], pluginsOptions }) {
30
+ return pluginsOptions.map(({ packageName }) => getPluginStatus(packageName, statuses));
31
+ };
32
+ const getPluginStatus = function (packageName, statuses) {
33
+ const pluginStatus = statuses.find((status) => status.packageName === packageName);
34
+ if (pluginStatus !== undefined) {
35
+ return pluginStatus;
36
+ }
37
+ return { packageName, state: 'skipped' };
38
+ };
39
+ // When not in production, print statuses to console.
40
+ // Only print successful ones, since errors are logged afterwards.
41
+ const printStatuses = function ({ statuses, mode, logs }) {
42
+ if (mode === 'buildbot') {
43
+ return;
44
+ }
45
+ const successStatuses = statuses.filter(shouldPrintStatus);
46
+ if (successStatuses.length === 0) {
47
+ return;
48
+ }
49
+ logStatuses(logs, successStatuses);
50
+ };
51
+ const shouldPrintStatus = function ({ state, summary }) {
52
+ return state === 'success' && summary !== undefined;
53
+ };
54
+ // In production, send statuses to the API
55
+ const sendApiStatuses = async function ({ statuses, childEnv, api, mode, netlifyConfig, errorMonitor, deployId, logs, debug, sendStatus, testOpts, }) {
56
+ if ((mode !== 'buildbot' && !sendStatus) || api === undefined || !deployId) {
57
+ return;
58
+ }
59
+ await Promise.all(statuses.map((status) => sendApiStatus({ api, status, childEnv, mode, netlifyConfig, errorMonitor, deployId, logs, debug, testOpts })));
60
+ };
61
+ const sendApiStatus = async function ({ api, status: { packageName, version, state, event, title, summary, text, extraData }, childEnv, mode, netlifyConfig, errorMonitor, deployId, logs, debug, testOpts, }) {
62
+ try {
63
+ await api.createPluginRun({
64
+ deploy_id: deployId,
65
+ body: {
66
+ package: packageName,
67
+ version,
68
+ state,
69
+ reporting_event: event,
70
+ title,
71
+ summary,
72
+ text,
73
+ extra_data: extraData,
74
+ },
75
+ });
76
+ // Bitballoon API randomly fails with 502.
77
+ // Builds should be successful when this API call fails, but we still want
78
+ // to report the error both in logs and in error monitoring.
79
+ }
80
+ catch (error) {
81
+ await handleBuildError(error, { errorMonitor, netlifyConfig, childEnv, mode, logs, debug, testOpts });
82
+ }
83
+ };
@@ -0,0 +1,14 @@
1
+ import { runsOnlyOnBuildFailure } from '../plugins/events.js';
2
+ // The last event handler of a plugin (except for `onError` and `onEnd`)
3
+ // defaults to `utils.status.show({ state: 'success' })` without any `summary`.
4
+ export const getSuccessStatus = function (newStatus, { steps, event, packageName }) {
5
+ if (newStatus === undefined && isLastNonErrorStep({ steps, event, packageName })) {
6
+ return IMPLICIT_STATUS;
7
+ }
8
+ return newStatus;
9
+ };
10
+ const isLastNonErrorStep = function ({ steps, event, packageName }) {
11
+ const nonErrorSteps = steps.filter((step) => step.packageName === packageName && !runsOnlyOnBuildFailure(step.event));
12
+ return nonErrorSteps.length === 0 || nonErrorSteps[nonErrorSteps.length - 1].event === event;
13
+ };
14
+ const IMPLICIT_STATUS = { state: 'success', implicit: true };
@@ -0,0 +1,57 @@
1
+ import { setEnvChanges } from '../env/changes.js';
2
+ import { addErrorInfo, isBuildError } from '../error/info.js';
3
+ import { updateNetlifyConfig, listConfigSideFiles } from './update_config.js';
4
+ // Fire a core step
5
+ export const fireCoreStep = async function ({ coreStep, coreStepName, configPath, buildDir, repositoryRoot, constants, buildbotServerSocket, events, logs, nodePath, childEnv, context, branch, envChanges, errorParams, configOpts, netlifyConfig, configMutations, headersPath, redirectsPath, featureFlags, debug, systemLog, saveConfig, }) {
6
+ try {
7
+ const configSideFiles = await listConfigSideFiles([headersPath, redirectsPath]);
8
+ const childEnvA = setEnvChanges(envChanges, { ...childEnv });
9
+ const { newEnvChanges = {}, configMutations: newConfigMutations = [], tags, } = await coreStep({
10
+ configPath,
11
+ buildDir,
12
+ repositoryRoot,
13
+ constants,
14
+ buildbotServerSocket,
15
+ events,
16
+ logs,
17
+ context,
18
+ branch,
19
+ childEnv: childEnvA,
20
+ netlifyConfig,
21
+ nodePath,
22
+ configMutations,
23
+ headersPath,
24
+ redirectsPath,
25
+ featureFlags,
26
+ debug,
27
+ systemLog,
28
+ saveConfig,
29
+ });
30
+ const { netlifyConfig: netlifyConfigA, configMutations: configMutationsA, headersPath: headersPathA, redirectsPath: redirectsPathA, } = await updateNetlifyConfig({
31
+ configOpts,
32
+ netlifyConfig,
33
+ headersPath,
34
+ redirectsPath,
35
+ configMutations,
36
+ newConfigMutations,
37
+ configSideFiles,
38
+ errorParams,
39
+ logs,
40
+ debug,
41
+ });
42
+ return {
43
+ newEnvChanges,
44
+ netlifyConfig: netlifyConfigA,
45
+ configMutations: configMutationsA,
46
+ headersPath: headersPathA,
47
+ redirectsPath: redirectsPathA,
48
+ tags,
49
+ };
50
+ }
51
+ catch (newError) {
52
+ if (!isBuildError(newError)) {
53
+ addErrorInfo(newError, { type: 'coreStep', location: { coreStepName } });
54
+ }
55
+ return { newError };
56
+ }
57
+ };
@@ -0,0 +1,65 @@
1
+ import { cancelBuild } from '../error/cancel.js';
2
+ import { handleBuildError } from '../error/handle.js';
3
+ import { getFullErrorInfo, parseErrorInfo } from '../error/parse/parse.js';
4
+ import { serializeErrorStatus } from '../error/parse/serialize_status.js';
5
+ import { isSoftFailEvent } from '../plugins/events.js';
6
+ // Handle build command errors and plugin errors:
7
+ // - usually, propagate the error to make the build stop.
8
+ // - `utils.build.cancelBuild()` also cancels the build by calling the API
9
+ // - `utils.build.failPlugin()` or post-deploy errors do not make the build
10
+ // stop, but are still reported, and prevent future events from the same
11
+ // plugin.
12
+ // This also computes error statuses that are sent to the API.
13
+ export const handleStepError = function ({ event, newError, childEnv, mode, api, errorMonitor, deployId, coreStep, netlifyConfig, logs, debug, testOpts, }) {
14
+ // Core steps do not report error statuses
15
+ if (coreStep !== undefined) {
16
+ return { newError };
17
+ }
18
+ const fullErrorInfo = getFullErrorInfo({ error: newError, colors: false, debug });
19
+ const { type } = fullErrorInfo;
20
+ if (type === 'failPlugin' || isSoftFailEvent(event)) {
21
+ return handleFailPlugin({
22
+ fullErrorInfo,
23
+ newError,
24
+ childEnv,
25
+ mode,
26
+ errorMonitor,
27
+ netlifyConfig,
28
+ logs,
29
+ debug,
30
+ testOpts,
31
+ });
32
+ }
33
+ if (type === 'cancelBuild') {
34
+ return handleCancelBuild({ fullErrorInfo, newError, api, deployId });
35
+ }
36
+ return handleFailBuild({ fullErrorInfo, newError });
37
+ };
38
+ // On `utils.build.failPlugin()` or during `onSuccess` or `onEnd`
39
+ const handleFailPlugin = async function ({ fullErrorInfo, fullErrorInfo: { errorInfo: { location: { packageName } = {} }, }, newError, childEnv, mode, errorMonitor, netlifyConfig, logs, debug, testOpts, }) {
40
+ const newStatus = serializeErrorStatus({ fullErrorInfo, state: 'failed_plugin' });
41
+ await handleBuildError(newError, { errorMonitor, netlifyConfig, childEnv, mode, logs, debug, testOpts });
42
+ return { failedPlugin: [packageName], newStatus };
43
+ };
44
+ // On `utils.build.cancelBuild()`
45
+ const handleCancelBuild = async function ({ fullErrorInfo, newError, api, deployId }) {
46
+ const newStatus = serializeErrorStatus({ fullErrorInfo, state: 'canceled_build' });
47
+ await cancelBuild({ api, deployId });
48
+ return { newError, newStatus };
49
+ };
50
+ // On `utils.build.failBuild()` or uncaught exception
51
+ const handleFailBuild = function ({ fullErrorInfo, newError }) {
52
+ const newStatus = serializeErrorStatus({ fullErrorInfo, state: 'failed_build' });
53
+ return { newError, newStatus };
54
+ };
55
+ // Unlike community plugins, core plugin bugs should be handled as system errors
56
+ export const getPluginErrorType = function (error, loadedFrom) {
57
+ if (!isCorePluginBug(error, loadedFrom)) {
58
+ return {};
59
+ }
60
+ return { type: 'corePlugin' };
61
+ };
62
+ const isCorePluginBug = function (error, loadedFrom) {
63
+ const { severity } = parseErrorInfo(error);
64
+ return severity === 'warning' && loadedFrom === 'core';
65
+ };
@@ -0,0 +1,43 @@
1
+ import { DEV_EVENTS, EVENTS } from '../plugins/events.js';
2
+ import { buildCommandCore } from '../plugins_core/build_command.js';
3
+ import { deploySite } from '../plugins_core/deploy/index.js';
4
+ import { bundleEdgeFunctions } from '../plugins_core/edge_functions/index.js';
5
+ import { bundleFunctions } from '../plugins_core/functions/index.js';
6
+ // Get all build steps
7
+ export const getSteps = function (steps) {
8
+ const stepsA = addCoreSteps(steps);
9
+ const stepsB = sortSteps(stepsA, EVENTS);
10
+ const events = getEvents(stepsB);
11
+ return { steps: stepsB, events };
12
+ };
13
+ // Get all dev steps
14
+ export const getDevSteps = function (command, steps) {
15
+ const devCommandStep = {
16
+ event: 'onDev',
17
+ coreStep: async () => {
18
+ await command();
19
+ return {};
20
+ },
21
+ coreStepId: 'dev_command',
22
+ coreStepName: 'dev.command',
23
+ coreStepDescription: () => 'Run command for local development',
24
+ };
25
+ const sortedSteps = sortSteps([...steps, devCommandStep], DEV_EVENTS);
26
+ const events = getEvents(sortedSteps);
27
+ return { steps: sortedSteps, events };
28
+ };
29
+ const addCoreSteps = function (steps) {
30
+ return [buildCommandCore, ...steps, bundleFunctions, bundleEdgeFunctions, deploySite];
31
+ };
32
+ // Sort plugin steps by event order.
33
+ const sortSteps = function (steps, events) {
34
+ return events.flatMap((event) => steps.filter((step) => step.event === event));
35
+ };
36
+ // Retrieve list of unique events
37
+ const getEvents = function (steps) {
38
+ const events = steps.map(getEvent);
39
+ return [...new Set(events)];
40
+ };
41
+ const getEvent = function ({ event }) {
42
+ return event;
43
+ };
@@ -0,0 +1,55 @@
1
+ import { addErrorInfo } from '../error/info.js';
2
+ import { logStepCompleted } from '../log/messages/ipc.js';
3
+ import { pipePluginOutput, unpipePluginOutput } from '../log/stream.js';
4
+ import { callChild } from '../plugins/ipc.js';
5
+ import { getSuccessStatus } from '../status/success.js';
6
+ import { getPluginErrorType } from './error.js';
7
+ import { updateNetlifyConfig, listConfigSideFiles } from './update_config.js';
8
+ // Fire a plugin step
9
+ export const firePluginStep = async function ({ event, childProcess, packageName, pluginPackageJson, loadedFrom, origin, envChanges, errorParams, configOpts, netlifyConfig, configMutations, headersPath, redirectsPath, constants, steps, error, logs, debug, verbose, }) {
10
+ const listeners = pipePluginOutput(childProcess, logs);
11
+ try {
12
+ const configSideFiles = await listConfigSideFiles([headersPath, redirectsPath]);
13
+ const { newEnvChanges, configMutations: newConfigMutations, status, } = await callChild({
14
+ childProcess,
15
+ eventName: 'run',
16
+ payload: { event, error, envChanges, netlifyConfig, constants },
17
+ logs,
18
+ verbose,
19
+ });
20
+ const { netlifyConfig: netlifyConfigA, configMutations: configMutationsA, headersPath: headersPathA, redirectsPath: redirectsPathA, } = await updateNetlifyConfig({
21
+ configOpts,
22
+ netlifyConfig,
23
+ headersPath,
24
+ redirectsPath,
25
+ configMutations,
26
+ newConfigMutations,
27
+ configSideFiles,
28
+ errorParams,
29
+ logs,
30
+ debug,
31
+ });
32
+ const newStatus = getSuccessStatus(status, { steps, event, packageName });
33
+ return {
34
+ newEnvChanges,
35
+ netlifyConfig: netlifyConfigA,
36
+ configMutations: configMutationsA,
37
+ headersPath: headersPathA,
38
+ redirectsPath: redirectsPathA,
39
+ newStatus,
40
+ };
41
+ }
42
+ catch (newError) {
43
+ const errorType = getPluginErrorType(newError, loadedFrom);
44
+ addErrorInfo(newError, {
45
+ ...errorType,
46
+ plugin: { pluginPackageJson, packageName },
47
+ location: { event, packageName, loadedFrom, origin },
48
+ });
49
+ return { newError };
50
+ }
51
+ finally {
52
+ await unpipePluginOutput(childProcess, logs, listeners);
53
+ logStepCompleted(logs, verbose);
54
+ }
55
+ };
@@ -0,0 +1,25 @@
1
+ import { logTimer } from '../log/messages/core.js';
2
+ import { logStepSuccess } from '../log/messages/steps.js';
3
+ import { handleStepError } from './error.js';
4
+ // Retrieve the return value of a step
5
+ export const getStepReturn = function ({ event, packageName, newError, newEnvChanges, newStatus, coreStep, coreStepName: timerName = `${packageName} ${event}`, childEnv, mode, api, errorMonitor, deployId, netlifyConfig, configMutations, headersPath, redirectsPath, logs, debug, timers, durationNs, testOpts, }) {
6
+ if (newError !== undefined) {
7
+ return handleStepError({
8
+ event,
9
+ newError,
10
+ childEnv,
11
+ mode,
12
+ api,
13
+ errorMonitor,
14
+ deployId,
15
+ coreStep,
16
+ netlifyConfig,
17
+ logs,
18
+ debug,
19
+ testOpts,
20
+ });
21
+ }
22
+ logStepSuccess(logs);
23
+ logTimer(logs, durationNs, timerName);
24
+ return { newEnvChanges, netlifyConfig, configMutations, headersPath, redirectsPath, newStatus, timers };
25
+ };
@@ -0,0 +1,147 @@
1
+ import { getConfigOpts, loadConfig } from '../core/config.js';
2
+ import { getConstants } from '../core/constants.js';
3
+ import { normalizeFlags } from '../core/normalize_flags.js';
4
+ import { getSeverity } from '../core/severity.js';
5
+ import { handleBuildError } from '../error/handle.js';
6
+ import { getErrorInfo } from '../error/info.js';
7
+ import { startErrorMonitor } from '../error/monitor/start.js';
8
+ import { getBufferLogs, getSystemLogger } from '../log/logger.js';
9
+ import { logBuildStart } from '../log/messages/core.js';
10
+ import { reportStatuses } from '../status/report.js';
11
+ import { getSteps } from './get.js';
12
+ import { runSteps } from './run_steps.js';
13
+ /**
14
+ * Runs specific core steps for a build and returns whether it succeeded or not.
15
+ *
16
+ * @param {string[]} [buildSteps] - a string array of build steps to run
17
+ * @param {object} [flags] - build configuration CLI flags
18
+ * @param {string} [flags.config] - Path to the configuration file
19
+ * @param {string} [flags.cwd] - Current directory. Used to retrieve the configuration file
20
+ * @param {string} [flags.repositoryRoot] - Git repository root directory. Used to retrieve the configuration file.
21
+ * @param {string} [flags.apiHost] - Netlify API endpoint
22
+ * @param {string} [flags.token] - Netlify API token for authentication
23
+ * @param {string} [flags.siteId] - Netlify Site ID
24
+ * @param {string} [flags.deployId] - Netlify Deploy ID
25
+ * @param {string} [flags.context] - Build context
26
+ * @param {string} [flags.branch] - Repository branch
27
+ * @param {boolean} [flags.dry=false] - Run in dry mode, i.e. printing steps without executing them
28
+ * @param {string} [flags.nodePath] - Path to the Node.js binary to use in the build command and plugins
29
+ * @param {boolean} [flags.buffer=false] - Buffer output instead of printing it
30
+ *
31
+ * @returns {object} buildResult
32
+ * @returns {boolean} buildResult.success - Whether build succeeded or failed
33
+ * @returns {number} buildResult.severityCode - Build success/failure status among:
34
+ * 0 (success), 1 (build cancelled), 2 (user error), 3 (plugin error), 4 (system error). Can be used as exit code.
35
+ * @returns {string[]} buildResult.logs - When using the `buffer` option, all log messages
36
+ */
37
+ export const runCoreSteps = async (buildSteps, flags = {}) => {
38
+ const { errorMonitor, mode, logs, debug, ...flagsA } = startBuild(flags);
39
+ const errorParams = { errorMonitor, mode, logs, debug };
40
+ const systemLog = getSystemLogger(logs, debug);
41
+ try {
42
+ const { netlifyConfig: netlifyConfigA, configMutations } = await executeBuildStep({
43
+ ...flagsA,
44
+ errorMonitor,
45
+ mode,
46
+ logs,
47
+ debug,
48
+ errorParams,
49
+ buildSteps,
50
+ systemLog,
51
+ });
52
+ const { success, severityCode } = getSeverity('success');
53
+ return { success, severityCode, netlifyConfig: netlifyConfigA, configMutations, logs };
54
+ }
55
+ catch (error) {
56
+ const { severity } = await handleBuildError(error, errorParams);
57
+ const { success, severityCode } = getSeverity(severity);
58
+ return { success, severityCode, logs };
59
+ }
60
+ };
61
+ const startBuild = function (flags) {
62
+ const logs = getBufferLogs(flags);
63
+ logBuildStart(logs);
64
+ const { bugsnagKey, ...flagsA } = normalizeFlags(flags, logs);
65
+ const errorMonitor = startErrorMonitor({ flags: flagsA, logs, bugsnagKey });
66
+ return { ...flagsA, errorMonitor, logs };
67
+ };
68
+ const getBuildSteps = function (buildSteps) {
69
+ const allSteps = getSteps([]).steps.filter(({ coreStepId }) => buildSteps.includes(coreStepId));
70
+ return allSteps;
71
+ };
72
+ const executeBuildStep = async function ({ config, defaultConfig, cachedConfig, debug, nodePath, functionsDistDir, edgeFunctionsDistDir, errorMonitor, mode, logs, errorParams, featureFlags, buildSteps, repositoryRoot, systemLog, }) {
73
+ const configOpts = getConfigOpts({
74
+ config,
75
+ defaultConfig,
76
+ featureFlags,
77
+ mode,
78
+ repositoryRoot,
79
+ });
80
+ const { netlifyConfig, buildDir, siteInfo, childEnv, userNodeVersion, repositoryRoot: repositoryRootA, } = await loadConfig({
81
+ configOpts,
82
+ cachedConfig,
83
+ debug,
84
+ logs,
85
+ nodePath,
86
+ timers: [],
87
+ });
88
+ const constants = await getConstants({
89
+ buildDir,
90
+ functionsDistDir,
91
+ edgeFunctionsDistDir,
92
+ netlifyConfig,
93
+ siteInfo,
94
+ mode,
95
+ });
96
+ Object.assign(errorParams, { netlifyConfig, siteInfo, childEnv, userNodeVersion });
97
+ try {
98
+ const { netlifyConfig: netlifyConfigA, configMutations } = await runBuildStep({
99
+ netlifyConfig,
100
+ buildDir,
101
+ nodePath,
102
+ logs,
103
+ debug,
104
+ constants,
105
+ featureFlags,
106
+ childEnv,
107
+ buildSteps,
108
+ repositoryRoot: repositoryRootA,
109
+ systemLog,
110
+ });
111
+ return {
112
+ netlifyConfig: netlifyConfigA,
113
+ configMutations,
114
+ };
115
+ }
116
+ catch (error) {
117
+ const [{ statuses }] = getErrorInfo(error);
118
+ await reportStatuses({
119
+ statuses,
120
+ childEnv,
121
+ mode,
122
+ netlifyConfig,
123
+ errorMonitor,
124
+ logs,
125
+ debug,
126
+ pluginsOptions: [],
127
+ });
128
+ throw error;
129
+ }
130
+ };
131
+ const runBuildStep = async function ({ netlifyConfig, buildDir, nodePath, constants, logs, debug, featureFlags, childEnv, buildSteps, repositoryRoot, systemLog, }) {
132
+ const { netlifyConfig: netlifyConfigA, configMutations } = await runSteps({
133
+ steps: getBuildSteps(buildSteps),
134
+ buildDir,
135
+ nodePath,
136
+ constants,
137
+ netlifyConfig,
138
+ logs,
139
+ debug,
140
+ timers: [],
141
+ featureFlags,
142
+ childEnv,
143
+ repositoryRoot,
144
+ systemLog,
145
+ });
146
+ return { netlifyConfig: netlifyConfigA, configMutations };
147
+ };