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.
- package/lib/commands/ext-configure.js +0 -1
- package/lib/commands/ext-install.js +56 -56
- package/lib/commands/ext-update.js +0 -1
- package/lib/commands/index.js +0 -2
- package/lib/commands/internaltesting-frameworks-compose.js +4 -2
- package/lib/commands/open.js +2 -2
- package/lib/deploy/extensions/planner.js +8 -6
- package/lib/deploy/functions/ensure.js +0 -3
- package/lib/deploy/functions/prepare.js +12 -17
- package/lib/deploy/functions/release/index.js +1 -1
- package/lib/deploy/functions/release/reporter.js +41 -24
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +0 -3
- package/lib/deploy/functions/runtimes/node/versioning.js +0 -2
- package/lib/deploy/lifecycleHooks.js +25 -6
- package/lib/emulator/downloadableEmulators.js +3 -3
- package/lib/extensions/displayExtensionInfo.js +104 -42
- package/lib/extensions/emulator/triggerHelper.js +1 -1
- package/lib/extensions/extensionsApi.js +1 -1
- package/lib/extensions/extensionsHelper.js +19 -30
- package/lib/extensions/publisherApi.js +1 -2
- package/lib/extensions/updateHelper.js +2 -2
- package/lib/frameworks/compose/discover/filesystem.js +1 -1
- package/lib/frameworks/compose/discover/index.js +27 -18
- package/lib/frameworks/compose/discover/runtime/node.js +149 -0
- package/lib/frameworks/compose/driver/docker.js +23 -13
- package/lib/frameworks/compose/driver/local.js +13 -4
- package/lib/frameworks/compose/index.js +9 -8
- package/lib/frameworks/next/index.js +13 -4
- package/lib/{api → gcp}/frameworks.js +7 -5
- package/lib/init/features/frameworks/index.js +31 -1
- package/lib/init/features/{composer → frameworks}/repo.js +1 -4
- package/package.json +1 -1
- package/schema/firebase-config.json +4 -0
- package/lib/commands/internaltesting-frameworks-init.js +0 -14
|
@@ -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 [
|
|
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 (
|
|
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 (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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(
|
|
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 (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
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,
|
|
127
|
-
const isLocalSource = (0, extensionsHelper_1.isLocalPath)(
|
|
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 ${
|
|
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 ?
|
|
161
|
+
localPath: isLocalSource ? extensionRef : undefined,
|
|
162
162
|
params: paramBindingOptions,
|
|
163
163
|
extensionSpec: spec,
|
|
164
164
|
},
|
package/lib/commands/index.js
CHANGED
|
@@ -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
|
});
|
package/lib/commands/open.js
CHANGED
|
@@ -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: "/
|
|
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/
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
108
|
+
context.codebaseDeployEvents[codebase].params = "env_only";
|
|
106
109
|
}
|
|
107
110
|
else {
|
|
108
|
-
|
|
111
|
+
context.codebaseDeployEvents[codebase].params = "with_secrets";
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
else {
|
|
112
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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.
|
|
112
|
+
return individualOnly.startsWith(`${target}:`);
|
|
113
113
|
})
|
|
114
114
|
.map((individualOnly) => {
|
|
115
115
|
return individualOnly.replace(`${target}:`, "");
|
|
116
116
|
});
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
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.
|
|
39
|
-
expectedSize:
|
|
40
|
-
expectedChecksum: "
|
|
38
|
+
version: "1.11.7",
|
|
39
|
+
expectedSize: 3064105,
|
|
40
|
+
expectedChecksum: "bd2bcc331cbf613a5b3b55a1ce08998b",
|
|
41
41
|
},
|
|
42
42
|
pubsub: {
|
|
43
43
|
version: "0.7.1",
|