@netlify/build 29.0.0-rc → 29.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 (266) hide show
  1. package/bin.js +5 -0
  2. package/lib/core/bin.js +66 -0
  3. package/lib/core/build.js +356 -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 +21 -0
  9. package/lib/core/flags.js +201 -0
  10. package/lib/core/lingering.js +68 -0
  11. package/lib/core/main.js +110 -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 +21 -0
  15. package/lib/core/types.js +8 -0
  16. package/lib/core/user_node_version.js +32 -0
  17. package/lib/env/changes.js +43 -0
  18. package/lib/env/main.js +14 -0
  19. package/lib/env/metadata.js +68 -0
  20. package/lib/error/api.js +37 -0
  21. package/lib/error/build.js +36 -0
  22. package/{src → lib}/error/cancel.js +5 -6
  23. package/lib/error/colors.js +9 -0
  24. package/lib/error/handle.js +46 -0
  25. package/lib/error/info.js +37 -0
  26. package/lib/error/monitor/location.js +16 -0
  27. package/lib/error/monitor/normalize.js +86 -0
  28. package/lib/error/monitor/print.js +20 -0
  29. package/lib/error/monitor/report.js +120 -0
  30. package/lib/error/monitor/start.js +61 -0
  31. package/lib/error/parse/clean_stack.js +70 -0
  32. package/lib/error/parse/location.js +50 -0
  33. package/lib/error/parse/normalize.js +24 -0
  34. package/lib/error/parse/parse.js +67 -0
  35. package/lib/error/parse/plugin.js +55 -0
  36. package/lib/error/parse/properties.js +16 -0
  37. package/lib/error/parse/serialize_log.js +34 -0
  38. package/lib/error/parse/serialize_status.js +18 -0
  39. package/lib/error/parse/stack.js +34 -0
  40. package/lib/error/report.js +27 -0
  41. package/lib/error/type.js +177 -0
  42. package/lib/install/functions.js +20 -0
  43. package/lib/install/local.js +45 -0
  44. package/lib/install/main.js +67 -0
  45. package/lib/install/missing.js +54 -0
  46. package/lib/log/colors.js +28 -0
  47. package/lib/log/description.js +21 -0
  48. package/lib/log/header.js +14 -0
  49. package/lib/log/header_func.js +13 -0
  50. package/lib/log/logger.js +140 -0
  51. package/lib/log/messages/compatibility.js +146 -0
  52. package/lib/log/messages/config.js +91 -0
  53. package/lib/log/messages/core.js +51 -0
  54. package/lib/log/messages/core_steps.js +75 -0
  55. package/lib/log/messages/dry.js +41 -0
  56. package/lib/log/messages/install.js +25 -0
  57. package/lib/log/messages/ipc.js +29 -0
  58. package/lib/log/messages/mutations.js +62 -0
  59. package/{src → lib}/log/messages/plugins.js +18 -32
  60. package/lib/log/messages/status.js +14 -0
  61. package/lib/log/messages/steps.js +18 -0
  62. package/lib/log/old_version.js +32 -0
  63. package/lib/log/serialize.js +10 -0
  64. package/lib/log/stream.js +68 -0
  65. package/lib/log/theme.js +27 -0
  66. package/lib/plugins/child/diff.js +46 -0
  67. package/lib/plugins/child/error.js +26 -0
  68. package/lib/plugins/child/lazy.js +15 -0
  69. package/lib/plugins/child/load.js +22 -0
  70. package/lib/plugins/child/logic.js +57 -0
  71. package/lib/plugins/child/main.js +37 -0
  72. package/lib/plugins/child/run.js +19 -0
  73. package/lib/plugins/child/status.js +63 -0
  74. package/lib/plugins/child/typescript.js +28 -0
  75. package/lib/plugins/child/utils.js +42 -0
  76. package/lib/plugins/child/validate.js +31 -0
  77. package/lib/plugins/compatibility.js +104 -0
  78. package/{src → lib}/plugins/error.js +31 -35
  79. package/{src → lib}/plugins/events.js +7 -12
  80. package/lib/plugins/expected_version.js +81 -0
  81. package/lib/plugins/internal.js +10 -0
  82. package/lib/plugins/ipc.js +120 -0
  83. package/lib/plugins/list.js +73 -0
  84. package/lib/plugins/load.js +50 -0
  85. package/lib/plugins/manifest/check.js +85 -0
  86. package/lib/plugins/manifest/load.js +38 -0
  87. package/lib/plugins/manifest/main.js +19 -0
  88. package/lib/plugins/manifest/path.js +24 -0
  89. package/lib/plugins/manifest/validate.js +91 -0
  90. package/lib/plugins/node_version.js +35 -0
  91. package/lib/plugins/options.js +70 -0
  92. package/lib/plugins/pinned_version.js +83 -0
  93. package/lib/plugins/resolve.js +110 -0
  94. package/lib/plugins/spawn.js +58 -0
  95. package/lib/plugins_core/add.js +35 -0
  96. package/lib/plugins_core/build_command.js +50 -0
  97. package/lib/plugins_core/deploy/buildbot_client.js +87 -0
  98. package/lib/plugins_core/deploy/index.js +49 -0
  99. package/{src → lib}/plugins_core/deploy/manifest.yml +0 -0
  100. package/lib/plugins_core/edge_functions/index.js +76 -0
  101. package/{src → lib}/plugins_core/edge_functions/lib/error.js +13 -17
  102. package/lib/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +21 -0
  103. package/lib/plugins_core/functions/error.js +123 -0
  104. package/lib/plugins_core/functions/feature_flags.js +6 -0
  105. package/lib/plugins_core/functions/index.js +114 -0
  106. package/lib/plugins_core/functions/utils.js +45 -0
  107. package/lib/plugins_core/functions/zisi.js +39 -0
  108. package/{src → lib}/plugins_core/functions_install/index.js +8 -11
  109. package/{src → lib}/plugins_core/functions_install/manifest.yml +0 -0
  110. package/lib/plugins_core/list.js +20 -0
  111. package/lib/report/statsd.js +31 -0
  112. package/lib/status/add.js +30 -0
  113. package/lib/status/colors.js +18 -0
  114. package/lib/status/load_error.js +10 -0
  115. package/lib/status/report.js +83 -0
  116. package/lib/status/success.js +14 -0
  117. package/lib/steps/core_step.js +59 -0
  118. package/lib/steps/error.js +65 -0
  119. package/lib/steps/get.js +43 -0
  120. package/lib/steps/plugin.js +55 -0
  121. package/lib/steps/return.js +25 -0
  122. package/lib/steps/run_core_steps.js +117 -0
  123. package/lib/steps/run_step.js +190 -0
  124. package/lib/steps/run_steps.js +96 -0
  125. package/lib/steps/update_config.js +66 -0
  126. package/lib/telemetry/main.js +97 -0
  127. package/lib/time/aggregate.js +109 -0
  128. package/lib/time/main.js +31 -0
  129. package/lib/time/measure.js +16 -0
  130. package/lib/time/report.js +24 -0
  131. package/lib/utils/errors.js +13 -0
  132. package/lib/utils/json.js +15 -0
  133. package/lib/utils/omit.js +3 -0
  134. package/lib/utils/package.js +24 -0
  135. package/lib/utils/remove_falsy.js +8 -0
  136. package/lib/utils/resolve.js +41 -0
  137. package/lib/utils/runtime.js +5 -0
  138. package/lib/utils/semver.js +28 -0
  139. package/package.json +41 -24
  140. package/types/config/netlify_config.d.ts +4 -4
  141. package/types/netlify_plugin_constants.d.ts +8 -8
  142. package/src/core/bin.js +0 -83
  143. package/src/core/build.js +0 -554
  144. package/src/core/config.js +0 -186
  145. package/src/core/constants.js +0 -156
  146. package/src/core/dev.js +0 -31
  147. package/src/core/dry.js +0 -39
  148. package/src/core/feature_flags.js +0 -22
  149. package/src/core/flags.js +0 -204
  150. package/src/core/lingering.js +0 -85
  151. package/src/core/main.js +0 -165
  152. package/src/core/missing_side_file.js +0 -29
  153. package/src/core/normalize_flags.js +0 -70
  154. package/src/core/severity.js +0 -22
  155. package/src/core/user_node_version.js +0 -41
  156. package/src/env/changes.js +0 -52
  157. package/src/env/main.js +0 -19
  158. package/src/env/metadata.js +0 -81
  159. package/src/error/api.js +0 -46
  160. package/src/error/build.js +0 -50
  161. package/src/error/colors.js +0 -11
  162. package/src/error/handle.js +0 -57
  163. package/src/error/info.js +0 -46
  164. package/src/error/monitor/location.js +0 -21
  165. package/src/error/monitor/normalize.js +0 -96
  166. package/src/error/monitor/print.js +0 -42
  167. package/src/error/monitor/report.js +0 -138
  168. package/src/error/monitor/start.js +0 -69
  169. package/src/error/parse/clean_stack.js +0 -87
  170. package/src/error/parse/location.js +0 -62
  171. package/src/error/parse/normalize.js +0 -29
  172. package/src/error/parse/parse.js +0 -97
  173. package/src/error/parse/plugin.js +0 -70
  174. package/src/error/parse/properties.js +0 -23
  175. package/src/error/parse/serialize_log.js +0 -42
  176. package/src/error/parse/serialize_status.js +0 -23
  177. package/src/error/parse/stack.js +0 -43
  178. package/src/error/type.js +0 -189
  179. package/src/install/functions.js +0 -28
  180. package/src/install/local.js +0 -62
  181. package/src/install/main.js +0 -81
  182. package/src/install/missing.js +0 -67
  183. package/src/log/colors.js +0 -34
  184. package/src/log/description.js +0 -26
  185. package/src/log/header.js +0 -16
  186. package/src/log/header_func.js +0 -17
  187. package/src/log/logger.js +0 -161
  188. package/src/log/messages/compatibility.js +0 -164
  189. package/src/log/messages/config.js +0 -107
  190. package/src/log/messages/core.js +0 -70
  191. package/src/log/messages/core_steps.js +0 -104
  192. package/src/log/messages/dry.js +0 -63
  193. package/src/log/messages/install.js +0 -20
  194. package/src/log/messages/ipc.js +0 -38
  195. package/src/log/messages/mutations.js +0 -82
  196. package/src/log/messages/status.js +0 -16
  197. package/src/log/messages/steps.js +0 -22
  198. package/src/log/old_version.js +0 -41
  199. package/src/log/serialize.js +0 -13
  200. package/src/log/stream.js +0 -85
  201. package/src/log/theme.js +0 -26
  202. package/src/plugins/child/diff.js +0 -55
  203. package/src/plugins/child/error.js +0 -32
  204. package/src/plugins/child/lazy.js +0 -18
  205. package/src/plugins/child/load.js +0 -29
  206. package/src/plugins/child/logic.js +0 -57
  207. package/src/plugins/child/main.js +0 -51
  208. package/src/plugins/child/run.js +0 -28
  209. package/src/plugins/child/status.js +0 -74
  210. package/src/plugins/child/typescript.js +0 -45
  211. package/src/plugins/child/utils.js +0 -56
  212. package/src/plugins/child/validate.js +0 -34
  213. package/src/plugins/compatibility.js +0 -128
  214. package/src/plugins/expected_version.js +0 -119
  215. package/src/plugins/ipc.js +0 -145
  216. package/src/plugins/list.js +0 -86
  217. package/src/plugins/load.js +0 -70
  218. package/src/plugins/manifest/check.js +0 -106
  219. package/src/plugins/manifest/load.js +0 -41
  220. package/src/plugins/manifest/main.js +0 -22
  221. package/src/plugins/manifest/path.js +0 -31
  222. package/src/plugins/manifest/validate.js +0 -108
  223. package/src/plugins/node_version.js +0 -50
  224. package/src/plugins/options.js +0 -88
  225. package/src/plugins/pinned_version.js +0 -131
  226. package/src/plugins/resolve.js +0 -152
  227. package/src/plugins/spawn.js +0 -66
  228. package/src/plugins_core/add.js +0 -49
  229. package/src/plugins_core/build_command.js +0 -75
  230. package/src/plugins_core/deploy/buildbot_client.js +0 -102
  231. package/src/plugins_core/deploy/index.js +0 -73
  232. package/src/plugins_core/edge_functions/index.js +0 -123
  233. package/src/plugins_core/edge_functions/lib/internal_manifest.js +0 -54
  234. package/src/plugins_core/edge_functions/validate_manifest/validate_edge_functions_manifest.js +0 -89
  235. package/src/plugins_core/functions/error.js +0 -163
  236. package/src/plugins_core/functions/feature_flags.js +0 -6
  237. package/src/plugins_core/functions/index.js +0 -160
  238. package/src/plugins_core/functions/utils.js +0 -66
  239. package/src/plugins_core/functions/zisi.js +0 -53
  240. package/src/plugins_core/list.js +0 -27
  241. package/src/status/add.js +0 -36
  242. package/src/status/colors.js +0 -23
  243. package/src/status/load_error.js +0 -11
  244. package/src/status/report.js +0 -137
  245. package/src/status/success.js +0 -18
  246. package/src/steps/core_step.js +0 -92
  247. package/src/steps/error.js +0 -102
  248. package/src/steps/get.js +0 -51
  249. package/src/steps/plugin.js +0 -85
  250. package/src/steps/return.js +0 -52
  251. package/src/steps/run_core_steps.js +0 -200
  252. package/src/steps/run_step.js +0 -304
  253. package/src/steps/run_steps.js +0 -179
  254. package/src/steps/update_config.js +0 -93
  255. package/src/telemetry/main.js +0 -136
  256. package/src/time/aggregate.js +0 -146
  257. package/src/time/main.js +0 -48
  258. package/src/time/measure.js +0 -22
  259. package/src/time/report.js +0 -59
  260. package/src/utils/errors.js +0 -12
  261. package/src/utils/json.js +0 -19
  262. package/src/utils/omit.js +0 -6
  263. package/src/utils/package.js +0 -23
  264. package/src/utils/remove_falsy.js +0 -10
  265. package/src/utils/resolve.js +0 -46
  266. package/src/utils/semver.js +0 -34
@@ -0,0 +1,21 @@
1
+ import pFilter from 'p-filter';
2
+ import { logDryRunStart, logDryRunStep, logDryRunEnd } from '../log/messages/dry.js';
3
+ import { runsOnlyOnBuildFailure } from '../plugins/events.js';
4
+ // If the `dry` flag is specified, do a dry run
5
+ export const doDryRun = async function ({ buildDir, steps, netlifyConfig, constants, buildbotServerSocket, logs }) {
6
+ const successSteps = await pFilter(steps, ({ event, condition }) => shouldIncludeStep({ buildDir, event, condition, netlifyConfig, constants, buildbotServerSocket }));
7
+ const eventWidth = Math.max(...successSteps.map(getEventLength));
8
+ const stepsCount = successSteps.length;
9
+ logDryRunStart({ logs, eventWidth, stepsCount });
10
+ successSteps.forEach((step, index) => {
11
+ logDryRunStep({ logs, step, index, netlifyConfig, eventWidth, stepsCount });
12
+ });
13
+ logDryRunEnd(logs);
14
+ };
15
+ const shouldIncludeStep = async function ({ buildDir, event, condition, netlifyConfig, constants, buildbotServerSocket, }) {
16
+ return (!runsOnlyOnBuildFailure(event) &&
17
+ (condition === undefined || (await condition({ buildDir, constants, netlifyConfig, buildbotServerSocket }))));
18
+ };
19
+ const getEventLength = function ({ event }) {
20
+ return event.length;
21
+ };
@@ -0,0 +1,21 @@
1
+ // From CLI `--featureFlags=a,b,c` to programmatic `{ a: true, b: true, c: true }`
2
+ export const normalizeCliFeatureFlags = function (cliFeatureFlags) {
3
+ return Object.assign({}, ...cliFeatureFlags.split(',').filter(isNotEmpty).map(getFeatureFlag));
4
+ };
5
+ const isNotEmpty = function (name) {
6
+ return name.trim() !== '';
7
+ };
8
+ const getFeatureFlag = function (name) {
9
+ return { [name]: true };
10
+ };
11
+ // Default values for feature flags
12
+ export const DEFAULT_FEATURE_FLAGS = {
13
+ buildbot_es_modules_esbuild: false,
14
+ buildbot_zisi_trace_nft: false,
15
+ buildbot_zisi_esbuild_parser: false,
16
+ edge_functions_cache_cli: false,
17
+ edge_functions_system_logger: false,
18
+ // TODO: remove this flag once rolled out to everyone
19
+ // FF link: https://app.launchdarkly.com/default/production/features/plugins_break_builds_with_unsupported_plugin_versions/targeting
20
+ plugins_break_builds_with_unsupported_plugin_versions: false,
21
+ };
@@ -0,0 +1,201 @@
1
+ const jsonParse = function (value) {
2
+ return value === undefined ? undefined : JSON.parse(value);
3
+ };
4
+ // All CLI flags
5
+ export const FLAGS = {
6
+ config: {
7
+ string: true,
8
+ describe: `Path to the configuration file.
9
+ Defaults to any netlify.toml in the git repository root directory or the base directory`,
10
+ },
11
+ defaultConfig: {
12
+ string: true,
13
+ describe: `JSON configuration object containing default values.
14
+ Each configuration default value is used unless overriden through the main configuration file.
15
+ Default: none.`,
16
+ coerce: jsonParse,
17
+ hidden: true,
18
+ },
19
+ cachedConfig: {
20
+ string: true,
21
+ describe: `JSON configuration object returned by @netlify/config when --output=/ is used
22
+ or when using @netlify/config programmatically.
23
+ This is done as a performance optimization to cache the configuration loading logic.
24
+ Default: none.`,
25
+ coerce: jsonParse,
26
+ hidden: true,
27
+ },
28
+ cachedConfigPath: {
29
+ string: true,
30
+ describe: `File path to the JSON configuration object returned by @netlify/config
31
+ when --output=/path is used.
32
+ This is done as a performance optimization to cache the configuration loading logic.
33
+ Default: none.`,
34
+ hidden: true,
35
+ },
36
+ cwd: {
37
+ string: true,
38
+ describe: `Current directory. Used to retrieve the configuration file.
39
+ Default: current directory`,
40
+ },
41
+ repositoryRoot: {
42
+ string: true,
43
+ describe: `Git repository root directory. Used to retrieve the configuration file.
44
+ Default: automatically guessed`,
45
+ },
46
+ apiHost: {
47
+ string: true,
48
+ describe: `Netlify API endpoint.
49
+ Default: automatically guessed`,
50
+ },
51
+ token: {
52
+ string: true,
53
+ describe: `Netlify API token for authentication.
54
+ The NETLIFY_AUTH_TOKEN environment variable can be used as well.`,
55
+ },
56
+ siteId: {
57
+ string: true,
58
+ describe: `Netlify Site ID.`,
59
+ },
60
+ deployId: {
61
+ string: true,
62
+ describe: `Netlify Deploy ID.
63
+ Default: automatically guessed`,
64
+ },
65
+ buildId: {
66
+ string: true,
67
+ describe: `Netlify Build ID.
68
+ Default: automatically guessed`,
69
+ },
70
+ context: {
71
+ string: true,
72
+ describe: `Build context.
73
+ Default: 'production'`,
74
+ },
75
+ branch: {
76
+ string: true,
77
+ describe: `Repository branch.
78
+ Default: automatically guessed`,
79
+ },
80
+ framework: {
81
+ string: true,
82
+ describe: 'Front-end framework.',
83
+ hidden: true,
84
+ },
85
+ baseRelDir: {
86
+ boolean: true,
87
+ describe: `Feature flag meant for backward compatibility.
88
+ When enabled, if the 'build.base' configuration property is defined, it is used
89
+ to try to retrieve a second configuration file and discard the first one.
90
+ Default: true`,
91
+ hidden: true,
92
+ },
93
+ dry: {
94
+ alias: 'dry-run',
95
+ boolean: true,
96
+ describe: `Run in dry mode, i.e. printing steps without executing them.
97
+ Default: false`,
98
+ },
99
+ nodePath: {
100
+ string: true,
101
+ describe: `Path to the Node.js binary to use in the build command and plugins.
102
+ Default: Current Node.js binary`,
103
+ },
104
+ functionsDistDir: {
105
+ string: true,
106
+ describe: `Path to the directory where packaged functions are kept.
107
+ Default: automatically guessed`,
108
+ hidden: true,
109
+ },
110
+ edgeFunctionsDistDir: {
111
+ string: true,
112
+ describe: `Path to the directory where packaged Edge Functions are kept.
113
+ Default: automatically guessed`,
114
+ hidden: true,
115
+ },
116
+ cacheDir: {
117
+ string: true,
118
+ describe: `Path to the cache directory.
119
+ Default: .netlify/cache/`,
120
+ hidden: true,
121
+ },
122
+ buildbotServerSocket: {
123
+ string: true,
124
+ describe: `Path to the buildbot server socket. This is used to connect to the buildbot to trigger deploys.`,
125
+ hidden: true,
126
+ },
127
+ telemetry: {
128
+ boolean: true,
129
+ describe: `Enable telemetry.
130
+ Default: false`,
131
+ },
132
+ mode: {
133
+ string: true,
134
+ describe: `Environment in which this is loaded. Can be:
135
+ - 'buildbot': within Netlify Buildbot
136
+ - 'cli': within Netlify CLI
137
+ - 'require': through import('@netlify/build')`,
138
+ hidden: true,
139
+ },
140
+ debug: {
141
+ boolean: true,
142
+ describe: 'Print user-facing debugging information',
143
+ hidden: true,
144
+ },
145
+ systemLogFile: {
146
+ type: 'number',
147
+ describe: 'File descriptor to where system logs should be piped',
148
+ hidden: true,
149
+ },
150
+ verbose: {
151
+ boolean: true,
152
+ describe: 'Print internal debugging information',
153
+ hidden: true,
154
+ },
155
+ sendStatus: {
156
+ boolean: true,
157
+ describe: 'Whether plugin statuses should be sent to the Netlify API',
158
+ hidden: true,
159
+ },
160
+ saveConfig: {
161
+ boolean: true,
162
+ describe: 'Whether configuration changes should be saved to netlify.toml',
163
+ hidden: true,
164
+ },
165
+ testOpts: {
166
+ describe: 'Options for testing only',
167
+ hidden: true,
168
+ },
169
+ featureFlags: {
170
+ describe: 'Comma-separated list of feature flags to enable unreleased features',
171
+ hidden: true,
172
+ },
173
+ statsd: {
174
+ describe: 'Statsd-related options, for performance measuring',
175
+ hidden: true,
176
+ },
177
+ 'statsd.host': {
178
+ type: 'string',
179
+ describe: 'Statsd host',
180
+ hidden: true,
181
+ },
182
+ 'statsd.port': {
183
+ type: 'number',
184
+ describe: 'Statsd port',
185
+ hidden: true,
186
+ },
187
+ offline: {
188
+ boolean: true,
189
+ describe: `Do not send requests to the Netlify API to retrieve site settings.
190
+ Default: false`,
191
+ },
192
+ buffer: {
193
+ boolean: true,
194
+ describe: 'Buffer output instead of printing it',
195
+ },
196
+ timeline: {
197
+ string: true,
198
+ describe: 'The sequence of lifecycle events to run',
199
+ hidden: true,
200
+ },
201
+ };
@@ -0,0 +1,68 @@
1
+ import psList from 'ps-list';
2
+ import { logLingeringProcesses } from '../log/messages/core.js';
3
+ // Print a warning when some build processes are still running.
4
+ // We cannot rely on using the process tree:
5
+ // - This is because it is impossible to know whether a process was a child of
6
+ // of another once its parent process has exited. When that happens, the s
7
+ // child becomes inherited by `init`, changing its `ppid`. The information
8
+ // about the original parent is then lost.
9
+ // - The only way to implement this would be to repeatedly list processes as
10
+ // the build command is ongoing. However, this would fail to detect processes
11
+ // spawned just before the build commands ends.
12
+ // We cannot list processes before and after the build command and use the
13
+ // difference.
14
+ // - This is because other processes (unrelated to @netlify/build) might be
15
+ // running at the same time. This includes OS background processes.
16
+ // Therefore, we run this in a controlled environment only (the buildbot) and
17
+ // exclude specific processes manually. This is a lesser evil, although still
18
+ // quite hacky.
19
+ export const warnOnLingeringProcesses = async function ({ mode, logs, testOpts: { silentLingeringProcesses = false }, }) {
20
+ if (mode !== 'buildbot' || silentLingeringProcesses) {
21
+ return;
22
+ }
23
+ const processes = await psList();
24
+ const commands = processes.map(getCommand).filter(isNotIgnoredCommand);
25
+ if (commands.length === 0) {
26
+ return;
27
+ }
28
+ logLingeringProcesses(logs, commands);
29
+ };
30
+ // `cmd` is only available on Unix. Unlike `name`, it includes the arguments.
31
+ const getCommand = function ({ name, cmd = name }) {
32
+ return cmd;
33
+ };
34
+ // We ignore any command known to be internal to the buildbot.
35
+ // We also ignore commands known not to complete properly in builds if they are
36
+ // widely used.
37
+ const isNotIgnoredCommand = function (command) {
38
+ return !IGNORED_COMMANDS.some((ignoredCommand) => matchesIgnoredCommand(command, ignoredCommand));
39
+ };
40
+ const matchesIgnoredCommand = function (command, ignoredCommand) {
41
+ if (typeof ignoredCommand === 'string') {
42
+ return command.includes(ignoredCommand);
43
+ }
44
+ return ignoredCommand.test(command);
45
+ };
46
+ const IGNORED_COMMANDS = [
47
+ // TODO: Those can most likely be removed
48
+ 'ps',
49
+ 'grep',
50
+ 'bash',
51
+ // Internal buildbot commands
52
+ '[build]',
53
+ /buildbot.*\[node]/,
54
+ // buildbot's main Bash script
55
+ '/opt/build-bin/build',
56
+ // `@netlify/build` binary itself
57
+ 'netlify-build',
58
+ // Plugin child processes spawned by @netlify/build
59
+ '@netlify/build',
60
+ // Shown for parent processes with currently running child processes.
61
+ // Happens on `ps` itself.
62
+ 'defunct',
63
+ // Processes often left running. We should report those but don't because of
64
+ // how common those are in production builds
65
+ 'gatsby-telemetry',
66
+ 'jest-worker',
67
+ 'broccoli-babel-transpiler',
68
+ ];
@@ -0,0 +1,110 @@
1
+ import { handleBuildError } from '../error/handle.js';
2
+ import { reportError } from '../error/report.js';
3
+ import { getSystemLogger } from '../log/logger.js';
4
+ import { logTimer, logBuildSuccess } from '../log/messages/core.js';
5
+ import { trackBuildComplete } from '../telemetry/main.js';
6
+ import { reportTimers } from '../time/report.js';
7
+ import { execBuild, startBuild } from './build.js';
8
+ import { getSeverity } from './severity.js';
9
+ export { startDev } from './dev.js';
10
+ export { runCoreSteps } from '../steps/run_core_steps.js';
11
+ /**
12
+ * Main entry point of Netlify Build.
13
+ * Runs a builds and returns whether it succeeded or not.
14
+ *
15
+ * @param flags - build configuration CLI flags
16
+ */
17
+ export default async function buildSite(flags = {}) {
18
+ const { errorMonitor, framework, mode, logs, debug, systemLogFile, testOpts, statsdOpts, dry, telemetry, buildId, deployId, ...flagsA } = startBuild(flags);
19
+ const errorParams = { errorMonitor, mode, logs, debug, testOpts };
20
+ const systemLog = getSystemLogger(logs, debug, systemLogFile);
21
+ try {
22
+ const { pluginsOptions, netlifyConfig: netlifyConfigA, siteInfo, userNodeVersion, stepsCount, timers, durationNs, configMutations, } = await execBuild({
23
+ ...flagsA,
24
+ buildId,
25
+ systemLogFile,
26
+ deployId,
27
+ dry,
28
+ errorMonitor,
29
+ mode,
30
+ logs,
31
+ debug,
32
+ testOpts,
33
+ errorParams,
34
+ });
35
+ await handleBuildSuccess({
36
+ framework,
37
+ dry,
38
+ logs,
39
+ timers,
40
+ durationNs,
41
+ statsdOpts,
42
+ systemLog,
43
+ });
44
+ const { success, severityCode, status } = getSeverity('success');
45
+ await telemetryReport({
46
+ buildId,
47
+ deployId,
48
+ status,
49
+ stepsCount,
50
+ pluginsOptions,
51
+ durationNs,
52
+ siteInfo,
53
+ telemetry,
54
+ userNodeVersion,
55
+ framework,
56
+ testOpts,
57
+ errorParams,
58
+ });
59
+ return { success, severityCode, netlifyConfig: netlifyConfigA, logs, configMutations };
60
+ }
61
+ catch (error) {
62
+ const { severity } = await handleBuildError(error, errorParams);
63
+ const { pluginsOptions, siteInfo, userNodeVersion } = errorParams;
64
+ const { success, severityCode, status } = getSeverity(severity);
65
+ await telemetryReport({
66
+ buildId,
67
+ deployId,
68
+ status,
69
+ pluginsOptions,
70
+ siteInfo,
71
+ telemetry,
72
+ userNodeVersion,
73
+ framework,
74
+ testOpts,
75
+ errorParams,
76
+ });
77
+ await reportError({ error, framework, statsdOpts });
78
+ return { success, severityCode, logs };
79
+ }
80
+ }
81
+ // Logs and reports that a build successfully ended
82
+ const handleBuildSuccess = async function ({ framework, dry, logs, timers, durationNs, statsdOpts, systemLog }) {
83
+ if (dry) {
84
+ return;
85
+ }
86
+ logBuildSuccess(logs);
87
+ logTimer(logs, durationNs, 'Netlify Build', systemLog);
88
+ await reportTimers({ timers, statsdOpts, framework });
89
+ };
90
+ // Handles the calls and errors of telemetry reports
91
+ const telemetryReport = async function ({ deployId, buildId, status, stepsCount, pluginsOptions, durationNs, siteInfo, telemetry, userNodeVersion, framework, testOpts, errorParams, }) {
92
+ try {
93
+ await trackBuildComplete({
94
+ deployId,
95
+ buildId,
96
+ status,
97
+ stepsCount,
98
+ pluginsOptions,
99
+ durationNs,
100
+ siteInfo,
101
+ telemetry,
102
+ userNodeVersion,
103
+ framework,
104
+ testOpts,
105
+ });
106
+ }
107
+ catch (error) {
108
+ await handleBuildError(error, errorParams);
109
+ }
110
+ };
@@ -0,0 +1,17 @@
1
+ import { relative } from 'path';
2
+ import { pathExists } from 'path-exists';
3
+ import { logMissingSideFile } from '../log/messages/core.js';
4
+ // Some files like `_headers` and `_redirects` must be copied to the publish
5
+ // directory to be used in production. When those are present in the repository
6
+ // but not in the publish directory, this most likely indicates that the build
7
+ // command accidentally forgot to copy those. We then print a warning message.
8
+ export const warnOnMissingSideFiles = async function ({ buildDir, netlifyConfig: { build: { publish }, }, logs, }) {
9
+ await Promise.all(SIDE_FILES.map((sideFile) => warnOnMissingSideFile({ logs, sideFile, buildDir, publish })));
10
+ };
11
+ const SIDE_FILES = ['_headers', '_redirects'];
12
+ const warnOnMissingSideFile = async function ({ logs, sideFile, buildDir, publish }) {
13
+ if (!(await pathExists(`${buildDir}/${sideFile}`)) || (await pathExists(`${publish}/${sideFile}`))) {
14
+ return;
15
+ }
16
+ logMissingSideFile(logs, sideFile, relative(buildDir, publish));
17
+ };
@@ -0,0 +1,59 @@
1
+ import { env, execPath } from 'process';
2
+ import { logFlags } from '../log/messages/config.js';
3
+ import { removeFalsy } from '../utils/remove_falsy.js';
4
+ import { DEFAULT_FEATURE_FLAGS } from './feature_flags.js';
5
+ const REQUIRE_MODE = 'require';
6
+ const DEFAULT_EDGE_FUNCTIONS_DIST = '.netlify/edge-functions-dist/';
7
+ const DEFAULT_FUNCTIONS_DIST = '.netlify/functions/';
8
+ const DEFAULT_CACHE_DIR = '.netlify/cache/';
9
+ const DEFAULT_STATSD_PORT = 8125;
10
+ /** Normalize CLI flags */
11
+ export const normalizeFlags = function (flags, logs) {
12
+ const rawFlags = removeFalsy(flags);
13
+ // Combine the flags object env with the process.env
14
+ const combinedEnv = { ...env, ...rawFlags.env };
15
+ const defaultFlags = getDefaultFlags(rawFlags, combinedEnv);
16
+ // The telemetry flag requires specific logic to compute
17
+ const telemetryFlag = computeTelemetry(rawFlags, combinedEnv);
18
+ const mergedFlags = {
19
+ ...defaultFlags,
20
+ ...rawFlags,
21
+ ...telemetryFlag,
22
+ statsdOpts: { ...defaultFlags.statsd, ...rawFlags.statsd },
23
+ featureFlags: { ...defaultFlags.featureFlags, ...rawFlags.featureFlags },
24
+ };
25
+ const normalizedFlags = removeFalsy(mergedFlags);
26
+ logFlags(logs, rawFlags, normalizedFlags);
27
+ return normalizedFlags;
28
+ };
29
+ // Default values of CLI flags
30
+ const getDefaultFlags = function ({ env: envOpt = {} }, combinedEnv) {
31
+ return {
32
+ env: envOpt,
33
+ nodePath: execPath,
34
+ token: combinedEnv.NETLIFY_AUTH_TOKEN,
35
+ mode: REQUIRE_MODE,
36
+ offline: false,
37
+ telemetry: false,
38
+ verbose: Boolean(combinedEnv.NETLIFY_BUILD_DEBUG),
39
+ functionsDistDir: DEFAULT_FUNCTIONS_DIST,
40
+ edgeFunctionsDistDir: DEFAULT_EDGE_FUNCTIONS_DIST,
41
+ cacheDir: DEFAULT_CACHE_DIR,
42
+ deployId: combinedEnv.DEPLOY_ID,
43
+ buildId: combinedEnv.BUILD_ID,
44
+ debug: Boolean(combinedEnv.NETLIFY_BUILD_DEBUG),
45
+ bugsnagKey: combinedEnv.BUGSNAG_KEY,
46
+ sendStatus: false,
47
+ saveConfig: false,
48
+ apiHost: 'api.netlify.com',
49
+ testOpts: {},
50
+ featureFlags: DEFAULT_FEATURE_FLAGS,
51
+ statsd: { port: DEFAULT_STATSD_PORT },
52
+ timeline: 'build',
53
+ };
54
+ };
55
+ // Compute the telemetry flag, it's disabled by default and we want to always disable it
56
+ // if BUILD_TELEMETRY_DISABLED is passed.
57
+ const computeTelemetry = function (flags, envOpts) {
58
+ return envOpts.BUILD_TELEMETRY_DISABLED ? { telemetry: false } : { telemetry: flags.telemetry };
59
+ };
@@ -0,0 +1,21 @@
1
+ const SEVERITY_MAP = {
2
+ success: { severityCode: 0, status: 'success' },
3
+ none: { severityCode: 1, status: 'cancelled' },
4
+ info: { severityCode: 2, status: 'user-error' },
5
+ warning: { severityCode: 3, status: 'plugin-error' },
6
+ error: { severityCode: 4, status: 'system-error' },
7
+ };
8
+ const SUCCESS_SEVERITY = 'success';
9
+ /** Indicates a bug in our codebase */
10
+ const FALLBACK_SEVERITY = 'error';
11
+ /** Map error severities to exit codes and status (used for telemetry purposes) */
12
+ export const FALLBACK_SEVERITY_ENTRY = SEVERITY_MAP[FALLBACK_SEVERITY];
13
+ /**
14
+ * Used to extract exit codes and respective status strings
15
+ * 1|2|3 indicate whether this was a user|plugin|system error.
16
+ */
17
+ export const getSeverity = (severity = FALLBACK_SEVERITY) => {
18
+ const severityEntry = severity in SEVERITY_MAP ? SEVERITY_MAP[severity] : FALLBACK_SEVERITY_ENTRY;
19
+ const success = severity === SUCCESS_SEVERITY;
20
+ return { success, ...severityEntry };
21
+ };
@@ -0,0 +1,8 @@
1
+ export var SeverityCode;
2
+ (function (SeverityCode) {
3
+ SeverityCode[SeverityCode["success"] = 1] = "success";
4
+ SeverityCode[SeverityCode["buildCancelled"] = 2] = "buildCancelled";
5
+ SeverityCode[SeverityCode["userError"] = 3] = "userError";
6
+ SeverityCode[SeverityCode["pluginError"] = 4] = "pluginError";
7
+ SeverityCode[SeverityCode["systemError"] = 5] = "systemError";
8
+ })(SeverityCode = SeverityCode || (SeverityCode = {}));
@@ -0,0 +1,32 @@
1
+ import { version as currentVersion, execPath } from 'process';
2
+ import { execa } from 'execa';
3
+ import semver from 'semver';
4
+ import { addErrorInfo } from '../error/info.js';
5
+ // Retrieve Node.js version if the Node.js path is using nvm.
6
+ // `node.exe` on Windows, `bin/node` on Unix.
7
+ const NVM_NODE_VERSION_REGEXP = /[/\\]v(\d+\.\d+\.\d+)[/\\](bin[/\\]node|node.exe)$/;
8
+ // Retrieve Node.js version from current process
9
+ const getCurrentNodeVersion = function () {
10
+ return semver.clean(currentVersion);
11
+ };
12
+ // Retrieve Node.js version from `--node-path` or fallback to extracting the current Node.js process version
13
+ export const getUserNodeVersion = async function (nodePath) {
14
+ // No `--node-path` CLI flag, use the current node process version
15
+ if (nodePath === execPath) {
16
+ return getCurrentNodeVersion();
17
+ }
18
+ // Extract version from path
19
+ const result = NVM_NODE_VERSION_REGEXP.exec(nodePath);
20
+ if (result !== null) {
21
+ return result[1];
22
+ }
23
+ // Fallback to actually running `node --version` with the given nodePath
24
+ const { stdout } = await execa(nodePath, ['--version'], { reject: false });
25
+ const version = semver.clean(stdout);
26
+ if (version === null) {
27
+ const error = new Error(`Invalid --node-path CLI flag: ${nodePath}`);
28
+ addErrorInfo(error, { type: 'resolveConfig' });
29
+ throw error;
30
+ }
31
+ return version;
32
+ };
@@ -0,0 +1,43 @@
1
+ import { env } from 'process';
2
+ import filterObj from 'filter-obj';
3
+ import mapObj from 'map-obj';
4
+ // If plugins modify `process.env`, this is propagated in other plugins and in
5
+ // `build.command`. Since those are different processes, we figure out when they
6
+ // do this and communicate the new `process.env` to other processes.
7
+ export const getNewEnvChanges = function (envBefore, netlifyConfig, netlifyConfigCopy) {
8
+ const processEnvChanges = diffEnv(envBefore, env);
9
+ const netlifyConfigEnvChanges = diffEnv(netlifyConfig.build.environment, netlifyConfigCopy.build.environment);
10
+ return { ...processEnvChanges, ...netlifyConfigEnvChanges };
11
+ };
12
+ const diffEnv = function (envBefore, envAfter) {
13
+ const envChanges = filterObj(envAfter, (name, value) => value !== envBefore[name]);
14
+ const deletedEnv = filterObj(envBefore, (name) => envAfter[name] === undefined);
15
+ const deletedEnvA = mapObj(deletedEnv, setToNull);
16
+ return { ...envChanges, ...deletedEnvA };
17
+ };
18
+ // `undefined` is not JSON-serializable (which is used in process IPC), so we
19
+ // convert it to `null`
20
+ // Note: `process.env[name] = undefined` actually does
21
+ // `process.env[name] = 'undefined'` in Node.js.
22
+ const setToNull = function (name) {
23
+ return [name, null];
24
+ };
25
+ // Set `process.env` changes from a previous different plugin.
26
+ // Can also merge with a `currentEnv` plain object instead of `process.env`.
27
+ export const setEnvChanges = function (envChanges, currentEnv = env) {
28
+ Object.entries(envChanges).forEach(([name, value]) => {
29
+ setEnvChange(name, value, currentEnv);
30
+ });
31
+ return { ...currentEnv };
32
+ };
33
+ const setEnvChange = function (name, value, currentEnv) {
34
+ if (currentEnv[name] === value) {
35
+ return;
36
+ }
37
+ if (value === null) {
38
+ // `currentEnv` is a mutable variable
39
+ delete currentEnv[name];
40
+ return;
41
+ }
42
+ currentEnv[name] = value;
43
+ };
@@ -0,0 +1,14 @@
1
+ import { env } from 'process';
2
+ import filterObj from 'filter-obj';
3
+ import { getParentColorEnv } from '../log/colors.js';
4
+ // Retrieve the environment variables passed to plugins and `build.command`
5
+ // When run locally, this tries to emulate the production environment.
6
+ export const getChildEnv = function ({ envOpt, env: allConfigEnv }) {
7
+ const parentColorEnv = getParentColorEnv();
8
+ const parentEnv = { ...env, ...allConfigEnv, ...envOpt, ...parentColorEnv };
9
+ return filterObj(parentEnv, shouldKeepEnv);
10
+ };
11
+ const shouldKeepEnv = function (key) {
12
+ return !REMOVED_PARENT_ENV.has(key.toLowerCase());
13
+ };
14
+ const REMOVED_PARENT_ENV = new Set(['bugsnag_key']);