diff --git a/eslint_temporary_suppressions.js b/eslint_temporary_suppressions.js index 2ed0c0edec..935d9de79c 100644 --- a/eslint_temporary_suppressions.js +++ b/eslint_temporary_suppressions.js @@ -707,6 +707,12 @@ export default [ 'n/no-missing-import': 'off', }, }, + { + files: ['packages/build/src/log/messages/lambda_compat_deprecation.ts'], + rules: { + 'n/no-missing-import': 'off', + }, + }, { files: ['packages/build/src/log/messages/mutations.js'], rules: { diff --git a/packages/build/src/core/build.ts b/packages/build/src/core/build.ts index 2a43602e87..95f98474d2 100644 --- a/packages/build/src/core/build.ts +++ b/packages/build/src/core/build.ts @@ -704,6 +704,7 @@ const runBuild = async function ({ explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, + pluginsOptions, }) return { diff --git a/packages/build/src/log/messages/lambda_compat_deprecation.ts b/packages/build/src/log/messages/lambda_compat_deprecation.ts new file mode 100644 index 0000000000..62acda3f78 --- /dev/null +++ b/packages/build/src/log/messages/lambda_compat_deprecation.ts @@ -0,0 +1,87 @@ +import path from 'path' + +import type { FunctionResult } from '@netlify/zip-it-and-ship-it' +import semver from 'semver' + +import type { PluginsOptions } from '../../plugins/node_version.js' +import { isRuntime } from '../../utils/runtime.js' +import { log, logArray, logWarningSubHeader, type Logs } from '../logger.js' + +const LEGACY_NEXTJS_RUNTIME_RANGE = '4.x' + +interface LegacyNextjsRuntime { + name: string + version: string +} + +const detectLegacyNextjsRuntime = (pluginsOptions: PluginsOptions[] | undefined): LegacyNextjsRuntime | null => { + const runtime = pluginsOptions?.find(isRuntime) + const version: unknown = runtime?.pluginPackageJson?.version + + if (runtime && typeof version === 'string' && semver.satisfies(version, LEGACY_NEXTJS_RUNTIME_RANGE)) { + return { name: runtime.packageName, version } + } + + return null +} + +interface LogLambdaCompatibilityDeprecationOptions { + logs: Logs | undefined + results: FunctionResult[] + functionsSrc: string | undefined + pluginsOptions: PluginsOptions[] | undefined +} + +/** + * Warns about JavaScript/TypeScript functions still using Lambda compatibility + * mode (V1) after bundling. + */ +export const logLambdaCompatibilityDeprecation = ({ + logs, + results, + functionsSrc, + pluginsOptions, +}: LogLambdaCompatibilityDeprecationOptions): void => { + const v1JsFunctions = results.filter((result) => result.runtime === 'js' && result.runtimeAPIVersion !== 2) + + if (v1JsFunctions.length === 0) { + return + } + + const userFns: string[] = [] + const generatedFns: string[] = [] + + for (const fn of v1JsFunctions) { + if (functionsSrc && fn.mainFile.startsWith(`${functionsSrc}${path.sep}`)) { + userFns.push(fn.name) + } else { + generatedFns.push(fn.name) + } + } + + logWarningSubHeader( + logs, + 'Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.', + ) + + if (userFns.length > 0) { + log(logs, '\n These functions in your project use Lambda compatibility mode:') + logArray(logs, userFns) + log(logs, '\n Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.') + } + + if (generatedFns.length > 0) { + log(logs, '\n These functions were generated by a framework adapter and use Lambda compatibility mode:') + logArray(logs, generatedFns) + + const legacyNextjsRuntime = detectLegacyNextjsRuntime(pluginsOptions) + if (legacyNextjsRuntime) { + log( + logs, + `\n Your project is using ${legacyNextjsRuntime.name} v${legacyNextjsRuntime.version}. Upgrade to the latest Netlify Next.js Adapter to emit modern Netlify Functions. Refer to https://ntl.fyi/nextjs-adapter-upgrade for upgrade guidance.`, + ) + } else { + log(logs, '\n Update the framework adapter to a version that emits modern Netlify Functions.') + } + } +} diff --git a/packages/build/src/plugins_core/functions/index.ts b/packages/build/src/plugins_core/functions/index.ts index 34f80ebe6f..3dd7414ac4 100644 --- a/packages/build/src/plugins_core/functions/index.ts +++ b/packages/build/src/plugins_core/functions/index.ts @@ -7,6 +7,7 @@ import { addErrorInfo } from '../../error/info.js' import { log } from '../../log/logger.js' import { type GeneratedFunction, getGeneratedFunctions } from '../../steps/return_values.js' import { logBundleResults, logFunctionsNonExistingDir, logFunctionsToBundle } from '../../log/messages/core_steps.js' +import { logLambdaCompatibilityDeprecation } from '../../log/messages/lambda_compat_deprecation.js' import { FRAMEWORKS_API_FUNCTIONS_PATH } from '../../utils/frameworks_api.js' import { getZipError } from './error.js' @@ -77,6 +78,7 @@ const zipFunctionsAndLogResults = async ({ repositoryRoot, userNodeVersion, systemLog, + pluginsOptions, }) => { const zisiParameters = getZisiParameters({ branch, @@ -115,6 +117,12 @@ const zipFunctionsAndLogResults = async ({ const bundlers = Array.from(getBundlers(results)) logBundleResults({ logs, results }) + logLambdaCompatibilityDeprecation({ + logs, + results, + functionsSrc, + pluginsOptions, + }) return { bundlers } } catch (error) { @@ -142,6 +150,7 @@ const coreStep = async function ({ userNodeVersion, systemLog, returnValues, + pluginsOptions, }) { const functionsSrc = relativeFunctionsSrc === undefined ? undefined : resolve(buildDir, relativeFunctionsSrc) const functionsDist = resolve(buildDir, relativeFunctionsDist) @@ -206,6 +215,7 @@ const coreStep = async function ({ userNodeVersion, systemLog, generatedFunctions: generatedFunctions.map((func) => func.path), + pluginsOptions, }) const metrics = getMetrics(internalFunctions, userFunctions) diff --git a/packages/build/src/steps/core_step.ts b/packages/build/src/steps/core_step.ts index e037783dd5..e29c7f089e 100644 --- a/packages/build/src/steps/core_step.ts +++ b/packages/build/src/steps/core_step.ts @@ -44,6 +44,7 @@ export const fireCoreStep = async function ({ outputFlusher, api, returnValues, + pluginsOptions, }) { const logsA = outputFlusher ? addOutputFlusher(logs, outputFlusher) : logs @@ -87,6 +88,7 @@ export const fireCoreStep = async function ({ edgeFunctionsBootstrapURL, deployId, returnValues, + pluginsOptions, }) const { netlifyConfig: netlifyConfigA, diff --git a/packages/build/src/steps/run_step.ts b/packages/build/src/steps/run_step.ts index 53c6c8c5b4..57a7fffd2e 100644 --- a/packages/build/src/steps/run_step.ts +++ b/packages/build/src/steps/run_step.ts @@ -73,6 +73,7 @@ export const runStep = async function ({ edgeFunctionsBootstrapURL, extensionMetadata, returnValues, + pluginsOptions, }) { // Add relevant attributes to the upcoming span context const attributes: StepExecutionAttributes = { @@ -195,6 +196,7 @@ export const runStep = async function ({ api, returnValues, deployEnvVars, + pluginsOptions, }) const newValues = await getStepReturn({ @@ -367,6 +369,7 @@ const tFireStep = function ({ extensionMetadata, api, returnValues, + pluginsOptions, }) { if (coreStep !== undefined) { return fireCoreStep({ @@ -408,6 +411,7 @@ const tFireStep = function ({ deployId, api, returnValues, + pluginsOptions, }) } diff --git a/packages/build/src/steps/run_steps.js b/packages/build/src/steps/run_steps.js index 50a012dcc8..aa77b8c2c2 100644 --- a/packages/build/src/steps/run_steps.js +++ b/packages/build/src/steps/run_steps.js @@ -47,6 +47,7 @@ export const runSteps = async function ({ explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, + pluginsOptions, }) { const { index: stepsCount, @@ -164,6 +165,7 @@ export const runSteps = async function ({ explicitSecretKeys, enhancedSecretScan, edgeFunctionsBootstrapURL, + pluginsOptions, }) const statusesA = addStatus({ newStatus, statuses, event, packageName, pluginPackageJson }) diff --git a/packages/build/tests/core/snapshots/tests.js.md b/packages/build/tests/core/snapshots/tests.js.md index b960cebcb0..bfc6ebffd8 100644 --- a/packages/build/tests/core/snapshots/tests.js.md +++ b/packages/build/tests/core/snapshots/tests.js.md @@ -1292,6 +1292,13 @@ Generated by [AVA](https://avajs.dev). - test.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - test␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -1761,6 +1768,14 @@ Generated by [AVA](https://avajs.dev). - function_two.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - function_one␊ + - function_two␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -1827,6 +1842,13 @@ Generated by [AVA](https://avajs.dev). - function_one.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - function_one␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -1966,6 +1988,15 @@ Generated by [AVA](https://avajs.dev). - function_with_dynamic_require.zip␊ - function_with_native.zip␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - function_simple␊ + - function_with_dynamic_require␊ + - function_with_native␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -2021,6 +2052,13 @@ Generated by [AVA](https://avajs.dev). > Failed to bundle functions with selected bundler (fallback used):␊ - function_with_module.zip␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - function_with_module␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ diff --git a/packages/build/tests/core/snapshots/tests.js.snap b/packages/build/tests/core/snapshots/tests.js.snap index 82c05655b4..8e7fbc8e27 100644 Binary files a/packages/build/tests/core/snapshots/tests.js.snap and b/packages/build/tests/core/snapshots/tests.js.snap differ diff --git a/packages/build/tests/functions/snapshots/tests.js.md b/packages/build/tests/functions/snapshots/tests.js.md index c3d44ca742..89546cc897 100644 --- a/packages/build/tests/functions/snapshots/tests.js.md +++ b/packages/build/tests/functions/snapshots/tests.js.md @@ -136,6 +136,13 @@ Generated by [AVA](https://avajs.dev). - test.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - test␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -223,6 +230,13 @@ Generated by [AVA](https://avajs.dev). - test.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - test␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -321,6 +335,13 @@ Generated by [AVA](https://avajs.dev). - test.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - test␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ diff --git a/packages/build/tests/functions/snapshots/tests.js.snap b/packages/build/tests/functions/snapshots/tests.js.snap index d0bfc0a82f..655f268556 100644 Binary files a/packages/build/tests/functions/snapshots/tests.js.snap and b/packages/build/tests/functions/snapshots/tests.js.snap differ diff --git a/packages/build/tests/install/snapshots/tests.js.md b/packages/build/tests/install/snapshots/tests.js.md index ceb36508bc..561cbc656f 100644 --- a/packages/build/tests/install/snapshots/tests.js.md +++ b/packages/build/tests/install/snapshots/tests.js.md @@ -56,6 +56,13 @@ Generated by [AVA](https://avajs.dev). - function/index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - function␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -110,6 +117,13 @@ Generated by [AVA](https://avajs.dev). - test.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - test␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -171,6 +185,13 @@ Generated by [AVA](https://avajs.dev). - index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - index␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -232,6 +253,13 @@ Generated by [AVA](https://avajs.dev). - index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - index␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -295,6 +323,13 @@ Generated by [AVA](https://avajs.dev). - index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - index␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -344,6 +379,13 @@ Generated by [AVA](https://avajs.dev). - index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - index␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -534,6 +576,13 @@ Generated by [AVA](https://avajs.dev). - index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - index␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -583,6 +632,13 @@ Generated by [AVA](https://avajs.dev). - index.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - index␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ diff --git a/packages/build/tests/install/snapshots/tests.js.snap b/packages/build/tests/install/snapshots/tests.js.snap index f205564e3d..53ba03010a 100644 Binary files a/packages/build/tests/install/snapshots/tests.js.snap and b/packages/build/tests/install/snapshots/tests.js.snap differ diff --git a/packages/build/tests/plugins/snapshots/tests.js.md b/packages/build/tests/plugins/snapshots/tests.js.md index bf32664143..8e97b511bc 100644 --- a/packages/build/tests/plugins/snapshots/tests.js.md +++ b/packages/build/tests/plugins/snapshots/tests.js.md @@ -1809,6 +1809,13 @@ Generated by [AVA](https://avajs.dev). - test/test.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions were generated by a framework adapter and use Lambda compatibility mode:␊ + - test␊ + ␊ + Update the framework adapter to a version that emits modern Netlify Functions.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ @@ -1955,6 +1962,18 @@ Generated by [AVA](https://avajs.dev). - user_1.js␊ ␊ ␊ + > Lambda compatibility mode is deprecated and will be removed on June 1, 2027. Refer to https://ntl.fyi/lambda-deprecate for details.␊ + ␊ + These functions in your project use Lambda compatibility mode:␊ + - user_1␊ + ␊ + Migrate them to the modern Netlify Functions API. Refer to https://ntl.fyi/functions-migrate.␊ + ␊ + These functions were generated by a framework adapter and use Lambda compatibility mode:␊ + - internal_1␊ + ␊ + Update the framework adapter to a version that emits modern Netlify Functions.␊ + ␊ (Functions bundling completed in 1ms)␊ Build step duration: Functions bundling completed in 1ms␊ ␊ diff --git a/packages/build/tests/plugins/snapshots/tests.js.snap b/packages/build/tests/plugins/snapshots/tests.js.snap index 27ccf55412..b9dc6880ce 100644 Binary files a/packages/build/tests/plugins/snapshots/tests.js.snap and b/packages/build/tests/plugins/snapshots/tests.js.snap differ