diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bfa4e78dde..bbf41952c26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ +- Added a deprecation warning for functions.config() to stderr on deploy and all functions:config commands. (#8808) - Added analytics to track runtime config usage in functions deployments (#8870). - Fixed issue where `__name__` fields with DESCENDING order were incorrectly filtered from index listings, causing duplicate index issues (#7629) and deployment conflicts (#8859). The fix now preserves `__name__` fields with explicit DESCENDING order while filtering out implicit ASCENDING `__name__` fields. diff --git a/src/commands/functions-config-clone.ts b/src/commands/functions-config-clone.ts index 5fe6cc8d614..12b0d2c129d 100644 --- a/src/commands/functions-config-clone.ts +++ b/src/commands/functions-config-clone.ts @@ -8,6 +8,7 @@ import { requirePermissions } from "../requirePermissions"; import * as functionsConfig from "../functionsConfig"; import { functionsConfigClone } from "../functionsConfigClone"; import * as utils from "../utils"; +import { logFunctionsConfigDeprecationWarning } from "../functions/deprecationWarnings"; export const command = new Command("functions:config:clone") .description("clone environment config from another project") @@ -56,4 +57,5 @@ export const command = new Command("functions:config:clone") "firebase deploy --only functions", )}\n`, ); + logFunctionsConfigDeprecationWarning(); }); diff --git a/src/commands/functions-config-get.ts b/src/commands/functions-config-get.ts index 6367b0c7c9f..3827b80d2cf 100644 --- a/src/commands/functions-config-get.ts +++ b/src/commands/functions-config-get.ts @@ -6,6 +6,7 @@ import { logger } from "../logger"; import { needProjectId } from "../projectUtils"; import { requirePermissions } from "../requirePermissions"; import * as functionsConfig from "../functionsConfig"; +import { logFunctionsConfigDeprecationWarning } from "../functions/deprecationWarnings"; async function materialize(projectId: string, path?: string): Promise { if (path === undefined) { @@ -31,5 +32,6 @@ export const command = new Command("functions:config:get [path]") .action(async (path, options) => { const result = await materialize(needProjectId(options), path); logger.info(JSON.stringify(result, null, 2)); + logFunctionsConfigDeprecationWarning(); return result; }); diff --git a/src/commands/functions-config-set.ts b/src/commands/functions-config-set.ts index f29e37c0bbe..6ab9aa1f67a 100644 --- a/src/commands/functions-config-set.ts +++ b/src/commands/functions-config-set.ts @@ -7,6 +7,7 @@ import { needProjectId } from "../projectUtils"; import { requirePermissions } from "../requirePermissions"; import * as functionsConfig from "../functionsConfig"; import * as utils from "../utils"; +import { logFunctionsConfigDeprecationWarning } from "../functions/deprecationWarnings"; export const command = new Command("functions:config:set [values...]") .description("set environment config with key=value syntax") @@ -49,4 +50,5 @@ export const command = new Command("functions:config:set [values...]") "firebase deploy --only functions", )}\n`, ); + logFunctionsConfigDeprecationWarning(); }); diff --git a/src/commands/functions-config-unset.ts b/src/commands/functions-config-unset.ts index 97f989597e2..4b326876236 100644 --- a/src/commands/functions-config-unset.ts +++ b/src/commands/functions-config-unset.ts @@ -8,6 +8,7 @@ import * as functionsConfig from "../functionsConfig"; import * as runtimeconfig from "../gcp/runtimeconfig"; import * as utils from "../utils"; import { FirebaseError } from "../error"; +import { logFunctionsConfigDeprecationWarning } from "../functions/deprecationWarnings"; export const command = new Command("functions:config:unset [keys...]") .description("unset environment config at the specified path(s)") @@ -44,4 +45,5 @@ export const command = new Command("functions:config:unset [keys...]") "firebase deploy --only functions", )}\n`, ); + logFunctionsConfigDeprecationWarning(); }); diff --git a/src/deploy/functions/prepareFunctionsUpload.ts b/src/deploy/functions/prepareFunctionsUpload.ts index 175b8478252..f5fd2e94581 100644 --- a/src/deploy/functions/prepareFunctionsUpload.ts +++ b/src/deploy/functions/prepareFunctionsUpload.ts @@ -13,6 +13,7 @@ import * as functionsConfig from "../../functionsConfig"; import * as utils from "../../utils"; import * as fsAsync from "../../fsAsync"; import * as projectConfig from "../../functions/projectConfig"; +import { logFunctionsConfigDeprecationWarning } from "../../functions/deprecationWarnings"; const CONFIG_DEST_FILE = ".runtimeconfig.json"; @@ -99,6 +100,9 @@ async function packageSource( name: CONFIG_DEST_FILE, mode: 420 /* 0o644 */, }); + + // Log deprecation warning when runtime config is being packaged + logFunctionsConfigDeprecationWarning(); } await pipeAsync(archive, fileStream); } catch (err: any) { diff --git a/src/experiments.ts b/src/experiments.ts index 615c7459032..6027b9d5d3a 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -57,6 +57,14 @@ export const ALL_EXPERIMENTS = experiments({ "of how that image was created.", public: true, }, + dangerouslyAllowFunctionsConfig: { + shortDescription: "Allows the use of deprecated functions.config() API", + fullDescription: + "The functions.config() API is deprecated and will be removed on December 31, 2025. " + + "This experiment allows continued use of the API during the migration period.", + default: true, + public: true, + }, // Emulator experiments emulatoruisnapshot: { diff --git a/src/functions/deprecationWarnings.ts b/src/functions/deprecationWarnings.ts new file mode 100644 index 00000000000..96b98f65c63 --- /dev/null +++ b/src/functions/deprecationWarnings.ts @@ -0,0 +1,22 @@ +import { logWarningToStderr } from "../utils"; + +const FUNCTIONS_CONFIG_DEPRECATION_MESSAGE = `DEPRECATION NOTICE: Action required to deploy after Dec 31, 2025 + + functions.config() API is deprecated. + Cloud Runtime Configuration API, the Google Cloud service used to store function configuration data, will be shut down on December 31, 2025. As a result, you must migrate away from using functions.config() to continue deploying your functions after December 31, 2025. + + What this means for you: + + - The Firebase CLI commands for managing this configuration (functions:config:set, get, unset, clone, and export) are deprecated. These commands no longer work after December 31, 2025. + - firebase deploy command will fail for functions that use the legacy functions.config() API after December 31, 2025. + + Existing deployments will continue to work with their current configuration. + + See your migration options at: https://firebase.google.com/docs/functions/config-env#migrate-to-dotenv`; + +/** + * Logs a deprecation warning for functions.config() usage + */ +export function logFunctionsConfigDeprecationWarning(): void { + logWarningToStderr(FUNCTIONS_CONFIG_DEPRECATION_MESSAGE); +} diff --git a/src/utils.ts b/src/utils.ts index c5393b52da0..275cb313034 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -198,6 +198,14 @@ export function logWarning( logger[type](clc.yellow(clc.bold(`${WARNING_CHAR} `)), message, data); } +/** + * Log a warning statement to stderr, regardless of logger configuration. + */ +export function logWarningToStderr(message: string): void { + const prefix = clc.bold(`${WARNING_CHAR} `); + process.stderr.write(clc.yellow(prefix + message) + "\n"); +} + /** * Log an info statement with a gray bullet at the start of the line. */