firebase-tools 10.2.0 → 10.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/apiv2.js +3 -0
- package/lib/appdistribution/options-parser-util.js +1 -1
- package/lib/auth.js +3 -3
- package/lib/command.js +1 -1
- package/lib/commands/apps-android-sha-create.js +2 -2
- package/lib/commands/apps-sdkconfig.js +1 -1
- package/lib/commands/auth-import.js +1 -1
- package/lib/commands/database-rules-list.js +2 -2
- package/lib/commands/emulators-start.js +1 -1
- package/lib/commands/ext-configure.js +58 -4
- package/lib/commands/ext-dev-init.js +49 -49
- package/lib/commands/ext-export.js +7 -2
- package/lib/commands/ext-install.js +163 -104
- package/lib/commands/ext-uninstall.js +17 -8
- package/lib/commands/ext-update.js +64 -11
- package/lib/commands/functions-config-clone.js +1 -1
- package/lib/commands/functions-config-export.js +1 -1
- package/lib/commands/hosting-clone.js +3 -3
- package/lib/commands/remoteconfig-get.js +1 -1
- package/lib/config.js +6 -3
- package/lib/deploy/extensions/deploymentSummary.js +3 -3
- package/lib/deploy/extensions/planner.js +7 -6
- package/lib/deploy/extensions/tasks.js +1 -1
- package/lib/deploy/functions/backend.js +21 -5
- package/lib/deploy/functions/checkIam.js +5 -5
- package/lib/deploy/functions/containerCleaner.js +3 -3
- package/lib/deploy/functions/ensure.js +3 -3
- package/lib/deploy/functions/functionsDeployHelper.js +2 -2
- package/lib/deploy/functions/prepare.js +5 -3
- package/lib/deploy/functions/pricing.js +1 -1
- package/lib/deploy/functions/prompts.js +2 -2
- package/lib/deploy/functions/release/fabricator.js +7 -7
- package/lib/deploy/functions/release/index.js +1 -1
- package/lib/deploy/functions/release/planner.js +43 -26
- package/lib/deploy/functions/release/reporter.js +3 -0
- package/lib/deploy/functions/runtimes/discovery/index.js +6 -6
- package/lib/deploy/functions/runtimes/discovery/parsing.js +1 -1
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +22 -12
- package/lib/deploy/functions/runtimes/golang/index.js +2 -2
- package/lib/deploy/functions/runtimes/node/index.js +53 -0
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +2 -2
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +52 -15
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/services/firebaseAlerts.js +30 -0
- package/lib/deploy/functions/services/index.js +9 -1
- package/lib/deploy/functions/services/storage.js +10 -4
- package/lib/deploy/functions/triggerRegionHelper.js +1 -1
- package/lib/deploy/functions/validate.js +3 -3
- package/lib/deploy/hosting/client.js +9 -0
- package/lib/deploy/hosting/convertConfig.js +6 -0
- package/lib/deploy/hosting/deploy.js +2 -2
- package/lib/deploy/hosting/hashcache.js +21 -19
- package/lib/deploy/hosting/index.js +5 -5
- package/lib/deploy/hosting/prepare.js +25 -25
- package/lib/deploy/hosting/release.js +21 -24
- package/lib/deploy/hosting/uploader.js +5 -5
- package/lib/deploy/remoteconfig/functions.js +2 -2
- package/lib/emulator/auth/cloudFunctions.js +1 -1
- package/lib/emulator/auth/operations.js +1 -1
- package/lib/emulator/commandUtils.js +5 -1
- package/lib/emulator/constants.js +4 -0
- package/lib/emulator/controller.js +54 -24
- package/lib/emulator/download.js +18 -1
- package/lib/emulator/downloadableEmulators.js +30 -13
- package/lib/emulator/emulatorLogger.js +12 -1
- package/lib/emulator/extensions/validation.js +70 -0
- package/lib/emulator/extensionsEmulator.js +175 -0
- package/lib/emulator/functionsEmulator.js +106 -44
- package/lib/emulator/functionsEmulatorRuntime.js +44 -36
- package/lib/emulator/functionsEmulatorShared.js +17 -10
- package/lib/emulator/functionsEmulatorShell.js +1 -1
- package/lib/emulator/functionsEmulatorUtils.js +4 -4
- package/lib/emulator/functionsRuntimeWorker.js +2 -2
- package/lib/emulator/hub.js +4 -3
- package/lib/emulator/loggingEmulator.js +1 -1
- package/lib/emulator/pubsubEmulator.js +1 -1
- package/lib/emulator/registry.js +10 -2
- package/lib/emulator/storage/apis/firebase.js +314 -332
- package/lib/emulator/storage/apis/gcloud.js +241 -121
- package/lib/emulator/storage/crc.js +5 -1
- package/lib/emulator/storage/errors.js +9 -0
- package/lib/emulator/storage/files.js +159 -300
- package/lib/emulator/storage/index.js +27 -73
- package/lib/emulator/storage/metadata.js +65 -51
- package/lib/emulator/storage/multipart.js +62 -0
- package/lib/emulator/storage/persistence.js +78 -0
- package/lib/emulator/storage/rules/config.js +33 -0
- package/lib/emulator/storage/rules/manager.js +81 -0
- package/lib/emulator/storage/rules/runtime.js +8 -7
- package/lib/emulator/storage/rules/utils.js +48 -0
- package/lib/emulator/storage/server.js +2 -2
- package/lib/emulator/storage/upload.js +106 -0
- package/lib/emulator/types.js +3 -0
- package/lib/ensureApiEnabled.js +5 -1
- package/lib/error.js +1 -1
- package/lib/extensions/askUserForParam.js +1 -1
- package/lib/extensions/changelog.js +3 -1
- package/lib/extensions/checkProjectBilling.js +1 -1
- package/lib/extensions/displayExtensionInfo.js +1 -1
- package/lib/extensions/emulator/optionsHelper.js +56 -8
- package/lib/extensions/emulator/specHelper.js +10 -23
- package/lib/extensions/export.js +1 -51
- package/lib/extensions/extensionsApi.js +1 -1
- package/lib/extensions/extensionsHelper.js +32 -19
- package/lib/extensions/listExtensions.js +2 -0
- package/lib/extensions/manifest.js +144 -0
- package/lib/extensions/metricsUtils.js +4 -4
- package/lib/extensions/paramHelper.js +9 -8
- package/lib/extensions/refs.js +1 -1
- package/lib/extensions/secretsUtils.js +3 -3
- package/lib/functional.js +1 -1
- package/lib/functions/env.js +6 -7
- package/lib/functions/events/v2.js +11 -0
- package/lib/gcp/cloudfunctions.js +42 -11
- package/lib/gcp/cloudfunctionsv2.js +48 -17
- package/lib/gcp/cloudtasks.js +1 -1
- package/lib/gcp/docker.js +2 -2
- package/lib/gcp/resourceManager.js +4 -4
- package/lib/gcp/run.js +2 -2
- package/lib/gcp/storage.js +1 -0
- package/lib/hosting/api.js +1 -1
- package/lib/hosting/functionsProxy.js +15 -5
- package/lib/hosting/proxy.js +2 -2
- package/lib/init/features/account.js +1 -1
- package/lib/management/database.js +1 -1
- package/lib/previews.js +1 -1
- package/lib/responseToError.js +16 -7
- package/lib/serve/functions.js +2 -1
- package/lib/serve/hosting.js +1 -1
- package/lib/utils.js +15 -2
- package/npm-shrinkwrap.json +904 -412
- package/package.json +3 -3
- package/schema/firebase-config.json +32 -0
- package/templates/init/functions/javascript/package.lint.json +3 -3
- package/templates/init/functions/javascript/package.nolint.json +2 -2
- package/templates/init/functions/typescript/package.lint.json +7 -7
- package/templates/init/functions/typescript/package.nolint.json +3 -3
- package/lib/deploy/extensions/params.js +0 -39
- package/lib/deploy/functions/eventTypes.js +0 -10
|
@@ -16,25 +16,25 @@ const prompt_1 = require("../prompt");
|
|
|
16
16
|
const requirePermissions_1 = require("../requirePermissions");
|
|
17
17
|
const utils = require("../utils");
|
|
18
18
|
const logger_1 = require("../logger");
|
|
19
|
+
const manifest = require("../extensions/manifest");
|
|
19
20
|
marked.setOptions({
|
|
20
21
|
renderer: new TerminalRenderer(),
|
|
21
22
|
});
|
|
22
|
-
function consoleUninstallOnly(projectId, instanceId) {
|
|
23
|
-
const instanceURL = `https://console.firebase.google.com/project/${projectId}/extensions/instances/${instanceId}`;
|
|
24
|
-
const consoleUninstall = "This extension has additional uninstall checks that are not currently supported by the CLI, and can only be uninstalled through the Firebase Console. " +
|
|
25
|
-
`Please visit **[${instanceURL}](${instanceURL})** to uninstall this extension.`;
|
|
26
|
-
logger_1.logger.info("\n");
|
|
27
|
-
utils.logLabeledWarning(extensionsHelper_1.logPrefix, marked(consoleUninstall));
|
|
28
|
-
return Promise.resolve();
|
|
29
|
-
}
|
|
30
23
|
exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
|
|
31
24
|
.description("uninstall an extension that is installed in your Firebase project by instance ID")
|
|
32
25
|
.withForce()
|
|
26
|
+
.option("--local", "remove from firebase.json rather than directly uninstall from a Firebase project")
|
|
33
27
|
.before(requirePermissions_1.requirePermissions, ["firebaseextensions.instances.delete"])
|
|
34
28
|
.before(extensionsHelper_1.ensureExtensionsApiEnabled)
|
|
35
29
|
.before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
|
|
36
30
|
.before(extensionsHelper_1.diagnoseAndFixProject)
|
|
37
31
|
.action(async (instanceId, options) => {
|
|
32
|
+
if (options.local) {
|
|
33
|
+
const config = manifest.loadConfig(options);
|
|
34
|
+
manifest.removeFromManifest(instanceId, config);
|
|
35
|
+
manifest.showPreviewWarning();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
38
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
39
39
|
let instance;
|
|
40
40
|
try {
|
|
@@ -101,4 +101,13 @@ exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
|
|
|
101
101
|
return utils.reject(`Error occurred uninstalling extension ${instanceId}`, { original: err });
|
|
102
102
|
}
|
|
103
103
|
utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `uninstalled ${clc.bold(instanceId)}`);
|
|
104
|
+
manifest.showDeprecationWarning();
|
|
104
105
|
});
|
|
106
|
+
function consoleUninstallOnly(projectId, instanceId) {
|
|
107
|
+
const instanceURL = `https://console.firebase.google.com/project/${projectId}/extensions/instances/${instanceId}`;
|
|
108
|
+
const consoleUninstall = "This extension has additional uninstall checks that are not currently supported by the CLI, and can only be uninstalled through the Firebase Console. " +
|
|
109
|
+
`Please visit **[${instanceURL}](${instanceURL})** to uninstall this extension.`;
|
|
110
|
+
logger_1.logger.info("\n");
|
|
111
|
+
utils.logLabeledWarning(extensionsHelper_1.logPrefix, marked(consoleUninstall));
|
|
112
|
+
return Promise.resolve();
|
|
113
|
+
}
|
|
@@ -22,18 +22,10 @@ const projectUtils_1 = require("../projectUtils");
|
|
|
22
22
|
const requirePermissions_1 = require("../requirePermissions");
|
|
23
23
|
const utils = require("../utils");
|
|
24
24
|
const previews_1 = require("../previews");
|
|
25
|
+
const manifest = require("../extensions/manifest");
|
|
25
26
|
marked.setOptions({
|
|
26
27
|
renderer: new TerminalRenderer(),
|
|
27
28
|
});
|
|
28
|
-
function isValidUpdate(existingSourceOrigin, newSourceOrigin) {
|
|
29
|
-
if (existingSourceOrigin === extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION) {
|
|
30
|
-
return [extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION, extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION_VERSION].includes(newSourceOrigin);
|
|
31
|
-
}
|
|
32
|
-
else if (existingSourceOrigin === extensionsHelper_1.SourceOrigin.LOCAL) {
|
|
33
|
-
return [extensionsHelper_1.SourceOrigin.LOCAL, extensionsHelper_1.SourceOrigin.URL].includes(newSourceOrigin);
|
|
34
|
-
}
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
29
|
exports.default = new command_1.Command("ext:update <extensionInstanceId> [updateSource]")
|
|
38
30
|
.description(previews_1.previews.extdev
|
|
39
31
|
? "update an existing extension instance to the latest version or from a local or URL source"
|
|
@@ -47,10 +39,61 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
47
39
|
.before(extensionsHelper_1.diagnoseAndFixProject)
|
|
48
40
|
.withForce()
|
|
49
41
|
.option("--params <paramsFile>", "name of params variables file with .env format.")
|
|
42
|
+
.option("--local", "save the update to firebase.json rather than directly update an existing Extension instance on a Firebase project")
|
|
50
43
|
.action(async (instanceId, updateSource, options) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
46
|
+
if (options.local) {
|
|
47
|
+
const config = manifest.loadConfig(options);
|
|
48
|
+
const oldRef = manifest.getInstanceRef(instanceId, config);
|
|
49
|
+
const oldExtensionVersion = await extensionsApi.getExtensionVersion(refs.toExtensionVersionRef(oldRef));
|
|
50
|
+
updateSource = (0, updateHelper_1.inferUpdateSource)(updateSource, refs.toExtensionRef(oldRef));
|
|
51
|
+
const newSourceOrigin = (0, extensionsHelper_1.getSourceOrigin)(updateSource);
|
|
52
|
+
if (![extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION, extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION_VERSION].includes(newSourceOrigin)) {
|
|
53
|
+
throw new error_1.FirebaseError(`Only updating to a published extension version is allowed`);
|
|
54
|
+
}
|
|
55
|
+
const newExtensionVersion = await extensionsApi.getExtensionVersion(updateSource);
|
|
56
|
+
if (oldExtensionVersion.ref === newExtensionVersion.ref) {
|
|
57
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, `${clc.bold(instanceId)} is already up to date. Its version is ${clc.bold(newExtensionVersion.ref)}.`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, `Updating ${clc.bold(instanceId)} from version ${clc.bold(oldExtensionVersion.ref)} to version ${clc.bold(newExtensionVersion.ref)}.`);
|
|
61
|
+
if (!(await (0, extensionsHelper_1.confirm)({
|
|
62
|
+
nonInteractive: options.nonInteractive,
|
|
63
|
+
force: options.force,
|
|
64
|
+
default: false,
|
|
65
|
+
}))) {
|
|
66
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, "Update aborted.");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const oldParamValues = manifest.readInstanceParam({
|
|
70
|
+
instanceId,
|
|
71
|
+
projectDir: config.projectDir,
|
|
72
|
+
});
|
|
73
|
+
const newParams = await paramHelper.getParamsForUpdate({
|
|
74
|
+
spec: oldExtensionVersion.spec,
|
|
75
|
+
newSpec: newExtensionVersion.spec,
|
|
76
|
+
currentParams: oldParamValues,
|
|
77
|
+
projectId,
|
|
78
|
+
paramsEnvPath: ((_a = options.params) !== null && _a !== void 0 ? _a : ""),
|
|
79
|
+
nonInteractive: options.nonInteractive,
|
|
80
|
+
instanceId,
|
|
81
|
+
});
|
|
82
|
+
await manifest.writeToManifest([
|
|
83
|
+
{
|
|
84
|
+
instanceId,
|
|
85
|
+
ref: refs.parse(newExtensionVersion.ref),
|
|
86
|
+
params: newParams,
|
|
87
|
+
},
|
|
88
|
+
], config, {
|
|
89
|
+
nonInteractive: options.nonInteractive,
|
|
90
|
+
force: true,
|
|
91
|
+
});
|
|
92
|
+
manifest.showPreviewWarning();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
51
95
|
const spinner = ora(`Updating ${clc.bold(instanceId)}. This usually takes 3 to 5 minutes...`);
|
|
52
96
|
try {
|
|
53
|
-
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
54
97
|
let existingInstance;
|
|
55
98
|
try {
|
|
56
99
|
existingInstance = await extensionsApi.getInstance(projectId, instanceId);
|
|
@@ -157,7 +200,7 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
157
200
|
newSpec,
|
|
158
201
|
currentParams: existingParams,
|
|
159
202
|
projectId,
|
|
160
|
-
paramsEnvPath: options.params,
|
|
203
|
+
paramsEnvPath: ((_b = options.params) !== null && _b !== void 0 ? _b : ""),
|
|
161
204
|
nonInteractive: options.nonInteractive,
|
|
162
205
|
instanceId,
|
|
163
206
|
});
|
|
@@ -179,6 +222,7 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
179
222
|
spinner.stop();
|
|
180
223
|
utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `successfully updated ${clc.bold(instanceId)}.`);
|
|
181
224
|
utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`You can view your updated instance in the Firebase console: ${utils.consoleUrl(projectId, `/extensions/instances/${instanceId}?tab=usage`)}`));
|
|
225
|
+
manifest.showDeprecationWarning();
|
|
182
226
|
}
|
|
183
227
|
catch (err) {
|
|
184
228
|
if (spinner.isSpinning) {
|
|
@@ -192,3 +236,12 @@ exports.default = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
192
236
|
throw err;
|
|
193
237
|
}
|
|
194
238
|
});
|
|
239
|
+
function isValidUpdate(existingSourceOrigin, newSourceOrigin) {
|
|
240
|
+
if (existingSourceOrigin === extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION) {
|
|
241
|
+
return [extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION, extensionsHelper_1.SourceOrigin.PUBLISHED_EXTENSION_VERSION].includes(newSourceOrigin);
|
|
242
|
+
}
|
|
243
|
+
else if (existingSourceOrigin === extensionsHelper_1.SourceOrigin.LOCAL) {
|
|
244
|
+
return [extensionsHelper_1.SourceOrigin.LOCAL, extensionsHelper_1.SourceOrigin.URL].includes(newSourceOrigin);
|
|
245
|
+
}
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
@@ -38,7 +38,7 @@ exports.default = new command_1.Command("functions:config:clone")
|
|
|
38
38
|
else if (options.only && options.except) {
|
|
39
39
|
throw new error_1.FirebaseError("Cannot use both --only and --except at the same time.");
|
|
40
40
|
}
|
|
41
|
-
let only
|
|
41
|
+
let only;
|
|
42
42
|
let except = [];
|
|
43
43
|
if (options.only) {
|
|
44
44
|
only = options.only.split(",");
|
|
@@ -96,7 +96,7 @@ exports.default = new command_1.Command("functions:config:export")
|
|
|
96
96
|
throw new error_1.FirebaseError("Exceeded max attempts to fix invalid config keys.");
|
|
97
97
|
}
|
|
98
98
|
const errMsg = configExport.hydrateEnvs(pInfos, prefix);
|
|
99
|
-
if (errMsg.length
|
|
99
|
+
if (errMsg.length === 0) {
|
|
100
100
|
break;
|
|
101
101
|
}
|
|
102
102
|
prefix = await promptForPrefix(errMsg);
|
|
@@ -32,8 +32,8 @@ exports.default = new command_1.Command("hosting:clone <source> <targetChannel>"
|
|
|
32
32
|
if (sourceChannelId) {
|
|
33
33
|
sourceChannelId = (0, api_1.normalizeName)(sourceChannelId);
|
|
34
34
|
}
|
|
35
|
-
const equalSiteIds = sourceSiteId
|
|
36
|
-
const equalChannelIds = sourceChannelId
|
|
35
|
+
const equalSiteIds = sourceSiteId === targetSiteId;
|
|
36
|
+
const equalChannelIds = sourceChannelId === targetChannelId;
|
|
37
37
|
if (equalSiteIds && equalChannelIds) {
|
|
38
38
|
throw new error_1.FirebaseError(`Source and destination cannot be equal. Please pick a different source or desination.`);
|
|
39
39
|
}
|
|
@@ -67,7 +67,7 @@ exports.default = new command_1.Command("hosting:clone <source> <targetChannel>"
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
const currentTargetVersionName = (_d = (_c = tChannel.release) === null || _c === void 0 ? void 0 : _c.version) === null || _d === void 0 ? void 0 : _d.name;
|
|
70
|
-
if (equalSiteIds && sourceVersionName
|
|
70
|
+
if (equalSiteIds && sourceVersionName === currentTargetVersionName) {
|
|
71
71
|
utils.logSuccess(`Channels ${(0, cli_color_1.bold)(sourceChannelId)} and ${(0, cli_color_1.bold)(targetChannel)} are serving identical versions. No need to clone.`);
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
@@ -15,7 +15,7 @@ const error_1 = require("../error");
|
|
|
15
15
|
const tableHead = ["Entry Name", "Value"];
|
|
16
16
|
const MAX_DISPLAY_ITEMS = 20;
|
|
17
17
|
function checkValidOptionalNumber(versionNumber) {
|
|
18
|
-
if (!versionNumber || typeof Number(versionNumber)
|
|
18
|
+
if (!versionNumber || typeof Number(versionNumber) === "number") {
|
|
19
19
|
return versionNumber;
|
|
20
20
|
}
|
|
21
21
|
throw new error_1.FirebaseError(`Could not interpret "${versionNumber}" as a valid number.`);
|
package/lib/config.js
CHANGED
|
@@ -17,12 +17,12 @@ const logger_1 = require("./logger");
|
|
|
17
17
|
const loadCJSON = require("./loadCJSON");
|
|
18
18
|
const parseBoltRules = require("./parseBoltRules");
|
|
19
19
|
class Config {
|
|
20
|
-
constructor(src, options) {
|
|
20
|
+
constructor(src, options = {}) {
|
|
21
21
|
this.data = {};
|
|
22
22
|
this.defaults = {};
|
|
23
23
|
this.notes = {};
|
|
24
|
-
this.options = options
|
|
25
|
-
this.projectDir = options.projectDir || (0, detectProjectRoot_1.detectProjectRoot)(options);
|
|
24
|
+
this.options = options;
|
|
25
|
+
this.projectDir = this.options.projectDir || (0, detectProjectRoot_1.detectProjectRoot)(this.options);
|
|
26
26
|
this._src = src;
|
|
27
27
|
if (this._src.firebase) {
|
|
28
28
|
this.defaults.project = this._src.firebase;
|
|
@@ -144,6 +144,9 @@ class Config {
|
|
|
144
144
|
fs.ensureFileSync(this.path(p));
|
|
145
145
|
fs.writeFileSync(this.path(p), content, "utf8");
|
|
146
146
|
}
|
|
147
|
+
deleteProjectFile(p) {
|
|
148
|
+
fs.removeSync(this.path(p));
|
|
149
|
+
}
|
|
147
150
|
askWriteProjectFile(p, content, force) {
|
|
148
151
|
const writeTo = this.path(p);
|
|
149
152
|
let next;
|
|
@@ -7,8 +7,8 @@ const humanReadable = (dep) => `${clc.bold(dep.instanceId)} (${dep.ref ? `${refs
|
|
|
7
7
|
exports.humanReadable = humanReadable;
|
|
8
8
|
const humanReadableUpdate = (from, to) => {
|
|
9
9
|
var _a, _b, _c, _d, _e;
|
|
10
|
-
if (((_a = from.ref) === null || _a === void 0 ? void 0 : _a.publisherId)
|
|
11
|
-
((_c = from.ref) === null || _c === void 0 ? void 0 : _c.extensionId)
|
|
10
|
+
if (((_a = from.ref) === null || _a === void 0 ? void 0 : _a.publisherId) === ((_b = to.ref) === null || _b === void 0 ? void 0 : _b.publisherId) &&
|
|
11
|
+
((_c = from.ref) === null || _c === void 0 ? void 0 : _c.extensionId) === ((_d = to.ref) === null || _d === void 0 ? void 0 : _d.extensionId)) {
|
|
12
12
|
return `\t${clc.bold(from.instanceId)} (${refs.toExtensionVersionRef(from.ref)} => ${(_e = to.ref) === null || _e === void 0 ? void 0 : _e.version})`;
|
|
13
13
|
}
|
|
14
14
|
else {
|
|
@@ -28,7 +28,7 @@ exports.createsSummary = createsSummary;
|
|
|
28
28
|
function updatesSummary(toUpdate, have) {
|
|
29
29
|
const instancesToUpdate = toUpdate
|
|
30
30
|
.map((to) => {
|
|
31
|
-
const from = have.find((exists) => exists.instanceId
|
|
31
|
+
const from = have.find((exists) => exists.instanceId === to.instanceId);
|
|
32
32
|
return humanReadableUpdate(from, to);
|
|
33
33
|
})
|
|
34
34
|
.join("\n");
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveVersion = exports.want = exports.have = exports.getExtension = exports.getExtensionVersion = void 0;
|
|
4
4
|
const semver = require("semver");
|
|
5
|
-
const error_1 = require("../../error");
|
|
6
5
|
const extensionsApi = require("../../extensions/extensionsApi");
|
|
7
|
-
const extensionsHelper_1 = require("../../extensions/extensionsHelper");
|
|
8
6
|
const refs = require("../../extensions/refs");
|
|
9
|
-
const
|
|
7
|
+
const error_1 = require("../../error");
|
|
8
|
+
const extensionsHelper_1 = require("../../extensions/extensionsHelper");
|
|
10
9
|
const logger_1 = require("../../logger");
|
|
10
|
+
const manifest_1 = require("../../extensions/manifest");
|
|
11
11
|
async function getExtensionVersion(i) {
|
|
12
12
|
if (!i.extensionVersion) {
|
|
13
13
|
if (!i.ref) {
|
|
@@ -52,14 +52,15 @@ async function want(args) {
|
|
|
52
52
|
const instanceId = e[0];
|
|
53
53
|
const ref = refs.parse(e[1]);
|
|
54
54
|
ref.version = await resolveVersion(ref);
|
|
55
|
-
const params = (0,
|
|
55
|
+
const params = (0, manifest_1.readInstanceParam)({
|
|
56
56
|
projectDir: args.projectDir,
|
|
57
57
|
instanceId,
|
|
58
58
|
projectId: args.projectId,
|
|
59
59
|
projectNumber: args.projectNumber,
|
|
60
60
|
aliases: args.aliases,
|
|
61
|
+
checkLocal: args.emulatorMode,
|
|
61
62
|
});
|
|
62
|
-
const autoPopulatedParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId);
|
|
63
|
+
const autoPopulatedParams = await (0, extensionsHelper_1.getFirebaseProjectParams)(args.projectId, args.emulatorMode);
|
|
63
64
|
const subbedParams = (0, extensionsHelper_1.substituteParams)(params, autoPopulatedParams);
|
|
64
65
|
instanceSpecs.push({
|
|
65
66
|
instanceId,
|
|
@@ -80,7 +81,7 @@ async function want(args) {
|
|
|
80
81
|
}
|
|
81
82
|
exports.want = want;
|
|
82
83
|
async function resolveVersion(ref) {
|
|
83
|
-
if (!ref.version || ref.version
|
|
84
|
+
if (!ref.version || ref.version === "latest") {
|
|
84
85
|
return "latest";
|
|
85
86
|
}
|
|
86
87
|
const extensionRef = refs.toExtensionRef(ref);
|
|
@@ -5,7 +5,7 @@ const clc = require("cli-color");
|
|
|
5
5
|
const extensionsApi = require("../../extensions/extensionsApi");
|
|
6
6
|
const refs = require("../../extensions/refs");
|
|
7
7
|
const utils = require("../../utils");
|
|
8
|
-
const isRetryable = (err) => err.status
|
|
8
|
+
const isRetryable = (err) => err.status === 429 || err.status === 409;
|
|
9
9
|
function extensionsDeploymentHandler(errorHandler) {
|
|
10
10
|
return async (task) => {
|
|
11
11
|
var _a, _b, _c, _d;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.of = exports.empty = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isHttpsTriggered = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_MEMORY_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.memoryOptionDisplayName = exports.endpointTriggerType = void 0;
|
|
3
|
+
exports.compareFunctions = exports.findEventFilter = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.of = exports.empty = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_MEMORY_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.memoryOptionDisplayName = exports.endpointTriggerType = void 0;
|
|
4
4
|
const gcf = require("../../gcp/cloudfunctions");
|
|
5
5
|
const gcfV2 = require("../../gcp/cloudfunctionsv2");
|
|
6
6
|
const utils = require("../../utils");
|
|
@@ -13,6 +13,9 @@ function endpointTriggerType(endpoint) {
|
|
|
13
13
|
else if (isHttpsTriggered(endpoint)) {
|
|
14
14
|
return "https";
|
|
15
15
|
}
|
|
16
|
+
else if (isCallableTriggered(endpoint)) {
|
|
17
|
+
return "callable";
|
|
18
|
+
}
|
|
16
19
|
else if (isEventTriggered(endpoint)) {
|
|
17
20
|
return endpoint.eventTrigger.eventType;
|
|
18
21
|
}
|
|
@@ -39,10 +42,19 @@ exports.memoryOptionDisplayName = memoryOptionDisplayName;
|
|
|
39
42
|
exports.DEFAULT_MEMORY = 256;
|
|
40
43
|
exports.MIN_MEMORY_FOR_CONCURRENCY = 2048;
|
|
41
44
|
exports.SCHEDULED_FUNCTION_LABEL = Object.freeze({ deployment: "firebase-schedule" });
|
|
45
|
+
function secretVersionName(s) {
|
|
46
|
+
var _a;
|
|
47
|
+
return `projects/${s.projectId}/secrets/${s.secret}/versions/${(_a = s.version) !== null && _a !== void 0 ? _a : "latest"}`;
|
|
48
|
+
}
|
|
49
|
+
exports.secretVersionName = secretVersionName;
|
|
42
50
|
function isHttpsTriggered(triggered) {
|
|
43
51
|
return {}.hasOwnProperty.call(triggered, "httpsTrigger");
|
|
44
52
|
}
|
|
45
53
|
exports.isHttpsTriggered = isHttpsTriggered;
|
|
54
|
+
function isCallableTriggered(triggered) {
|
|
55
|
+
return {}.hasOwnProperty.call(triggered, "callableTrigger");
|
|
56
|
+
}
|
|
57
|
+
exports.isCallableTriggered = isCallableTriggered;
|
|
46
58
|
function isEventTriggered(triggered) {
|
|
47
59
|
return {}.hasOwnProperty.call(triggered, "eventTrigger");
|
|
48
60
|
}
|
|
@@ -57,7 +69,7 @@ function isTaskQueueTriggered(triggered) {
|
|
|
57
69
|
exports.isTaskQueueTriggered = isTaskQueueTriggered;
|
|
58
70
|
function empty() {
|
|
59
71
|
return {
|
|
60
|
-
requiredAPIs:
|
|
72
|
+
requiredAPIs: [],
|
|
61
73
|
endpoints: {},
|
|
62
74
|
environmentVariables: {},
|
|
63
75
|
};
|
|
@@ -76,7 +88,7 @@ function of(...endpoints) {
|
|
|
76
88
|
}
|
|
77
89
|
exports.of = of;
|
|
78
90
|
function isEmptyBackend(backend) {
|
|
79
|
-
return (Object.keys(backend.requiredAPIs).length
|
|
91
|
+
return (Object.keys(backend.requiredAPIs).length === 0 && Object.keys(backend.endpoints).length === 0);
|
|
80
92
|
}
|
|
81
93
|
exports.isEmptyBackend = isEmptyBackend;
|
|
82
94
|
function functionName(cloudFunction) {
|
|
@@ -140,7 +152,7 @@ async function checkAvailability(context, want) {
|
|
|
140
152
|
const gcfV1Regions = new Set();
|
|
141
153
|
const gcfV2Regions = new Set();
|
|
142
154
|
for (const ep of allEndpoints(want)) {
|
|
143
|
-
if (ep.platform
|
|
155
|
+
if (ep.platform === "gcfv1") {
|
|
144
156
|
gcfV1Regions.add(ep.region);
|
|
145
157
|
}
|
|
146
158
|
else {
|
|
@@ -218,8 +230,12 @@ const missingEndpoint = (backend) => (endpoint) => {
|
|
|
218
230
|
return !(0, exports.hasEndpoint)(backend)(endpoint);
|
|
219
231
|
};
|
|
220
232
|
exports.missingEndpoint = missingEndpoint;
|
|
233
|
+
function findEventFilter(endpoint, attribute) {
|
|
234
|
+
return endpoint.eventTrigger.eventFilters.find((ef) => ef.attribute === attribute);
|
|
235
|
+
}
|
|
236
|
+
exports.findEventFilter = findEventFilter;
|
|
221
237
|
function compareFunctions(left, right) {
|
|
222
|
-
if (left.platform
|
|
238
|
+
if (left.platform !== right.platform) {
|
|
223
239
|
return right.platform < left.platform ? -1 : 1;
|
|
224
240
|
}
|
|
225
241
|
if (left.region < right.region) {
|
|
@@ -52,7 +52,7 @@ async function checkHttpIam(context, options, payload) {
|
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
if (!passed) {
|
|
55
|
-
track("Error (User)", "deploy:functions:http_create_missing_iam");
|
|
55
|
+
void track("Error (User)", "deploy:functions:http_create_missing_iam");
|
|
56
56
|
throw new error_1.FirebaseError(`Missing required permission on project ${(0, cli_color_1.bold)(context.projectId)} to deploy new HTTPS functions. The permission ${(0, cli_color_1.bold)(PERMISSION)} is required to deploy the following functions:\n\n- ` +
|
|
57
57
|
newHttpsEndpoints.map((func) => func.id).join("\n- ") +
|
|
58
58
|
`\n\nTo address this error, please ask a project Owner to assign your account the "Cloud Functions Admin" role at the following URL:\n\nhttps://console.cloud.google.com/iam-admin/iam?project=${context.projectId}`);
|
|
@@ -87,7 +87,7 @@ function mergeBindings(policy, allRequiredBindings) {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
exports.mergeBindings = mergeBindings;
|
|
90
|
-
async function ensureServiceAgentRoles(
|
|
90
|
+
async function ensureServiceAgentRoles(projectNumber, want, have) {
|
|
91
91
|
const wantServices = backend.allEndpoints(want).reduce(reduceEventsToServices, []);
|
|
92
92
|
const haveServices = backend.allEndpoints(have).reduce(reduceEventsToServices, []);
|
|
93
93
|
const newServices = wantServices.filter((wantS) => !haveServices.find((haveS) => wantS.name === haveS.name));
|
|
@@ -96,7 +96,7 @@ async function ensureServiceAgentRoles(projectId, want, have) {
|
|
|
96
96
|
}
|
|
97
97
|
let policy;
|
|
98
98
|
try {
|
|
99
|
-
policy = await (0, resourceManager_1.getIamPolicy)(
|
|
99
|
+
policy = await (0, resourceManager_1.getIamPolicy)(projectNumber);
|
|
100
100
|
}
|
|
101
101
|
catch (err) {
|
|
102
102
|
utils.logLabeledBullet("functions", "Could not verify the necessary IAM configuration for the following newly-integrated services: " +
|
|
@@ -105,11 +105,11 @@ async function ensureServiceAgentRoles(projectId, want, have) {
|
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
107
107
|
const findRequiredBindings = [];
|
|
108
|
-
newServices.forEach((service) => findRequiredBindings.push(service.requiredProjectBindings(
|
|
108
|
+
newServices.forEach((service) => findRequiredBindings.push(service.requiredProjectBindings(projectNumber, policy)));
|
|
109
109
|
const allRequiredBindings = await Promise.all(findRequiredBindings);
|
|
110
110
|
mergeBindings(policy, allRequiredBindings);
|
|
111
111
|
try {
|
|
112
|
-
await (0, resourceManager_1.setIamPolicy)(
|
|
112
|
+
await (0, resourceManager_1.setIamPolicy)(projectNumber, policy, "bindings");
|
|
113
113
|
}
|
|
114
114
|
catch (err) {
|
|
115
115
|
throw new error_1.FirebaseError("We failed to modify the IAM policy for the project. The functions " +
|
|
@@ -71,7 +71,7 @@ async function cleanupBuildImages(haveFunctions, deletedFunctions, cleaners = {}
|
|
|
71
71
|
let message = "Unhandled error cleaning up build images. This could result in a small monthly bill if not corrected. ";
|
|
72
72
|
message +=
|
|
73
73
|
"You can attempt to delete these images by redeploying or you can delete them manually at";
|
|
74
|
-
if (failedDomains.size
|
|
74
|
+
if (failedDomains.size === 1) {
|
|
75
75
|
message += " " + failedDomains.values().next().value;
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
@@ -205,7 +205,7 @@ async function listGcfPaths(projectId, locations, dockerHelpers = {}) {
|
|
|
205
205
|
.map((results) => results.children)
|
|
206
206
|
.reduce((acc, val) => [...acc, ...val], [])
|
|
207
207
|
.filter((loc) => locationsSet.has(loc));
|
|
208
|
-
if (failedSubdomains.length
|
|
208
|
+
if (failedSubdomains.length === subdomains.size) {
|
|
209
209
|
throw new error_1.FirebaseError("Failed to search all subdomains.");
|
|
210
210
|
}
|
|
211
211
|
else if (failedSubdomains.length > 0) {
|
|
@@ -237,7 +237,7 @@ async function deleteGcfArtifacts(projectId, locations, dockerHelpers = {}) {
|
|
|
237
237
|
}
|
|
238
238
|
});
|
|
239
239
|
await Promise.all(deleteLocations);
|
|
240
|
-
if (failedSubdomains.length
|
|
240
|
+
if (failedSubdomains.length === subdomains.size) {
|
|
241
241
|
throw new error_1.FirebaseError("Failed to search all subdomains.");
|
|
242
242
|
}
|
|
243
243
|
else if (failedSubdomains.length > 0) {
|
|
@@ -26,7 +26,7 @@ async function defaultServiceAccount(e) {
|
|
|
26
26
|
}
|
|
27
27
|
exports.defaultServiceAccount = defaultServiceAccount;
|
|
28
28
|
function nodeBillingError(projectId) {
|
|
29
|
-
track("functions_runtime_notices", "nodejs10_billing_error");
|
|
29
|
+
void track("functions_runtime_notices", "nodejs10_billing_error");
|
|
30
30
|
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:
|
|
31
31
|
|
|
32
32
|
https://console.firebase.google.com/project/${projectId}/usage/details
|
|
@@ -36,7 +36,7 @@ For additional information about this requirement, see Firebase FAQs:
|
|
|
36
36
|
${FAQ_URL}`, { exit: 1 });
|
|
37
37
|
}
|
|
38
38
|
function nodePermissionError(projectId) {
|
|
39
|
-
track("functions_runtime_notices", "nodejs10_permission_error");
|
|
39
|
+
void track("functions_runtime_notices", "nodejs10_permission_error");
|
|
40
40
|
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)}.
|
|
41
41
|
|
|
42
42
|
Please ask a project owner to visit the following URL to enable Cloud Build:
|
|
@@ -99,7 +99,7 @@ async function secretAccess(projectId, wantBackend, haveBackend) {
|
|
|
99
99
|
for (const serviceAccount of serviceAccounts) {
|
|
100
100
|
(_a = wantSecrets[secret]) === null || _a === void 0 ? void 0 : _a.delete(serviceAccount);
|
|
101
101
|
}
|
|
102
|
-
if (((_b = wantSecrets[secret]) === null || _b === void 0 ? void 0 : _b.size)
|
|
102
|
+
if (((_b = wantSecrets[secret]) === null || _b === void 0 ? void 0 : _b.size) === 0) {
|
|
103
103
|
delete wantSecrets[secret];
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -10,7 +10,7 @@ function functionMatchesAnyGroup(func, filterGroups) {
|
|
|
10
10
|
exports.functionMatchesAnyGroup = functionMatchesAnyGroup;
|
|
11
11
|
function functionMatchesGroup(func, groupChunks) {
|
|
12
12
|
const functionNameChunks = func.id.split("-").slice(0, groupChunks.length);
|
|
13
|
-
if (functionNameChunks.length
|
|
13
|
+
if (functionNameChunks.length !== groupChunks.length) {
|
|
14
14
|
return false;
|
|
15
15
|
}
|
|
16
16
|
for (let i = 0; i < groupChunks.length; i += 1) {
|
|
@@ -28,7 +28,7 @@ function getFilterGroups(options) {
|
|
|
28
28
|
const only = options.only.split(",");
|
|
29
29
|
const onlyFunctions = only.filter((filter) => {
|
|
30
30
|
const opts = filter.split(":");
|
|
31
|
-
return opts[0]
|
|
31
|
+
return opts[0] === "functions" && opts[1];
|
|
32
32
|
});
|
|
33
33
|
return onlyFunctions.map((filter) => {
|
|
34
34
|
return filter.split(":")[1].split(/[.-]/);
|
|
@@ -27,6 +27,7 @@ function hasDotenv(opts) {
|
|
|
27
27
|
}
|
|
28
28
|
async function prepare(context, options, payload) {
|
|
29
29
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
30
|
+
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
30
31
|
const sourceDirName = options.config.get("functions.source");
|
|
31
32
|
if (!sourceDirName) {
|
|
32
33
|
throw new error_1.FirebaseError(`No functions code detected at default location (./functions), and no functions.source defined in firebase.json`);
|
|
@@ -69,7 +70,7 @@ async function prepare(context, options, payload) {
|
|
|
69
70
|
: usedDotenv
|
|
70
71
|
? "dotenv"
|
|
71
72
|
: "none";
|
|
72
|
-
|
|
73
|
+
void (0, track_1.track)("functions_codebase_deploy_env_method", tag);
|
|
73
74
|
logger_1.logger.debug(`Analyzing ${runtimeDelegate.name} backend spec`);
|
|
74
75
|
const wantBackend = await runtimeDelegate.discoverSpec(runtimeConfig, firebaseEnvs);
|
|
75
76
|
wantBackend.environmentVariables = Object.assign(Object.assign({}, userEnvs), firebaseEnvs);
|
|
@@ -102,7 +103,7 @@ async function prepare(context, options, payload) {
|
|
|
102
103
|
for (const endpoint of backend.allEndpoints(wantBackend)) {
|
|
103
104
|
endpoint.environmentVariables = wantBackend.environmentVariables;
|
|
104
105
|
}
|
|
105
|
-
await Promise.all(Object.values(wantBackend.requiredAPIs).map((api) => {
|
|
106
|
+
await Promise.all(Object.values(wantBackend.requiredAPIs).map(({ api }) => {
|
|
106
107
|
return ensureApiEnabled.ensure(projectId, api, "functions", false);
|
|
107
108
|
}));
|
|
108
109
|
validate.endpointsAreValid(wantBackend);
|
|
@@ -111,7 +112,7 @@ async function prepare(context, options, payload) {
|
|
|
111
112
|
return (0, functionsDeployHelper_1.functionMatchesAnyGroup)(endpoint, context.filters);
|
|
112
113
|
});
|
|
113
114
|
const haveBackend = await backend.existingBackend(context);
|
|
114
|
-
await (0, checkIam_1.ensureServiceAgentRoles)(
|
|
115
|
+
await (0, checkIam_1.ensureServiceAgentRoles)(projectNumber, wantBackend, haveBackend);
|
|
115
116
|
inferDetailsFromExisting(wantBackend, haveBackend, usedDotenv);
|
|
116
117
|
await (0, triggerRegionHelper_1.ensureTriggerRegions)(wantBackend);
|
|
117
118
|
await (0, prompts_1.promptForFailurePolicies)(options, matchingBackend, haveBackend);
|
|
@@ -134,6 +135,7 @@ function inferDetailsFromExisting(want, have, usedDotenv) {
|
|
|
134
135
|
if (!wantE.availableMemoryMb && haveE.availableMemoryMb) {
|
|
135
136
|
wantE.availableMemoryMb = haveE.availableMemoryMb;
|
|
136
137
|
}
|
|
138
|
+
wantE.securityLevel = haveE.securityLevel ? haveE.securityLevel : "SECURE_ALWAYS";
|
|
137
139
|
maybeCopyTriggerRegion(wantE, haveE);
|
|
138
140
|
}
|
|
139
141
|
}
|
|
@@ -106,7 +106,7 @@ function canCalculateMinInstanceCost(endpoint) {
|
|
|
106
106
|
if (!endpoint.minInstances) {
|
|
107
107
|
return true;
|
|
108
108
|
}
|
|
109
|
-
if (endpoint.platform
|
|
109
|
+
if (endpoint.platform === "gcfv1") {
|
|
110
110
|
if (!MB_TO_GHZ[endpoint.availableMemoryMb || 256]) {
|
|
111
111
|
return false;
|
|
112
112
|
}
|
|
@@ -21,7 +21,7 @@ async function promptForFailurePolicies(options, want, have) {
|
|
|
21
21
|
const existing = (_a = have.endpoints[endpoint.region]) === null || _a === void 0 ? void 0 : _a[endpoint.id];
|
|
22
22
|
return !(existing && backend.isEventTriggered(existing) && existing.eventTrigger.retry);
|
|
23
23
|
});
|
|
24
|
-
if (newRetryEndpoints.length
|
|
24
|
+
if (newRetryEndpoints.length === 0) {
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
const warnMessage = "The following functions will newly be retried in case of failure: " +
|
|
@@ -137,7 +137,7 @@ async function promptForMinInstances(options, want, have) {
|
|
|
137
137
|
costLine = `With these options, your minimum bill will be $${cost} in a 30-day month`;
|
|
138
138
|
}
|
|
139
139
|
let cudAnnotation = "";
|
|
140
|
-
if (backend.someEndpoint(want, (fn) => fn.platform
|
|
140
|
+
if (backend.someEndpoint(want, (fn) => fn.platform === "gcfv2" && !!fn.minInstances)) {
|
|
141
141
|
cudAnnotation =
|
|
142
142
|
"\nThis bill can be lowered with a one year commitment. See https://cloud.google.com/run/cud for more";
|
|
143
143
|
}
|
|
@@ -51,12 +51,12 @@ class Fabricator {
|
|
|
51
51
|
totalTime: 0,
|
|
52
52
|
results: [],
|
|
53
53
|
};
|
|
54
|
-
const
|
|
55
|
-
const results = await this.
|
|
54
|
+
const deployChangesets = Object.values(plan).map(async (changes) => {
|
|
55
|
+
const results = await this.applyChangeset(changes);
|
|
56
56
|
summary.results.push(...results);
|
|
57
57
|
return;
|
|
58
58
|
});
|
|
59
|
-
const promiseResults = await utils.allSettled(
|
|
59
|
+
const promiseResults = await utils.allSettled(deployChangesets);
|
|
60
60
|
const errs = promiseResults
|
|
61
61
|
.filter((r) => r.status === "rejected")
|
|
62
62
|
.map((r) => r.reason);
|
|
@@ -66,7 +66,7 @@ class Fabricator {
|
|
|
66
66
|
summary.totalTime = timer.stop();
|
|
67
67
|
return summary;
|
|
68
68
|
}
|
|
69
|
-
async
|
|
69
|
+
async applyChangeset(changes) {
|
|
70
70
|
const deployResults = [];
|
|
71
71
|
const handle = async (op, endpoint, fn) => {
|
|
72
72
|
const timer = new timer_1.Timer();
|
|
@@ -216,12 +216,12 @@ class Fabricator {
|
|
|
216
216
|
})
|
|
217
217
|
.catch(rethrowAs(endpoint, "create topic"));
|
|
218
218
|
}
|
|
219
|
-
const resultFunction =
|
|
219
|
+
const resultFunction = await this.functionExecutor
|
|
220
220
|
.run(async () => {
|
|
221
221
|
const op = await gcfV2.createFunction(apiFunction);
|
|
222
222
|
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `create-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
223
223
|
})
|
|
224
|
-
.catch(rethrowAs(endpoint, "create"))
|
|
224
|
+
.catch(rethrowAs(endpoint, "create"));
|
|
225
225
|
endpoint.uri = resultFunction.serviceConfig.uri;
|
|
226
226
|
const serviceName = resultFunction.serviceConfig.service;
|
|
227
227
|
if (backend.isHttpsTriggered(endpoint)) {
|
|
@@ -243,7 +243,7 @@ class Fabricator {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
const mem = endpoint.availableMemoryMb || backend.DEFAULT_MEMORY;
|
|
246
|
-
if (mem >= backend.MIN_MEMORY_FOR_CONCURRENCY && endpoint.concurrency
|
|
246
|
+
if (mem >= backend.MIN_MEMORY_FOR_CONCURRENCY && endpoint.concurrency !== 1) {
|
|
247
247
|
await this.setConcurrency(endpoint, serviceName, endpoint.concurrency || DEFAULT_GCFV2_CONCURRENCY);
|
|
248
248
|
}
|
|
249
249
|
}
|
|
@@ -56,7 +56,7 @@ async function release(context, options, payload) {
|
|
|
56
56
|
await containerCleaner.cleanupBuildImages(haveEndpoints, deletedEndpoints, opts);
|
|
57
57
|
const allErrors = summary.results.filter((r) => r.error).map((r) => r.error);
|
|
58
58
|
if (allErrors.length) {
|
|
59
|
-
const opts = allErrors.length
|
|
59
|
+
const opts = allErrors.length === 1 ? { original: allErrors[0] } : { children: allErrors };
|
|
60
60
|
throw new error_1.FirebaseError("There was an error deploying functions", Object.assign(Object.assign({}, opts), { exit: 2 }));
|
|
61
61
|
}
|
|
62
62
|
}
|