firebase-tools 12.4.1 → 12.4.3

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 (34) hide show
  1. package/lib/commands/ext-configure.js +0 -1
  2. package/lib/commands/ext-install.js +56 -56
  3. package/lib/commands/ext-update.js +0 -1
  4. package/lib/commands/index.js +0 -2
  5. package/lib/commands/internaltesting-frameworks-compose.js +4 -2
  6. package/lib/commands/open.js +2 -2
  7. package/lib/deploy/extensions/planner.js +8 -6
  8. package/lib/deploy/functions/ensure.js +0 -3
  9. package/lib/deploy/functions/prepare.js +12 -17
  10. package/lib/deploy/functions/release/index.js +1 -1
  11. package/lib/deploy/functions/release/reporter.js +41 -24
  12. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +0 -3
  13. package/lib/deploy/functions/runtimes/node/versioning.js +0 -2
  14. package/lib/deploy/lifecycleHooks.js +25 -6
  15. package/lib/emulator/downloadableEmulators.js +3 -3
  16. package/lib/extensions/displayExtensionInfo.js +104 -42
  17. package/lib/extensions/emulator/triggerHelper.js +1 -1
  18. package/lib/extensions/extensionsApi.js +1 -1
  19. package/lib/extensions/extensionsHelper.js +19 -30
  20. package/lib/extensions/publisherApi.js +1 -2
  21. package/lib/extensions/updateHelper.js +2 -2
  22. package/lib/frameworks/compose/discover/filesystem.js +1 -1
  23. package/lib/frameworks/compose/discover/index.js +27 -18
  24. package/lib/frameworks/compose/discover/runtime/node.js +149 -0
  25. package/lib/frameworks/compose/driver/docker.js +23 -13
  26. package/lib/frameworks/compose/driver/local.js +13 -4
  27. package/lib/frameworks/compose/index.js +9 -8
  28. package/lib/frameworks/next/index.js +13 -4
  29. package/lib/{api → gcp}/frameworks.js +7 -5
  30. package/lib/init/features/frameworks/index.js +31 -1
  31. package/lib/init/features/{composer → frameworks}/repo.js +1 -4
  32. package/package.json +1 -1
  33. package/schema/firebase-config.json +4 -0
  34. package/lib/commands/internaltesting-frameworks-init.js +0 -14
@@ -65,7 +65,6 @@ exports.command = new command_1.Command("ext:configure <extensionInstanceId>")
65
65
  projectId,
66
66
  paramSpecs: tbdParams,
67
67
  nonInteractive: false,
68
- paramsEnvPath: "",
69
68
  instanceId,
70
69
  reconfiguring: true,
71
70
  });
@@ -3,18 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
5
  const marked_1 = require("marked");
6
+ const semver = require("semver");
6
7
  const TerminalRenderer = require("marked-terminal");
7
8
  const displayExtensionInfo_1 = require("../extensions/displayExtensionInfo");
8
9
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
9
10
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
10
11
  const command_1 = require("../command");
11
12
  const error_1 = require("../error");
13
+ const logger_1 = require("../logger");
12
14
  const projectUtils_1 = require("../projectUtils");
13
15
  const extensionsApi = require("../extensions/extensionsApi");
14
16
  const refs = require("../extensions/refs");
15
17
  const secretsUtils = require("../extensions/secretsUtils");
16
18
  const paramHelper = require("../extensions/paramHelper");
17
19
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
20
+ const planner_1 = require("../deploy/extensions/planner");
18
21
  const utils_1 = require("../extensions/utils");
19
22
  const requirePermissions_1 = require("../requirePermissions");
20
23
  const utils = require("../utils");
@@ -25,7 +28,7 @@ const tos_1 = require("../extensions/tos");
25
28
  marked_1.marked.setOptions({
26
29
  renderer: new TerminalRenderer(),
27
30
  });
28
- exports.command = new command_1.Command("ext:install [extensionName]")
31
+ exports.command = new command_1.Command("ext:install [extensionRef]")
29
32
  .description("add an uploaded extension to firebase.json if [publisherId/extensionId] is provided;" +
30
33
  "or, add a local extension if [localPath] is provided")
31
34
  .option("--local", "deprecated")
@@ -34,49 +37,48 @@ exports.command = new command_1.Command("ext:install [extensionName]")
34
37
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
35
38
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
36
39
  .before(extensionsHelper_1.diagnoseAndFixProject)
37
- .action(async (extensionName, options) => {
40
+ .action(async (extensionRef, options) => {
38
41
  var _a, _b;
39
- const projectId = (0, projectUtils_1.getProjectId)(options);
40
- const paramsEnvPath = "";
41
- let learnMore = false;
42
- if (!extensionName) {
43
- if (options.interactive) {
44
- learnMore = true;
45
- extensionName = await (0, extensionsHelper_1.promptForOfficialExtension)("Which official extension do you wish to install?\n" +
46
- " Select an extension, then press Enter to learn more.");
47
- }
48
- else {
49
- throw new error_1.FirebaseError(`Unable to find published extension '${clc.bold(extensionName)}'. ` +
50
- `Run ${clc.bold("firebase ext:install -i")} to select from the list of all available published extensions.`);
51
- }
52
- }
53
- let source;
54
- let extensionVersion;
55
- if ((0, extensionsHelper_1.isUrlPath)(extensionName)) {
56
- throw new error_1.FirebaseError(`Installing with a source url is no longer supported in the CLI. Please use Firebase Console instead.`);
57
- }
58
42
  if (options.local) {
59
43
  utils.logLabeledWarning(extensionsHelper_1.logPrefix, "As of firebase-tools@11.0.0, the `--local` flag is no longer required, as it is the default behavior.");
60
44
  }
61
- if ((0, extensionsHelper_1.isLocalPath)(extensionName)) {
62
- source = await (0, extensionsHelper_1.createSourceFromLocation)((0, projectUtils_1.needProjectId)({ projectId }), extensionName);
63
- await (0, displayExtensionInfo_1.displayExtInfo)(extensionName, "", source.spec);
64
- void (0, track_1.trackGA4)("extension_added_to_manifest", {
65
- published: "local",
66
- interactive: options.nonInteractive ? "false" : "true",
67
- });
45
+ if (!extensionRef) {
46
+ throw new error_1.FirebaseError("Extension ref is required to install. To see a full list of available extensions, go to Extensions Hub (https://extensions.dev/extensions).");
47
+ }
48
+ let source;
49
+ let extensionVersion;
50
+ const projectId = (0, projectUtils_1.getProjectId)(options);
51
+ if ((0, extensionsHelper_1.isLocalPath)(extensionRef)) {
52
+ source = await (0, extensionsHelper_1.createSourceFromLocation)((0, projectUtils_1.needProjectId)({ projectId }), extensionRef);
53
+ await (0, displayExtensionInfo_1.displayExtensionVersionInfo)({ spec: source.spec });
68
54
  }
69
55
  else {
70
- extensionName = await (0, extensionsHelper_1.canonicalizeRefInput)(extensionName);
71
- extensionVersion = await extensionsApi.getExtensionVersion(extensionName);
72
- void (0, track_1.trackGA4)("extension_added_to_manifest", {
73
- published: ((_a = extensionVersion.listing) === null || _a === void 0 ? void 0 : _a.state) === "APPROVED" ? "published" : "uploaded",
74
- interactive: options.nonInteractive ? "false" : "true",
75
- });
76
- await infoExtensionVersion({
77
- extensionName,
56
+ const extension = await extensionsApi.getExtension(extensionRef);
57
+ const ref = refs.parse(extensionRef);
58
+ ref.version = await (0, planner_1.resolveVersion)(ref, extension);
59
+ const extensionVersionRef = refs.toExtensionVersionRef(ref);
60
+ extensionVersion = await extensionsApi.getExtensionVersion(extensionVersionRef);
61
+ await (0, displayExtensionInfo_1.displayExtensionVersionInfo)({
62
+ spec: extensionVersion.spec,
78
63
  extensionVersion,
64
+ latestApprovedVersion: extension.latestApprovedVersion,
65
+ latestVersion: extension.latestVersion,
79
66
  });
67
+ if (extensionVersion.state === "DEPRECATED") {
68
+ throw new error_1.FirebaseError(`Extension version ${clc.bold(extensionVersionRef)} is deprecated and cannot be installed. To install the latest non-deprecated version, omit the version in the extension ref.`);
69
+ }
70
+ logger_1.logger.info();
71
+ if ((extension.latestApprovedVersion &&
72
+ semver.gt(extension.latestApprovedVersion, extensionVersion.spec.version)) ||
73
+ (!extension.latestApprovedVersion &&
74
+ extension.latestVersion &&
75
+ semver.gt(extension.latestVersion, extensionVersion.spec.version))) {
76
+ const version = extension.latestApprovedVersion || extension.latestVersion;
77
+ logger_1.logger.info(`You are about to install extension version ${clc.bold(extensionVersion.spec.version)} which is older than the latest ${extension.latestApprovedVersion ? "accepted version" : "version"} ${clc.bold(version)}.`);
78
+ }
79
+ }
80
+ if (!source && !extensionVersion) {
81
+ throw new error_1.FirebaseError(`Failed to parse ${clc.bold(extensionRef)} as an extension version or a path to a local extension. Please specify a valid reference.`);
80
82
  }
81
83
  if (!(await (0, prompt_1.confirm)({
82
84
  nonInteractive: options.nonInteractive,
@@ -85,23 +87,26 @@ exports.command = new command_1.Command("ext:install [extensionName]")
85
87
  }))) {
86
88
  return;
87
89
  }
88
- if (!source && !extensionVersion) {
89
- throw new error_1.FirebaseError("Could not find a source. Please specify a valid source to continue.");
90
- }
91
- const spec = (_b = source === null || source === void 0 ? void 0 : source.spec) !== null && _b !== void 0 ? _b : extensionVersion === null || extensionVersion === void 0 ? void 0 : extensionVersion.spec;
90
+ const spec = (_a = source === null || source === void 0 ? void 0 : source.spec) !== null && _a !== void 0 ? _a : extensionVersion === null || extensionVersion === void 0 ? void 0 : extensionVersion.spec;
92
91
  if (!spec) {
93
- throw new error_1.FirebaseError(`Could not find the extension.yaml for extension '${clc.bold(extensionName)}'. Please make sure this is a valid extension and try again.`);
92
+ throw new error_1.FirebaseError(`Could not find the extension.yaml for extension '${clc.bold(extensionRef)}'. Please make sure this is a valid extension and try again.`);
93
+ }
94
+ if (source) {
95
+ void (0, track_1.trackGA4)("extension_added_to_manifest", {
96
+ published: "local",
97
+ interactive: options.nonInteractive ? "false" : "true",
98
+ });
94
99
  }
95
- if (learnMore) {
96
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, `You selected: ${clc.bold(spec.displayName || "")}.\n` +
97
- `${spec.description}\n` +
98
- `View details: https://firebase.google.com/products/extensions/${spec.name}\n`);
100
+ else if (extensionVersion) {
101
+ void (0, track_1.trackGA4)("extension_added_to_manifest", {
102
+ published: ((_b = extensionVersion.listing) === null || _b === void 0 ? void 0 : _b.state) === "APPROVED" ? "published" : "uploaded",
103
+ interactive: options.nonInteractive ? "false" : "true",
104
+ });
99
105
  }
100
106
  try {
101
107
  return installToManifest({
102
- paramsEnvPath,
103
108
  projectId,
104
- extensionName,
109
+ extensionRef,
105
110
  source,
106
111
  extVersion: extensionVersion,
107
112
  nonInteractive: options.nonInteractive,
@@ -117,17 +122,13 @@ exports.command = new command_1.Command("ext:install [extensionName]")
117
122
  throw err;
118
123
  }
119
124
  });
120
- async function infoExtensionVersion(args) {
121
- const ref = refs.parse(args.extensionName);
122
- await (0, displayExtensionInfo_1.displayExtInfo)(args.extensionName, ref.publisherId, args.extensionVersion.spec, true);
123
- }
124
125
  async function installToManifest(options) {
125
126
  var _a, _b, _c;
126
- const { projectId, extensionName, extVersion, source, paramsEnvPath, nonInteractive, force } = options;
127
- const isLocalSource = (0, extensionsHelper_1.isLocalPath)(extensionName);
127
+ const { projectId, extensionRef, extVersion, source, nonInteractive, force } = options;
128
+ const isLocalSource = (0, extensionsHelper_1.isLocalPath)(extensionRef);
128
129
  const spec = (_a = extVersion === null || extVersion === void 0 ? void 0 : extVersion.spec) !== null && _a !== void 0 ? _a : source === null || source === void 0 ? void 0 : source.spec;
129
130
  if (!spec) {
130
- throw new error_1.FirebaseError(`Could not find the extension.yaml for ${extensionName}. Please make sure this is a valid extension and try again.`);
131
+ throw new error_1.FirebaseError(`Could not find the extension.yaml for ${extensionRef}. Please make sure this is a valid extension and try again.`);
131
132
  }
132
133
  if (secretsUtils.usesSecrets(spec)) {
133
134
  await secretsUtils.ensureSecretManagerApiEnabled(options);
@@ -141,7 +142,6 @@ async function installToManifest(options) {
141
142
  projectId,
142
143
  paramSpecs: ((_b = spec.params) !== null && _b !== void 0 ? _b : []).concat((_c = spec.systemParams) !== null && _c !== void 0 ? _c : []),
143
144
  nonInteractive,
144
- paramsEnvPath,
145
145
  instanceId,
146
146
  });
147
147
  const eventsConfig = spec.events
@@ -158,7 +158,7 @@ async function installToManifest(options) {
158
158
  {
159
159
  instanceId,
160
160
  ref: !isLocalSource ? ref : undefined,
161
- localPath: isLocalSource ? extensionName : undefined,
161
+ localPath: isLocalSource ? extensionRef : undefined,
162
162
  params: paramBindingOptions,
163
163
  extensionSpec: spec,
164
164
  },
@@ -76,7 +76,6 @@ exports.command = new command_1.Command("ext:update <extensionInstanceId> [updat
76
76
  newSpec: newExtensionVersion.spec,
77
77
  currentParams: oldParamValues,
78
78
  projectId,
79
- paramsEnvPath: "",
80
79
  nonInteractive: options.nonInteractive,
81
80
  instanceId,
82
81
  });
@@ -144,8 +144,6 @@ function load(client) {
144
144
  client.internaltesting.frameworks.compose = loadCommand("internaltesting-frameworks-compose");
145
145
  client.internaltesting.functions = {};
146
146
  client.internaltesting.functions.discover = loadCommand("internaltesting-functions-discover");
147
- client.internaltesting.frameworks = {};
148
- client.internaltesting.frameworks.init = loadCommand("internaltesting-frameworks-init");
149
147
  }
150
148
  client.login = loadCommand("login");
151
149
  client.login.add = loadCommand("login-add");
@@ -6,15 +6,17 @@ const logger_1 = require("../logger");
6
6
  const driver_1 = require("../frameworks/compose/driver");
7
7
  const compose_1 = require("../frameworks/compose");
8
8
  const error_1 = require("../error");
9
+ const filesystem_1 = require("../frameworks/compose/discover/filesystem");
10
+ const frameworkSpec_1 = require("../frameworks/compose/discover/frameworkSpec");
9
11
  exports.command = new command_1.Command("internaltesting:frameworks:compose")
10
12
  .option("-m, --mode <mode>", "Composer mode (local or docker)", "local")
11
13
  .description("compose framework in current directory")
12
- .action((options) => {
14
+ .action(async (options) => {
13
15
  const mode = options.mode;
14
16
  if (!driver_1.SUPPORTED_MODES.includes(mode)) {
15
17
  throw new error_1.FirebaseError(`Unsupported mode ${mode}. Supported modes are [${driver_1.SUPPORTED_MODES.join(", ")}]`);
16
18
  }
17
- const bundle = (0, compose_1.compose)(mode);
19
+ const bundle = await (0, compose_1.compose)(mode, new filesystem_1.LocalFileSystem("."), frameworkSpec_1.frameworkSpecs);
18
20
  logger_1.logger.info(JSON.stringify(bundle, null, 2));
19
21
  return {};
20
22
  });
@@ -16,7 +16,7 @@ const LINKS = [
16
16
  { name: "Analytics", arg: "analytics", consolePath: "/analytics" },
17
17
  { name: "Authentication: Providers", arg: "auth", consolePath: "/authentication/providers" },
18
18
  { name: "Authentication: Users", arg: "auth:users", consolePath: "/authentication/users" },
19
- { name: "Crash Reporting", arg: "crash", consolePath: "/monitoring" },
19
+ { name: "Crash Reporting", arg: "crash", consolePath: "/crashlytics" },
20
20
  { name: "Database: Data", arg: "database", consolePath: "/database/data" },
21
21
  { name: "Database: Rules", arg: "database:rules", consolePath: "/database/rules" },
22
22
  { name: "Docs", arg: "docs", url: "https://firebase.google.com/docs" },
@@ -38,7 +38,7 @@ const LINKS = [
38
38
  { name: "Functions", arg: "functions", consolePath: "/functions/list" },
39
39
  { name: "Functions Log", arg: "functions:log" },
40
40
  { name: "Hosting: Deployed Site", arg: "hosting:site" },
41
- { name: "Hosting", arg: "hosting", consolePath: "/hosting/main" },
41
+ { name: "Hosting", arg: "hosting", consolePath: "/hosting/sites" },
42
42
  { name: "Notifications", arg: "notifications", consolePath: "/notification" },
43
43
  { name: "Project Dashboard", arg: "dashboard", consolePath: "/overview" },
44
44
  { name: "Project Settings", arg: "settings", consolePath: "/settings/general" },
@@ -127,17 +127,19 @@ async function want(args) {
127
127
  return instanceSpecs;
128
128
  }
129
129
  exports.want = want;
130
- async function resolveVersion(ref) {
130
+ async function resolveVersion(ref, extension) {
131
131
  const extensionRef = refs.toExtensionRef(ref);
132
- const extension = await extensionsApi.getExtension(extensionRef);
133
- if (!ref.version || ref.version === "latest-approved") {
134
- if (!extension.latestApprovedVersion) {
132
+ if (!ref.version && (extension === null || extension === void 0 ? void 0 : extension.latestApprovedVersion)) {
133
+ return extension.latestApprovedVersion;
134
+ }
135
+ if (ref.version === "latest-approved") {
136
+ if (!(extension === null || extension === void 0 ? void 0 : extension.latestApprovedVersion)) {
135
137
  throw new error_1.FirebaseError(`${extensionRef} has not been published to Extensions Hub (https://extensions.dev). To install it, you must specify the version you want to install.`);
136
138
  }
137
139
  return extension.latestApprovedVersion;
138
140
  }
139
- if (ref.version === "latest") {
140
- if (!extension.latestVersion) {
141
+ if (!ref.version || ref.version === "latest") {
142
+ if (!(extension === null || extension === void 0 ? void 0 : extension.latestVersion)) {
141
143
  throw new error_1.FirebaseError(`${extensionRef} has no stable non-deprecated versions. If you wish to install a prerelease version, you must specify the version you want to install.`);
142
144
  }
143
145
  return extension.latestVersion;
@@ -8,7 +8,6 @@ const utils_1 = require("../../utils");
8
8
  const secretManager_1 = require("../../gcp/secretManager");
9
9
  const projects_1 = require("../../management/projects");
10
10
  const functional_1 = require("../../functional");
11
- const track_1 = require("../../track");
12
11
  const backend = require("./backend");
13
12
  const FAQ_URL = "https://firebase.google.com/support/faq#functions-runtime";
14
13
  const CLOUD_BUILD_API = "cloudbuild.googleapis.com";
@@ -30,7 +29,6 @@ async function defaultServiceAccount(e) {
30
29
  }
31
30
  exports.defaultServiceAccount = defaultServiceAccount;
32
31
  function nodeBillingError(projectId) {
33
- void (0, track_1.track)("functions_runtime_notices", "nodejs10_billing_error");
34
32
  return new error_1.FirebaseError(`Cloud Functions deployment requires the pay-as-you-go (Blaze) billing plan. To upgrade your project, visit the following URL:
35
33
 
36
34
  https://console.firebase.google.com/project/${projectId}/usage/details
@@ -40,7 +38,6 @@ For additional information about this requirement, see Firebase FAQs:
40
38
  ${FAQ_URL}`, { exit: 1 });
41
39
  }
42
40
  function nodePermissionError(projectId) {
43
- void (0, track_1.track)("functions_runtime_notices", "nodejs10_permission_error");
44
41
  return new error_1.FirebaseError(`Cloud Functions deployment requires the Cloud Build API to be enabled. The current credentials do not have permission to enable APIs for project ${clc.bold(projectId)}.
45
42
 
46
43
  Please ask a project owner to visit the following URL to enable Cloud Build:
@@ -15,7 +15,6 @@ const utils_1 = require("../../utils");
15
15
  const prepareFunctionsUpload_1 = require("./prepareFunctionsUpload");
16
16
  const prompts_1 = require("./prompts");
17
17
  const projectUtils_1 = require("../../projectUtils");
18
- const track_1 = require("../../track");
19
18
  const logger_1 = require("../../logger");
20
19
  const triggerRegionHelper_1 = require("./triggerRegionHelper");
21
20
  const checkIam_1 = require("./checkIam");
@@ -27,9 +26,6 @@ const applyHash_1 = require("./cache/applyHash");
27
26
  const backend_1 = require("./backend");
28
27
  const functional_1 = require("../../functional");
29
28
  exports.EVENTARC_SOURCE_ENV = "EVENTARC_CLOUD_EVENT_SOURCE";
30
- function hasUserConfig(config) {
31
- return Object.keys(config).length > 1;
32
- }
33
29
  async function prepare(context, options, payload) {
34
30
  var _a, _b;
35
31
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -55,6 +51,7 @@ async function prepare(context, options, payload) {
55
51
  if (checkAPIsEnabled[1]) {
56
52
  runtimeConfig = Object.assign(Object.assign({}, runtimeConfig), (await (0, prepareFunctionsUpload_1.getFunctionsConfig)(projectId)));
57
53
  }
54
+ context.codebaseDeployEvents = {};
58
55
  const wantBuilds = await loadCodebases(context.config, options, firebaseConfig, runtimeConfig, context.filters);
59
56
  const codebaseUsesEnvs = [];
60
57
  const wantBackends = {};
@@ -100,17 +97,24 @@ async function prepare(context, options, payload) {
100
97
  if (functionsEnv.hasUserEnvs(userEnvOpt) || hasEnvsFromParams) {
101
98
  codebaseUsesEnvs.push(codebase);
102
99
  }
100
+ context.codebaseDeployEvents[codebase] = {
101
+ fn_deploy_num_successes: 0,
102
+ fn_deploy_num_failures: 0,
103
+ fn_deploy_num_canceled: 0,
104
+ fn_deploy_num_skipped: 0,
105
+ };
103
106
  if (wantBuild.params.length > 0) {
104
107
  if (wantBuild.params.every((p) => p.type !== "secret")) {
105
- void (0, track_1.track)("functions_params_in_build", "env_only");
108
+ context.codebaseDeployEvents[codebase].params = "env_only";
106
109
  }
107
110
  else {
108
- void (0, track_1.track)("functions_params_in_build", "with_secrets");
111
+ context.codebaseDeployEvents[codebase].params = "with_secrets";
109
112
  }
110
113
  }
111
114
  else {
112
- void (0, track_1.track)("functions_params_in_build", "none");
115
+ context.codebaseDeployEvents[codebase].params = "none";
113
116
  }
117
+ context.codebaseDeployEvents[codebase].runtime = wantBuild.runtime;
114
118
  }
115
119
  validate.endpointsAreUnique(wantBackends);
116
120
  context.sources = {};
@@ -147,16 +151,6 @@ async function prepare(context, options, payload) {
147
151
  validate.endpointsAreValid(wantBackend);
148
152
  inferBlockingDetails(wantBackend);
149
153
  }
150
- const tag = hasUserConfig(runtimeConfig)
151
- ? codebaseUsesEnvs.length > 0
152
- ? "mixed"
153
- : "runtime_config"
154
- : codebaseUsesEnvs.length > 0
155
- ? "dotenv"
156
- : "none";
157
- void (0, track_1.track)("functions_codebase_deploy_env_method", tag);
158
- const codebaseCnt = Object.keys(payload.functions).length;
159
- void (0, track_1.track)("functions_codebase_deploy_count", codebaseCnt >= 5 ? "5+" : codebaseCnt.toString());
160
154
  const wantBackend = backend.merge(...Object.values(wantBackends));
161
155
  const haveBackend = backend.merge(...Object.values(haveBackends));
162
156
  await Promise.all(Object.values(wantBackend.requiredAPIs).map(({ api }) => {
@@ -303,6 +297,7 @@ async function loadCodebases(config, options, firebaseConfig, runtimeConfig, fil
303
297
  const firebaseEnvs = functionsEnv.loadFirebaseEnvs(firebaseConfig, projectId);
304
298
  (0, utils_1.logLabeledBullet)("functions", `Loading and anaylzing source code for codebase ${codebase} to determine what to deploy`);
305
299
  wantBuilds[codebase] = await runtimeDelegate.discoverBuild(runtimeConfig, Object.assign(Object.assign({}, firebaseEnvs), { GOOGLE_CLOUD_QUOTA_PROJECT: projectId }));
300
+ wantBuilds[codebase].runtime = codebaseConfig.runtime;
306
301
  }
307
302
  return wantBuilds;
308
303
  }
@@ -57,7 +57,7 @@ async function release(context, options, payload) {
57
57
  projectNumber: options.projectNumber || (await (0, getProjectNumber_1.getProjectNumber)(context.projectId)),
58
58
  });
59
59
  const summary = await fab.applyPlan(plan);
60
- await reporter.logAndTrackDeployStats(summary);
60
+ await reporter.logAndTrackDeployStats(summary, context);
61
61
  reporter.printErrors(summary);
62
62
  const wantBackend = backend.merge(...Object.values(payload.functions).map((p) => p.wantBackend));
63
63
  printTriggerUrls(wantBackend);
@@ -23,55 +23,72 @@ class AbortedDeploymentError extends DeploymentError {
23
23
  }
24
24
  }
25
25
  exports.AbortedDeploymentError = AbortedDeploymentError;
26
- async function logAndTrackDeployStats(summary) {
26
+ async function logAndTrackDeployStats(summary, context) {
27
+ var _a, _b, _c;
27
28
  let totalTime = 0;
28
29
  let totalErrors = 0;
29
30
  let totalSuccesses = 0;
30
31
  let totalAborts = 0;
31
32
  const reports = [];
32
33
  const regions = new Set();
34
+ const codebases = new Set();
33
35
  for (const result of summary.results) {
34
- const tag = triggerTag(result.endpoint);
36
+ const fnDeployEvent = {
37
+ platform: result.endpoint.platform,
38
+ trigger_type: backend.endpointTriggerType(result.endpoint),
39
+ region: result.endpoint.region,
40
+ runtime: result.endpoint.runtime,
41
+ status: !result.error
42
+ ? "success"
43
+ : result.error instanceof AbortedDeploymentError
44
+ ? "aborted"
45
+ : "failure",
46
+ duration: result.durationMs,
47
+ };
48
+ reports.push((0, track_1.trackGA4)("function_deploy", fnDeployEvent));
35
49
  regions.add(result.endpoint.region);
50
+ codebases.add(result.endpoint.codebase || "default");
36
51
  totalTime += result.durationMs;
37
52
  if (!result.error) {
38
53
  totalSuccesses++;
39
- reports.push((0, track_1.track)("function_deploy_success", tag, result.durationMs));
54
+ if (((_a = context === null || context === void 0 ? void 0 : context.codebaseDeployEvents) === null || _a === void 0 ? void 0 : _a[result.endpoint.codebase || "default"]) !== undefined) {
55
+ context.codebaseDeployEvents[result.endpoint.codebase || "default"]
56
+ .fn_deploy_num_successes++;
57
+ }
40
58
  }
41
59
  else if (result.error instanceof AbortedDeploymentError) {
42
60
  totalAborts++;
43
- reports.push((0, track_1.track)("function_deploy_abort", tag, result.durationMs));
61
+ if (((_b = context === null || context === void 0 ? void 0 : context.codebaseDeployEvents) === null || _b === void 0 ? void 0 : _b[result.endpoint.codebase || "default"]) !== undefined) {
62
+ context.codebaseDeployEvents[result.endpoint.codebase || "default"]
63
+ .fn_deploy_num_canceled++;
64
+ }
44
65
  }
45
66
  else {
46
67
  totalErrors++;
47
- reports.push((0, track_1.track)("function_deploy_failure", tag, result.durationMs));
68
+ if (((_c = context === null || context === void 0 ? void 0 : context.codebaseDeployEvents) === null || _c === void 0 ? void 0 : _c[result.endpoint.codebase || "default"]) !== undefined) {
69
+ context.codebaseDeployEvents[result.endpoint.codebase || "default"]
70
+ .fn_deploy_num_failures++;
71
+ }
48
72
  }
49
73
  }
50
- const regionCountTag = regions.size < 5 ? regions.size.toString() : ">=5";
51
- reports.push((0, track_1.track)("functions_region_count", regionCountTag, 1));
52
- const gcfv1 = summary.results.find((r) => r.endpoint.platform === "gcfv1");
53
- const gcfv2 = summary.results.find((r) => r.endpoint.platform === "gcfv2");
54
- const tag = gcfv1 && gcfv2 ? "v1+v2" : gcfv1 ? "v1" : "v2";
55
- reports.push((0, track_1.track)("functions_codebase_deploy", tag, summary.results.length));
74
+ for (const codebase of codebases) {
75
+ if (context === null || context === void 0 ? void 0 : context.codebaseDeployEvents) {
76
+ reports.push((0, track_1.trackGA4)("codebase_deploy", Object.assign({}, context.codebaseDeployEvents[codebase])));
77
+ }
78
+ }
79
+ const fnDeployGroupEvent = {
80
+ codebase_deploy_count: codebases.size >= 5 ? "5+" : codebases.size.toString(),
81
+ fn_deploy_num_successes: totalSuccesses,
82
+ fn_deploy_num_canceled: totalAborts,
83
+ fn_deploy_num_failures: totalErrors,
84
+ };
85
+ reports.push((0, track_1.trackGA4)("function_deploy_group", fnDeployGroupEvent));
56
86
  const avgTime = totalTime / (totalSuccesses + totalErrors);
57
87
  logger_1.logger.debug(`Total Function Deployment time: ${summary.totalTime}`);
58
88
  logger_1.logger.debug(`${totalErrors + totalSuccesses + totalAborts} Functions Deployed`);
59
89
  logger_1.logger.debug(`${totalErrors} Functions Errored`);
60
90
  logger_1.logger.debug(`${totalAborts} Function Deployments Aborted`);
61
91
  logger_1.logger.debug(`Average Function Deployment time: ${avgTime}`);
62
- if (totalErrors + totalSuccesses > 0) {
63
- if (totalErrors === 0) {
64
- reports.push((0, track_1.track)("functions_deploy_result", "success", totalSuccesses));
65
- }
66
- else if (totalSuccesses > 0) {
67
- reports.push((0, track_1.track)("functions_deploy_result", "partial_success", totalSuccesses));
68
- reports.push((0, track_1.track)("functions_deploy_result", "partial_failure", totalErrors));
69
- reports.push((0, track_1.track)("functions_deploy_result", "partial_error_ratio", totalErrors / (totalSuccesses + totalErrors)));
70
- }
71
- else {
72
- reports.push((0, track_1.track)("functions_deploy_result", "failure", totalErrors));
73
- }
74
- }
75
92
  await utils.allSettled(reports);
76
93
  }
77
94
  exports.logAndTrackDeployStats = logAndTrackDeployStats;
@@ -4,7 +4,6 @@ exports.getRuntimeChoice = exports.DEPRECATED_NODE_VERSION_INFO = exports.UNSUPP
4
4
  const path = require("path");
5
5
  const clc = require("colorette");
6
6
  const error_1 = require("../../../../error");
7
- const track_1 = require("../../../../track");
8
7
  const runtimes = require("../../runtimes");
9
8
  const cjson = require("cjson");
10
9
  const ENGINE_RUNTIMES = {
@@ -48,11 +47,9 @@ function getRuntimeChoice(sourceDir, runtimeFromConfig) {
48
47
  ? exports.UNSUPPORTED_NODE_VERSION_FIREBASE_JSON_MSG
49
48
  : exports.UNSUPPORTED_NODE_VERSION_PACKAGE_JSON_MSG) + exports.DEPRECATED_NODE_VERSION_INFO;
50
49
  if (!runtime || !ENGINE_RUNTIMES_NAMES.includes(runtime)) {
51
- void (0, track_1.track)("functions_runtime_notices", "package_missing_runtime");
52
50
  throw new error_1.FirebaseError(errorMessage, { exit: 1 });
53
51
  }
54
52
  if (runtimes.isDeprecatedRuntime(runtime) || !runtimes.isValidRuntime(runtime)) {
55
- void (0, track_1.track)("functions_runtime_notices", `${runtime}_deploy_prohibited`);
56
53
  throw new error_1.FirebaseError(errorMessage, { exit: 1 });
57
54
  }
58
55
  return runtime;
@@ -7,7 +7,6 @@ const clc = require("colorette");
7
7
  const spawn = require("cross-spawn");
8
8
  const semver = require("semver");
9
9
  const logger_1 = require("../../../../logger");
10
- const track_1 = require("../../../../track");
11
10
  const utils = require("../../../../utils");
12
11
  const MIN_SDK_VERSION = "2.0.0";
13
12
  const NPM_COMMAND_TIMEOUT_MILLIES = 10000;
@@ -70,7 +69,6 @@ exports.getLatestSDKVersion = getLatestSDKVersion;
70
69
  function checkFunctionsSDKVersion(currentVersion) {
71
70
  try {
72
71
  if (semver.lt(currentVersion, MIN_SDK_VERSION)) {
73
- void (0, track_1.track)("functions_runtime_notices", "functions_sdk_too_old");
74
72
  utils.logWarning(exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING);
75
73
  }
76
74
  const latest = exports.getLatestSDKVersion();
@@ -109,17 +109,36 @@ function getReleventConfigs(target, options) {
109
109
  }
110
110
  onlyTargets = onlyTargets
111
111
  .filter((individualOnly) => {
112
- return individualOnly.indexOf(`${target}:`) === 0;
112
+ return individualOnly.startsWith(`${target}:`);
113
113
  })
114
114
  .map((individualOnly) => {
115
115
  return individualOnly.replace(`${target}:`, "");
116
116
  });
117
- return targetConfigs.filter((config) => {
118
- if (target === "functions") {
119
- return onlyTargets.includes(config.codebase);
117
+ if (target === "functions") {
118
+ let onlyConfigs = [];
119
+ const matched = onlyTargets.reduce((matched, target) => (Object.assign(Object.assign({}, matched), { [target]: false })), {});
120
+ for (const config of targetConfigs) {
121
+ if (!config.codebase) {
122
+ onlyConfigs.push(config);
123
+ }
124
+ else {
125
+ const found = onlyTargets.find((individualOnly) => config.codebase === individualOnly.split(":")[0]);
126
+ if (found) {
127
+ onlyConfigs.push(config);
128
+ matched[found] = true;
129
+ }
130
+ }
120
131
  }
121
- return !config.target || onlyTargets.includes(config.target);
122
- });
132
+ if (!Object.values(matched).every((matched) => matched)) {
133
+ onlyConfigs = targetConfigs;
134
+ }
135
+ return onlyConfigs;
136
+ }
137
+ else {
138
+ return targetConfigs.filter((config) => {
139
+ return !config.target || onlyTargets.includes(config.target);
140
+ });
141
+ }
123
142
  }
124
143
  function lifecycleHooks(target, hook) {
125
144
  return function (context, options) {
@@ -35,9 +35,9 @@ const EMULATOR_UPDATE_DETAILS = {
35
35
  ui: experiments.isEnabled("emulatoruisnapshot")
36
36
  ? { version: "SNAPSHOT", expectedSize: -1, expectedChecksum: "" }
37
37
  : {
38
- version: "1.11.6",
39
- expectedSize: 3063444,
40
- expectedChecksum: "14b971f4ed4909f348e647db7114d62b",
38
+ version: "1.11.7",
39
+ expectedSize: 3064105,
40
+ expectedChecksum: "bd2bcc331cbf613a5b3b55a1ce08998b",
41
41
  },
42
42
  pubsub: {
43
43
  version: "0.7.1",