@netlify/build 35.13.8 → 35.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/log/messages/core_steps.d.ts +8 -0
- package/lib/log/messages/core_steps.js +55 -1
- package/lib/plugins_core/functions/index.d.ts +2 -34
- package/lib/plugins_core/functions/index.js +14 -16
- package/lib/plugins_core/types.d.ts +7 -3
- package/lib/types/config/functions.d.ts +16 -0
- package/package.json +3 -3
|
@@ -2,6 +2,14 @@ export function logBundleResults({ logs, results }: {
|
|
|
2
2
|
logs: any;
|
|
3
3
|
results: import("@netlify/zip-it-and-ship-it").FunctionResult[];
|
|
4
4
|
}): void;
|
|
5
|
+
export function trackBundleResults({ results, systemLog }: {
|
|
6
|
+
results: import("@netlify/zip-it-and-ship-it").FunctionResult[];
|
|
7
|
+
systemLog: (...args: unknown[]) => void;
|
|
8
|
+
}): {
|
|
9
|
+
bundlers: import("@netlify/zip-it-and-ship-it").NodeBundlerName[];
|
|
10
|
+
fallbackCount: number;
|
|
11
|
+
warningsCount: number;
|
|
12
|
+
};
|
|
5
13
|
export function logFunctionsNonExistingDir(logs: any, relativeFunctionsSrc: any): void;
|
|
6
14
|
export function logFunctionsToBundle({ logs, userFunctions, userFunctionsSrc, userFunctionsSrcExists, internalFunctions, internalFunctionsSrc, frameworkFunctions, generatedFunctions, type, }: {
|
|
7
15
|
logs: any;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import { RUNTIME } from '@netlify/zip-it-and-ship-it';
|
|
3
|
+
import { trace } from '@opentelemetry/api';
|
|
2
4
|
import { log, logArray, logError, logErrorSubHeader, logWarningSubHeader } from '../logger.js';
|
|
3
5
|
import { THEME } from '../theme.js';
|
|
4
6
|
const logBundleResultFunctions = ({ functions, headerMessage, logs, error }) => {
|
|
@@ -12,7 +14,7 @@ const logBundleResultFunctions = ({ functions, headerMessage, logs, error }) =>
|
|
|
12
14
|
logArray(logs, functionNames);
|
|
13
15
|
};
|
|
14
16
|
/**
|
|
15
|
-
* Logs the result of bundling functions
|
|
17
|
+
* Logs the result of bundling functions (user facing)
|
|
16
18
|
*
|
|
17
19
|
* @param {object} options
|
|
18
20
|
* @param {any} options.logs
|
|
@@ -44,6 +46,58 @@ export const logBundleResults = ({ logs, results = [] }) => {
|
|
|
44
46
|
logModulesWithDynamicImports({ logs, modulesWithDynamicImports });
|
|
45
47
|
}
|
|
46
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Sibling of `logBundleResults`. Derives structured telemetry from the same
|
|
51
|
+
* `results` array and emits it to the system log and the active span. Returns
|
|
52
|
+
* summary stats the caller can use for metric tags.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} options
|
|
55
|
+
* @param {import("@netlify/zip-it-and-ship-it").FunctionResult[]} options.results
|
|
56
|
+
* @param {(...args: unknown[]) => void} options.systemLog
|
|
57
|
+
* @returns {{
|
|
58
|
+
* bundlers: import("@netlify/zip-it-and-ship-it").NodeBundlerName[],
|
|
59
|
+
* fallbackCount: number,
|
|
60
|
+
* warningsCount: number,
|
|
61
|
+
* }}
|
|
62
|
+
*/
|
|
63
|
+
export const trackBundleResults = ({ results = [], systemLog }) => {
|
|
64
|
+
// `bundlerErrors` is only set when the user requested `esbuild_zisi` (esbuild
|
|
65
|
+
// with zisi fallback), esbuild failed, and zisi succeeded. The final
|
|
66
|
+
// `bundler` reflects the fallback, so this is our "silent fallback" signal.
|
|
67
|
+
const perFunction = results.map((result) => ({
|
|
68
|
+
name: result.name,
|
|
69
|
+
runtime: result.runtime,
|
|
70
|
+
bundler: result.runtime === RUNTIME.JAVASCRIPT ? result.bundler : null,
|
|
71
|
+
hadFallback: (result.bundlerErrors?.length ?? 0) > 0,
|
|
72
|
+
hadWarnings: (result.bundlerWarnings?.length ?? 0) > 0,
|
|
73
|
+
}));
|
|
74
|
+
// Exclude both `null` (non-JS runtimes) and `undefined` (prebuilt `.zip`
|
|
75
|
+
// JS functions, which zip-it-and-ship-it passes through with no bundler).
|
|
76
|
+
const jsResults = perFunction.filter((p) => p.bundler != null);
|
|
77
|
+
const bundlers = [...new Set(jsResults.map((p) => p.bundler))];
|
|
78
|
+
const bundlerCounts = jsResults.reduce((acc, p) => ({ ...acc, [p.bundler]: (acc[p.bundler] ?? 0) + 1 }), {});
|
|
79
|
+
const fallbackCount = perFunction.filter((p) => p.hadFallback).length;
|
|
80
|
+
const warningsCount = perFunction.filter((p) => p.hadWarnings).length;
|
|
81
|
+
systemLog({
|
|
82
|
+
msg: 'Functions bundling completed',
|
|
83
|
+
bundlers,
|
|
84
|
+
bundlerCounts,
|
|
85
|
+
fallbackCount,
|
|
86
|
+
warningsCount,
|
|
87
|
+
functions: perFunction,
|
|
88
|
+
});
|
|
89
|
+
const span = trace.getActiveSpan();
|
|
90
|
+
if (span) {
|
|
91
|
+
span.setAttribute('build.execution.step.bundler', bundlers);
|
|
92
|
+
span.setAttribute('build.execution.step.functions_count', perFunction.length);
|
|
93
|
+
span.setAttribute('build.execution.step.bundler.fallback_count', fallbackCount);
|
|
94
|
+
span.setAttribute('build.execution.step.bundler.warnings_count', warningsCount);
|
|
95
|
+
for (const [bundler, count] of Object.entries(bundlerCounts)) {
|
|
96
|
+
span.setAttribute(`build.execution.step.bundler.${bundler}.count`, count);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { bundlers, fallbackCount, warningsCount };
|
|
100
|
+
};
|
|
47
101
|
export const logFunctionsNonExistingDir = function (logs, relativeFunctionsSrc) {
|
|
48
102
|
log(logs, `The Netlify Functions setting targets a non-existing directory: ${relativeFunctionsSrc}`);
|
|
49
103
|
};
|
|
@@ -1,40 +1,8 @@
|
|
|
1
1
|
import { zipFunctions, type FunctionResult } from '@netlify/zip-it-and-ship-it';
|
|
2
|
+
import type { CoreStepFunction } from '../types.js';
|
|
2
3
|
export declare const bundleFunctions: {
|
|
3
4
|
event: string;
|
|
4
|
-
coreStep:
|
|
5
|
-
childEnv: any;
|
|
6
|
-
constants: {
|
|
7
|
-
INTERNAL_FUNCTIONS_SRC: any;
|
|
8
|
-
IS_LOCAL: any;
|
|
9
|
-
FUNCTIONS_SRC: any;
|
|
10
|
-
FUNCTIONS_DIST: any;
|
|
11
|
-
};
|
|
12
|
-
buildDir: any;
|
|
13
|
-
branch: any;
|
|
14
|
-
packagePath: any;
|
|
15
|
-
logs: any;
|
|
16
|
-
netlifyConfig: any;
|
|
17
|
-
featureFlags: any;
|
|
18
|
-
repositoryRoot: any;
|
|
19
|
-
userNodeVersion: any;
|
|
20
|
-
systemLog: any;
|
|
21
|
-
returnValues: any;
|
|
22
|
-
}) => Promise<{
|
|
23
|
-
tags?: undefined;
|
|
24
|
-
metrics?: undefined;
|
|
25
|
-
} | {
|
|
26
|
-
tags: {
|
|
27
|
-
bundler: ("zisi" | "nft" | "esbuild" | "none" | "esbuild_zisi")[];
|
|
28
|
-
};
|
|
29
|
-
metrics: {
|
|
30
|
-
type: string;
|
|
31
|
-
name: string;
|
|
32
|
-
value: number;
|
|
33
|
-
tags: {
|
|
34
|
-
type: string;
|
|
35
|
-
};
|
|
36
|
-
}[];
|
|
37
|
-
}>;
|
|
5
|
+
coreStep: CoreStepFunction;
|
|
38
6
|
coreStepId: string;
|
|
39
7
|
coreStepName: string;
|
|
40
8
|
coreStepDescription: () => string;
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import { resolve } from 'path';
|
|
2
|
-
import {
|
|
2
|
+
import { zipFunctions } from '@netlify/zip-it-and-ship-it';
|
|
3
3
|
import { pathExists } from 'path-exists';
|
|
4
4
|
import { addErrorInfo } from '../../error/info.js';
|
|
5
5
|
import { log } from '../../log/logger.js';
|
|
6
6
|
import { getGeneratedFunctions } from '../../steps/return_values.js';
|
|
7
|
-
import { logBundleResults, logFunctionsNonExistingDir, logFunctionsToBundle } from '../../log/messages/core_steps.js';
|
|
7
|
+
import { logBundleResults, logFunctionsNonExistingDir, logFunctionsToBundle, trackBundleResults, } from '../../log/messages/core_steps.js';
|
|
8
8
|
import { FRAMEWORKS_API_FUNCTIONS_PATH } from '../../utils/frameworks_api.js';
|
|
9
9
|
import { getZipError } from './error.js';
|
|
10
10
|
import { getUserAndInternalFunctions, validateFunctionsSrc } from './utils.js';
|
|
11
11
|
import { getZisiParameters } from './zisi.js';
|
|
12
|
-
// Get a list of all unique bundlers in this run
|
|
13
|
-
const getBundlers = (results = []) =>
|
|
14
|
-
// using a Set to filter duplicates
|
|
15
|
-
new Set(results
|
|
16
|
-
.map((bundle) => (bundle.runtime === RUNTIME.JAVASCRIPT ? bundle.bundler : null))
|
|
17
|
-
.filter(Boolean));
|
|
18
12
|
// see https://docs.netlify.com/functions/trigger-on-events/#available-triggers
|
|
19
13
|
const eventTriggeredFunctions = new Set([
|
|
20
14
|
'deploy-building',
|
|
@@ -74,9 +68,9 @@ const zipFunctionsAndLogResults = async ({ branch, buildDir, childEnv, featureFl
|
|
|
74
68
|
},
|
|
75
69
|
}, functionsDist, zisiParameters);
|
|
76
70
|
validateCustomRoutes(results);
|
|
77
|
-
const bundlers = Array.from(getBundlers(results));
|
|
78
71
|
logBundleResults({ logs, results });
|
|
79
|
-
|
|
72
|
+
const summary = trackBundleResults({ results, systemLog });
|
|
73
|
+
return summary;
|
|
80
74
|
}
|
|
81
75
|
catch (error) {
|
|
82
76
|
throw await getZipError(error, functionsSrc);
|
|
@@ -86,7 +80,7 @@ const zipFunctionsAndLogResults = async ({ branch, buildDir, childEnv, featureFl
|
|
|
86
80
|
const coreStep = async function ({ childEnv, constants: { INTERNAL_FUNCTIONS_SRC: relativeInternalFunctionsSrc, IS_LOCAL: isRunningLocally, FUNCTIONS_SRC: relativeFunctionsSrc, FUNCTIONS_DIST: relativeFunctionsDist, }, buildDir, branch, packagePath, logs, netlifyConfig, featureFlags, repositoryRoot, userNodeVersion, systemLog, returnValues, }) {
|
|
87
81
|
const functionsSrc = relativeFunctionsSrc === undefined ? undefined : resolve(buildDir, relativeFunctionsSrc);
|
|
88
82
|
const functionsDist = resolve(buildDir, relativeFunctionsDist);
|
|
89
|
-
const internalFunctionsSrc = resolve(buildDir, relativeInternalFunctionsSrc);
|
|
83
|
+
const internalFunctionsSrc = resolve(buildDir, relativeInternalFunctionsSrc ?? '');
|
|
90
84
|
const internalFunctionsSrcExists = await pathExists(internalFunctionsSrc);
|
|
91
85
|
const frameworkFunctionsSrc = resolve(buildDir, packagePath || '', FRAMEWORKS_API_FUNCTIONS_PATH);
|
|
92
86
|
const frameworkFunctionsSrcExists = await pathExists(frameworkFunctionsSrc);
|
|
@@ -123,7 +117,7 @@ const coreStep = async function ({ childEnv, constants: { INTERNAL_FUNCTIONS_SRC
|
|
|
123
117
|
generatedFunctions.length === 0) {
|
|
124
118
|
return {};
|
|
125
119
|
}
|
|
126
|
-
const { bundlers } = await zipFunctionsAndLogResults({
|
|
120
|
+
const { bundlers, fallbackCount, warningsCount } = await zipFunctionsAndLogResults({
|
|
127
121
|
branch,
|
|
128
122
|
buildDir,
|
|
129
123
|
childEnv,
|
|
@@ -140,10 +134,14 @@ const coreStep = async function ({ childEnv, constants: { INTERNAL_FUNCTIONS_SRC
|
|
|
140
134
|
systemLog,
|
|
141
135
|
generatedFunctions: generatedFunctions.map((func) => func.path),
|
|
142
136
|
});
|
|
143
|
-
const
|
|
137
|
+
const fallback = fallbackCount > 0 ? 'true' : 'false';
|
|
138
|
+
const warnings = warningsCount > 0 ? 'true' : 'false';
|
|
139
|
+
const metrics = getMetrics(internalFunctions, userFunctions, { bundlers, fallback, warnings });
|
|
144
140
|
return {
|
|
145
141
|
tags: {
|
|
146
142
|
bundler: bundlers,
|
|
143
|
+
fallback,
|
|
144
|
+
warnings,
|
|
147
145
|
},
|
|
148
146
|
metrics,
|
|
149
147
|
};
|
|
@@ -203,19 +201,19 @@ export const zipItAndShipIt = {
|
|
|
203
201
|
return await zipFunctions(...args);
|
|
204
202
|
},
|
|
205
203
|
};
|
|
206
|
-
const getMetrics = (internalFunctions, userFunctions) => {
|
|
204
|
+
const getMetrics = (internalFunctions, userFunctions, { bundlers, fallback, warnings }) => {
|
|
207
205
|
return [
|
|
208
206
|
{
|
|
209
207
|
type: 'increment',
|
|
210
208
|
name: 'buildbot.build.functions',
|
|
211
209
|
value: internalFunctions.length,
|
|
212
|
-
tags: { type: 'lambda:generated' },
|
|
210
|
+
tags: { type: 'lambda:generated', bundler: bundlers, fallback, warnings },
|
|
213
211
|
},
|
|
214
212
|
{
|
|
215
213
|
type: 'increment',
|
|
216
214
|
name: 'buildbot.build.functions',
|
|
217
215
|
value: userFunctions.length,
|
|
218
|
-
tags: { type: 'lambda:user' },
|
|
216
|
+
tags: { type: 'lambda:user', bundler: bundlers, fallback, warnings },
|
|
219
217
|
},
|
|
220
218
|
];
|
|
221
219
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type DynamicMethods } from 'packages/js-client/lib/types.js';
|
|
2
|
-
import { NetlifyPluginConstants } from '../core/constants.js';
|
|
3
|
-
import { BufferedLogs } from '../log/logger.js';
|
|
4
|
-
import { NetlifyConfig } from '../types/config/netlify_config.js';
|
|
2
|
+
import type { NetlifyPluginConstants } from '../core/constants.js';
|
|
3
|
+
import type { BufferedLogs } from '../log/logger.js';
|
|
4
|
+
import type { NetlifyConfig } from '../types/config/netlify_config.js';
|
|
5
|
+
import type { ReturnValue } from '../steps/return_values.js';
|
|
5
6
|
type $TSFixme = any;
|
|
6
7
|
export type CoreStepFunctionArgs = {
|
|
7
8
|
/**
|
|
@@ -46,6 +47,9 @@ export type CoreStepFunctionArgs = {
|
|
|
46
47
|
isSecret: boolean;
|
|
47
48
|
scopes: string[];
|
|
48
49
|
}[];
|
|
50
|
+
userNodeVersion?: string;
|
|
51
|
+
childEnv: $TSFixme;
|
|
52
|
+
returnValues: Record<string, ReturnValue>;
|
|
49
53
|
buildbotServerSocket?: string;
|
|
50
54
|
api: DynamicMethods;
|
|
51
55
|
};
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
type GlobPattern = string;
|
|
2
2
|
type FunctionsObject = {
|
|
3
|
+
/**
|
|
4
|
+
* marks the function as a [background function](https://docs.netlify.com/functions/background-functions/), which is invoked asynchronously and can run for up to 15 minutes.
|
|
5
|
+
*/
|
|
6
|
+
background?: boolean;
|
|
3
7
|
/**
|
|
4
8
|
* a list of additional paths to include in the function bundle. Although our build system includes statically referenced files (like `import * from "./some-file.js"`) by default, `included_files` lets you specify additional files or directories and reference them dynamically in function code. You can use `*` to match any character or prefix an entry with `!` to exclude files. Paths are relative to the [base directory](https://docs.netlify.com/configure-builds/get-started/#definitions-1).
|
|
5
9
|
*/
|
|
6
10
|
included_files?: string[];
|
|
11
|
+
/**
|
|
12
|
+
* the amount of memory allocated to the function, expressed either as a number of MB or as a string with a unit (e.g. `"2gb"`). Mutually exclusive with `vcpu`.
|
|
13
|
+
*/
|
|
14
|
+
memory?: number | string;
|
|
15
|
+
/**
|
|
16
|
+
* the [region](https://docs.netlify.com/functions/optional-configuration/#region) the function should run in, identified by its airport code (e.g. `"cmh"`).
|
|
17
|
+
*/
|
|
18
|
+
region?: string;
|
|
19
|
+
/**
|
|
20
|
+
* the number of vCPUs allocated to the function (between `0.5` and `2`). Mutually exclusive with `memory`.
|
|
21
|
+
*/
|
|
22
|
+
vcpu?: number;
|
|
7
23
|
} & ({
|
|
8
24
|
/**
|
|
9
25
|
* the function bundling method used in [`@netlify/zip-it-and-ship-it`](https://github.com/netlify/zip-it-and-ship-it).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/build",
|
|
3
|
-
"version": "35.
|
|
3
|
+
"version": "35.14.0",
|
|
4
4
|
"description": "Netlify build module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./lib/index.js",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@netlify/blobs": "^10.4.4",
|
|
71
71
|
"@netlify/cache-utils": "^6.0.5",
|
|
72
72
|
"@netlify/config": "^24.6.0",
|
|
73
|
-
"@netlify/edge-bundler": "14.10.
|
|
73
|
+
"@netlify/edge-bundler": "14.10.3",
|
|
74
74
|
"@netlify/functions-utils": "^6.2.34",
|
|
75
75
|
"@netlify/git-utils": "^6.0.4",
|
|
76
76
|
"@netlify/opentelemetry-utils": "^2.0.2",
|
|
@@ -152,5 +152,5 @@
|
|
|
152
152
|
"engines": {
|
|
153
153
|
"node": ">=18.14.0"
|
|
154
154
|
},
|
|
155
|
-
"gitHead": "
|
|
155
|
+
"gitHead": "dc4e6c79ae03de4070f706c936ed7e177d8ffec3"
|
|
156
156
|
}
|