firebase-tools 10.6.0 → 10.7.2
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/command.js +4 -4
- package/lib/commands/deploy.js +1 -1
- package/lib/commands/emulators-start.js +7 -2
- package/lib/commands/ext-configure.js +15 -5
- package/lib/commands/ext-export.js +6 -5
- package/lib/commands/ext-install.js +28 -44
- package/lib/commands/ext-update.js +9 -1
- package/lib/commands/functions-delete.js +7 -3
- package/lib/commands/hosting-channel-deploy.js +2 -2
- package/lib/deploy/database/deploy.js +4 -0
- package/lib/deploy/database/index.js +1 -0
- package/lib/deploy/extensions/deploy.js +4 -4
- package/lib/deploy/extensions/deploymentSummary.js +8 -5
- package/lib/deploy/extensions/planner.js +36 -9
- package/lib/deploy/extensions/prepare.js +1 -1
- package/lib/deploy/extensions/secrets.js +2 -2
- package/lib/deploy/extensions/tasks.js +60 -21
- package/lib/deploy/functions/backend.js +37 -2
- package/lib/deploy/functions/build.js +173 -0
- package/lib/deploy/functions/checkIam.js +11 -14
- package/lib/deploy/functions/containerCleaner.js +8 -7
- package/lib/deploy/functions/deploy.js +49 -28
- package/lib/deploy/functions/ensure.js +4 -4
- package/lib/deploy/functions/functionsDeployHelper.js +99 -24
- package/lib/deploy/functions/prepare.js +129 -71
- package/lib/deploy/functions/prepareFunctionsUpload.js +16 -21
- package/lib/deploy/functions/pricing.js +6 -3
- package/lib/deploy/functions/prompts.js +1 -7
- package/lib/deploy/functions/release/executor.js +1 -1
- package/lib/deploy/functions/release/fabricator.js +69 -25
- package/lib/deploy/functions/release/index.js +20 -6
- package/lib/deploy/functions/release/planner.js +18 -10
- package/lib/deploy/functions/release/reporter.js +14 -11
- package/lib/deploy/functions/runtimes/discovery/parsing.js +12 -6
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +50 -3
- package/lib/deploy/functions/runtimes/golang/index.js +3 -0
- package/lib/deploy/functions/runtimes/node/index.js +7 -0
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +3 -3
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +132 -6
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/services/auth.js +95 -0
- package/lib/deploy/functions/services/index.js +41 -21
- package/lib/deploy/functions/validate.js +33 -7
- package/lib/deploy/hosting/args.js +2 -0
- package/lib/deploy/hosting/convertConfig.js +39 -8
- package/lib/deploy/hosting/deploy.js +3 -3
- package/lib/deploy/hosting/prepare.js +2 -2
- package/lib/deploy/hosting/release.js +6 -2
- package/lib/deploy/index.js +82 -93
- package/lib/deploy/remoteconfig/deploy.js +4 -0
- package/lib/deploy/remoteconfig/index.js +3 -1
- package/lib/emulator/auth/cloudFunctions.js +6 -2
- package/lib/emulator/auth/operations.js +5 -1
- package/lib/emulator/auth/server.js +8 -1
- package/lib/emulator/auth/state.js +27 -24
- package/lib/emulator/auth/utils.js +3 -25
- package/lib/emulator/controller.js +17 -14
- package/lib/emulator/databaseEmulator.js +36 -3
- package/lib/emulator/downloadableEmulators.js +39 -23
- package/lib/emulator/extensions/validation.js +2 -2
- package/lib/emulator/extensionsEmulator.js +85 -21
- package/lib/emulator/functionsEmulator.js +89 -15
- package/lib/emulator/functionsEmulatorRuntime.js +1 -1
- package/lib/emulator/functionsEmulatorShared.js +25 -2
- package/lib/emulator/functionsEmulatorShell.js +2 -3
- package/lib/emulator/functionsEmulatorUtils.js +5 -1
- package/lib/emulator/pubsubEmulator.js +13 -9
- package/lib/emulator/registry.js +34 -12
- package/lib/emulator/storage/apis/firebase.js +33 -6
- package/lib/emulator/storage/apis/gcloud.js +6 -3
- package/lib/emulator/storage/files.js +9 -1
- package/lib/ensureApiEnabled.js +8 -4
- package/lib/extensions/changelog.js +1 -1
- package/lib/extensions/emulator/optionsHelper.js +4 -3
- package/lib/extensions/emulator/specHelper.js +7 -1
- package/lib/extensions/extensionsHelper.js +30 -24
- package/lib/extensions/manifest.js +27 -7
- package/lib/extensions/paramHelper.js +7 -5
- package/lib/extensions/provisioningHelper.js +2 -2
- package/lib/extensions/warnings.js +11 -4
- package/lib/functions/events/index.js +7 -0
- package/lib/functions/events/v1.js +6 -0
- package/lib/functions/projectConfig.js +32 -6
- package/lib/functionsShellCommandAction.js +1 -1
- package/lib/gcp/cloudfunctions.js +38 -5
- package/lib/gcp/cloudfunctionsv2.js +46 -7
- package/lib/gcp/identityPlatform.js +44 -0
- package/lib/gcp/secretManager.js +1 -1
- package/lib/metaprogramming.js +2 -0
- package/lib/previews.js +1 -1
- package/lib/serve/functions.js +16 -19
- package/lib/serve/hosting.js +25 -12
- package/lib/serve/index.js +6 -0
- package/lib/track.js +15 -21
- package/npm-shrinkwrap.json +256 -527
- package/package.json +6 -3
- package/schema/firebase-config.json +6 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.inferDetailsFromExisting = exports.prepare = void 0;
|
|
3
|
+
exports.inferBlockingDetails = exports.inferDetailsFromExisting = exports.prepare = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const backend = require("./backend");
|
|
6
6
|
const ensureApiEnabled = require("../../ensureApiEnabled");
|
|
@@ -21,63 +21,126 @@ const checkIam_1 = require("./checkIam");
|
|
|
21
21
|
const error_1 = require("../../error");
|
|
22
22
|
const projectConfig_1 = require("../../functions/projectConfig");
|
|
23
23
|
const previews_1 = require("../../previews");
|
|
24
|
+
const v1_1 = require("../../functions/events/v1");
|
|
24
25
|
function hasUserConfig(config) {
|
|
25
26
|
return Object.keys(config).length > 1;
|
|
26
27
|
}
|
|
27
|
-
function hasDotenv(opts) {
|
|
28
|
-
return functionsEnv.hasUserEnvs(opts);
|
|
29
|
-
}
|
|
30
28
|
async function prepare(context, options, payload) {
|
|
31
29
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
32
30
|
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
33
|
-
context.config = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
context.config = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions);
|
|
32
|
+
context.filters = (0, functionsDeployHelper_1.getEndpointFilters)(options);
|
|
33
|
+
const codebases = (0, functionsDeployHelper_1.targetCodebases)(context.config, context.filters);
|
|
34
|
+
if (codebases.length === 0) {
|
|
35
|
+
throw new error_1.FirebaseError("No function matches given --only filters. Aborting deployment.");
|
|
37
36
|
}
|
|
38
|
-
const sourceDir = options.config.path(sourceDirName);
|
|
39
|
-
const delegateContext = {
|
|
40
|
-
projectId,
|
|
41
|
-
sourceDir,
|
|
42
|
-
projectDir: options.config.projectDir,
|
|
43
|
-
runtime: context.config.runtime || "",
|
|
44
|
-
};
|
|
45
|
-
const runtimeDelegate = await runtimes.getRuntimeDelegate(delegateContext);
|
|
46
|
-
logger_1.logger.debug(`Validating ${runtimeDelegate.name} source`);
|
|
47
|
-
await runtimeDelegate.validate();
|
|
48
|
-
logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
|
|
49
|
-
await runtimeDelegate.build();
|
|
50
37
|
const checkAPIsEnabled = await Promise.all([
|
|
51
38
|
ensureApiEnabled.ensure(projectId, "cloudfunctions.googleapis.com", "functions"),
|
|
52
39
|
ensureApiEnabled.check(projectId, "runtimeconfig.googleapis.com", "runtimeconfig", true),
|
|
53
40
|
ensure.cloudBuildEnabled(projectId),
|
|
54
41
|
ensure.maybeEnableAR(projectId),
|
|
55
42
|
]);
|
|
56
|
-
context.runtimeConfigEnabled = checkAPIsEnabled[1];
|
|
57
43
|
context.artifactRegistryEnabled = checkAPIsEnabled[3];
|
|
58
44
|
const firebaseConfig = await functionsConfig.getFirebaseConfig(options);
|
|
59
45
|
context.firebaseConfig = firebaseConfig;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
};
|
|
67
|
-
const
|
|
68
|
-
|
|
46
|
+
let runtimeConfig = { firebase: firebaseConfig };
|
|
47
|
+
if (checkAPIsEnabled[1]) {
|
|
48
|
+
runtimeConfig = Object.assign(Object.assign({}, runtimeConfig), (await (0, prepareFunctionsUpload_1.getFunctionsConfig)(projectId)));
|
|
49
|
+
}
|
|
50
|
+
context.sources = {};
|
|
51
|
+
const codebaseUsesEnvs = [];
|
|
52
|
+
const wantBackends = {};
|
|
53
|
+
for (const codebase of codebases) {
|
|
54
|
+
(0, utils_1.logLabeledBullet)("functions", `preparing codebase ${clc.bold(codebase)} for deployment`);
|
|
55
|
+
const config = (0, projectConfig_1.configForCodebase)(context.config, codebase);
|
|
56
|
+
const sourceDirName = config.source;
|
|
57
|
+
if (!sourceDirName) {
|
|
58
|
+
throw new error_1.FirebaseError(`No functions code detected at default location (./functions), and no functions source defined in firebase.json`);
|
|
59
|
+
}
|
|
60
|
+
const sourceDir = options.config.path(sourceDirName);
|
|
61
|
+
const delegateContext = {
|
|
62
|
+
projectId,
|
|
63
|
+
sourceDir,
|
|
64
|
+
projectDir: options.config.projectDir,
|
|
65
|
+
runtime: config.runtime || "",
|
|
66
|
+
};
|
|
67
|
+
const runtimeDelegate = await runtimes.getRuntimeDelegate(delegateContext);
|
|
68
|
+
logger_1.logger.debug(`Validating ${runtimeDelegate.name} source`);
|
|
69
|
+
await runtimeDelegate.validate();
|
|
70
|
+
logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
|
|
71
|
+
await runtimeDelegate.build();
|
|
72
|
+
const firebaseEnvs = functionsEnv.loadFirebaseEnvs(firebaseConfig, projectId);
|
|
73
|
+
const userEnvOpt = {
|
|
74
|
+
functionsSource: sourceDir,
|
|
75
|
+
projectId: projectId,
|
|
76
|
+
projectAlias: options.projectAlias,
|
|
77
|
+
};
|
|
78
|
+
const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
|
|
79
|
+
logger_1.logger.debug(`Analyzing ${runtimeDelegate.name} backend spec`);
|
|
80
|
+
const wantBackend = await runtimeDelegate.discoverSpec(runtimeConfig, firebaseEnvs);
|
|
81
|
+
wantBackend.environmentVariables = Object.assign(Object.assign({}, userEnvs), firebaseEnvs);
|
|
82
|
+
for (const endpoint of backend.allEndpoints(wantBackend)) {
|
|
83
|
+
endpoint.environmentVariables = wantBackend.environmentVariables;
|
|
84
|
+
endpoint.codebase = codebase;
|
|
85
|
+
}
|
|
86
|
+
wantBackends[codebase] = wantBackend;
|
|
87
|
+
if (functionsEnv.hasUserEnvs(userEnvOpt)) {
|
|
88
|
+
codebaseUsesEnvs.push(codebase);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
validate.endpointsAreUnique(wantBackends);
|
|
92
|
+
for (const [codebase, wantBackend] of Object.entries(wantBackends)) {
|
|
93
|
+
const config = (0, projectConfig_1.configForCodebase)(context.config, codebase);
|
|
94
|
+
const sourceDirName = config.source;
|
|
95
|
+
const sourceDir = options.config.path(sourceDirName);
|
|
96
|
+
const source = {};
|
|
97
|
+
if (backend.someEndpoint(wantBackend, () => true)) {
|
|
98
|
+
(0, utils_1.logLabeledBullet)("functions", `preparing ${clc.bold(sourceDirName)} directory for uploading...`);
|
|
99
|
+
}
|
|
100
|
+
if (backend.someEndpoint(wantBackend, (e) => e.platform === "gcfv2")) {
|
|
101
|
+
if (!previews_1.previews.functionsv2) {
|
|
102
|
+
throw new error_1.FirebaseError("This version of firebase-tools does not support Google Cloud " +
|
|
103
|
+
"Functions gen 2\n" +
|
|
104
|
+
"If Cloud Functions for Firebase gen 2 is still in alpha, sign up " +
|
|
105
|
+
"for the alpha program at " +
|
|
106
|
+
"https://services.google.com/fb/forms/firebasealphaprogram/\n" +
|
|
107
|
+
"If Cloud Functions for Firebase gen 2 is in beta, get the latest " +
|
|
108
|
+
"version of Firebse Tools with `npm i -g firebase-tools@latest`");
|
|
109
|
+
}
|
|
110
|
+
source.functionsSourceV2 = await (0, prepareFunctionsUpload_1.prepareFunctionsUpload)(sourceDir, config);
|
|
111
|
+
}
|
|
112
|
+
if (backend.someEndpoint(wantBackend, (e) => e.platform === "gcfv1")) {
|
|
113
|
+
source.functionsSourceV1 = await (0, prepareFunctionsUpload_1.prepareFunctionsUpload)(sourceDir, config, runtimeConfig);
|
|
114
|
+
}
|
|
115
|
+
context.sources[codebase] = source;
|
|
116
|
+
}
|
|
117
|
+
payload.functions = {};
|
|
118
|
+
const haveBackends = (0, functionsDeployHelper_1.groupEndpointsByCodebase)(wantBackends, backend.allEndpoints(await backend.existingBackend(context)));
|
|
119
|
+
for (const [codebase, wantBackend] of Object.entries(wantBackends)) {
|
|
120
|
+
const haveBackend = haveBackends[codebase] || Object.assign({}, backend.empty());
|
|
121
|
+
payload.functions[codebase] = { wantBackend, haveBackend };
|
|
122
|
+
}
|
|
123
|
+
for (const [codebase, { wantBackend, haveBackend }] of Object.entries(payload.functions)) {
|
|
124
|
+
inferDetailsFromExisting(wantBackend, haveBackend, codebaseUsesEnvs.includes(codebase));
|
|
125
|
+
await (0, triggerRegionHelper_1.ensureTriggerRegions)(wantBackend);
|
|
126
|
+
validate.endpointsAreValid(wantBackend);
|
|
127
|
+
inferBlockingDetails(wantBackend);
|
|
128
|
+
}
|
|
69
129
|
const tag = hasUserConfig(runtimeConfig)
|
|
70
|
-
?
|
|
130
|
+
? codebaseUsesEnvs.length > 0
|
|
71
131
|
? "mixed"
|
|
72
132
|
: "runtime_config"
|
|
73
|
-
:
|
|
133
|
+
: codebaseUsesEnvs.length > 0
|
|
74
134
|
? "dotenv"
|
|
75
135
|
: "none";
|
|
76
136
|
void (0, track_1.track)("functions_codebase_deploy_env_method", tag);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
wantBackend
|
|
80
|
-
|
|
137
|
+
const codebaseCnt = Object.keys(payload.functions).length;
|
|
138
|
+
void (0, track_1.track)("functions_codebase_deploy_count", codebaseCnt >= 5 ? "5+" : codebaseCnt.toString());
|
|
139
|
+
const wantBackend = backend.merge(...Object.values(wantBackends));
|
|
140
|
+
const haveBackend = backend.merge(...Object.values(haveBackends));
|
|
141
|
+
await Promise.all(Object.values(wantBackend.requiredAPIs).map(({ api }) => {
|
|
142
|
+
return ensureApiEnabled.ensure(projectId, api, "functions", false);
|
|
143
|
+
}));
|
|
81
144
|
if (backend.someEndpoint(wantBackend, (e) => e.platform === "gcfv2")) {
|
|
82
145
|
const V2_APIS = [
|
|
83
146
|
"artifactregistry.googleapis.com",
|
|
@@ -91,45 +154,13 @@ async function prepare(context, options, payload) {
|
|
|
91
154
|
});
|
|
92
155
|
await Promise.all(enablements);
|
|
93
156
|
}
|
|
94
|
-
if (backend.someEndpoint(wantBackend, () => true)) {
|
|
95
|
-
(0, utils_1.logBullet)(clc.cyan.bold("functions:") +
|
|
96
|
-
" preparing " +
|
|
97
|
-
clc.bold(sourceDirName) +
|
|
98
|
-
" directory for uploading...");
|
|
99
|
-
}
|
|
100
|
-
if (backend.someEndpoint(wantBackend, (e) => e.platform === "gcfv2")) {
|
|
101
|
-
if (!previews_1.previews.functionsv2) {
|
|
102
|
-
throw new error_1.FirebaseError("This version of firebase-tools does not support Google Cloud " +
|
|
103
|
-
"Functions gen 2\n" +
|
|
104
|
-
"If Cloud Functions for Firebase gen 2 is still in alpha, sign up " +
|
|
105
|
-
"for the alpha program at " +
|
|
106
|
-
"https://services.google.com/fb/forms/firebasealphaprogram/\n" +
|
|
107
|
-
"If Cloud Functions for Firebase gen 2 is in beta, get the latest " +
|
|
108
|
-
"version of Firebse Tools with `npm i -g firebase-tools@latest`");
|
|
109
|
-
}
|
|
110
|
-
context.functionsSourceV2 = await (0, prepareFunctionsUpload_1.prepareFunctionsUpload)(sourceDir, context.config);
|
|
111
|
-
}
|
|
112
|
-
if (backend.someEndpoint(wantBackend, (e) => e.platform === "gcfv1")) {
|
|
113
|
-
context.functionsSourceV1 = await (0, prepareFunctionsUpload_1.prepareFunctionsUpload)(sourceDir, context.config, runtimeConfig);
|
|
114
|
-
}
|
|
115
|
-
for (const endpoint of backend.allEndpoints(wantBackend)) {
|
|
116
|
-
endpoint.environmentVariables = wantBackend.environmentVariables;
|
|
117
|
-
}
|
|
118
|
-
await Promise.all(Object.values(wantBackend.requiredAPIs).map(({ api }) => {
|
|
119
|
-
return ensureApiEnabled.ensure(projectId, api, "functions", false);
|
|
120
|
-
}));
|
|
121
|
-
validate.endpointsAreValid(wantBackend);
|
|
122
|
-
context.filters = (0, functionsDeployHelper_1.getFilterGroups)(options);
|
|
123
157
|
const matchingBackend = backend.matchingBackend(wantBackend, (endpoint) => {
|
|
124
|
-
return (0, functionsDeployHelper_1.
|
|
158
|
+
return (0, functionsDeployHelper_1.endpointMatchesAnyFilter)(endpoint, context.filters);
|
|
125
159
|
});
|
|
126
|
-
const haveBackend = await backend.existingBackend(context);
|
|
127
|
-
await (0, checkIam_1.ensureServiceAgentRoles)(projectNumber, wantBackend, haveBackend);
|
|
128
|
-
inferDetailsFromExisting(wantBackend, haveBackend, usedDotenv);
|
|
129
|
-
await (0, triggerRegionHelper_1.ensureTriggerRegions)(wantBackend);
|
|
130
160
|
await (0, prompts_1.promptForFailurePolicies)(options, matchingBackend, haveBackend);
|
|
131
161
|
await (0, prompts_1.promptForMinInstances)(options, matchingBackend, haveBackend);
|
|
132
|
-
await backend.checkAvailability(context,
|
|
162
|
+
await backend.checkAvailability(context, matchingBackend);
|
|
163
|
+
await (0, checkIam_1.ensureServiceAgentRoles)(projectNumber, matchingBackend, haveBackend);
|
|
133
164
|
await validate.secretsAreValid(projectId, matchingBackend);
|
|
134
165
|
await ensure.secretAccess(projectId, matchingBackend, haveBackend);
|
|
135
166
|
}
|
|
@@ -165,3 +196,30 @@ function maybeCopyTriggerRegion(wantE, haveE) {
|
|
|
165
196
|
}
|
|
166
197
|
wantE.eventTrigger.region = haveE.eventTrigger.region;
|
|
167
198
|
}
|
|
199
|
+
function inferBlockingDetails(want) {
|
|
200
|
+
var _a, _b, _c;
|
|
201
|
+
const authBlockingEndpoints = backend
|
|
202
|
+
.allEndpoints(want)
|
|
203
|
+
.filter((ep) => backend.isBlockingTriggered(ep) &&
|
|
204
|
+
v1_1.AUTH_BLOCKING_EVENTS.includes(ep.blockingTrigger.eventType));
|
|
205
|
+
if (authBlockingEndpoints.length === 0) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
let accessToken = false;
|
|
209
|
+
let idToken = false;
|
|
210
|
+
let refreshToken = false;
|
|
211
|
+
for (const blockingEp of authBlockingEndpoints) {
|
|
212
|
+
accessToken || (accessToken = !!((_a = blockingEp.blockingTrigger.options) === null || _a === void 0 ? void 0 : _a.accessToken));
|
|
213
|
+
idToken || (idToken = !!((_b = blockingEp.blockingTrigger.options) === null || _b === void 0 ? void 0 : _b.idToken));
|
|
214
|
+
refreshToken || (refreshToken = !!((_c = blockingEp.blockingTrigger.options) === null || _c === void 0 ? void 0 : _c.refreshToken));
|
|
215
|
+
}
|
|
216
|
+
for (const blockingEp of authBlockingEndpoints) {
|
|
217
|
+
if (!blockingEp.blockingTrigger.options) {
|
|
218
|
+
blockingEp.blockingTrigger.options = {};
|
|
219
|
+
}
|
|
220
|
+
blockingEp.blockingTrigger.options.accessToken = accessToken;
|
|
221
|
+
blockingEp.blockingTrigger.options.idToken = idToken;
|
|
222
|
+
blockingEp.blockingTrigger.options.refreshToken = refreshToken;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.inferBlockingDetails = inferBlockingDetails;
|
|
@@ -14,31 +14,26 @@ const functionsConfig = require("../../functionsConfig");
|
|
|
14
14
|
const utils = require("../../utils");
|
|
15
15
|
const fsAsync = require("../../fsAsync");
|
|
16
16
|
const CONFIG_DEST_FILE = ".runtimeconfig.json";
|
|
17
|
-
async function getFunctionsConfig(
|
|
17
|
+
async function getFunctionsConfig(projectId) {
|
|
18
18
|
var _a, _b;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
try {
|
|
20
|
+
return await functionsConfig.materializeAll(projectId);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
logger_1.logger.debug(err);
|
|
24
|
+
let errorCode = (_b = (_a = err === null || err === void 0 ? void 0 : err.context) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode;
|
|
25
|
+
if (!errorCode) {
|
|
26
|
+
logger_1.logger.debug("Got unexpected error from Runtime Config; it has no status code:", err);
|
|
27
|
+
errorCode = 500;
|
|
23
28
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
errorCode = 500;
|
|
30
|
-
}
|
|
31
|
-
if (errorCode === 500 || errorCode === 503) {
|
|
32
|
-
throw new error_1.FirebaseError("Cloud Runtime Config is currently experiencing issues, " +
|
|
33
|
-
"which is preventing your functions from being deployed. " +
|
|
34
|
-
"Please wait a few minutes and then try to deploy your functions again." +
|
|
35
|
-
"\nRun `firebase deploy --except functions` if you want to continue deploying the rest of your project.");
|
|
36
|
-
}
|
|
37
|
-
config = {};
|
|
29
|
+
if (errorCode === 500 || errorCode === 503) {
|
|
30
|
+
throw new error_1.FirebaseError("Cloud Runtime Config is currently experiencing issues, " +
|
|
31
|
+
"which is preventing your functions from being deployed. " +
|
|
32
|
+
"Please wait a few minutes and then try to deploy your functions again." +
|
|
33
|
+
"\nRun `firebase deploy --except functions` if you want to continue deploying the rest of your project.");
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
return config;
|
|
36
|
+
return {};
|
|
42
37
|
}
|
|
43
38
|
exports.getFunctionsConfig = getFunctionsConfig;
|
|
44
39
|
async function pipeAsync(from, to) {
|
|
@@ -93,14 +93,17 @@ exports.V2_FREE_TIER = {
|
|
|
93
93
|
vCpu: 180000,
|
|
94
94
|
egress: 1,
|
|
95
95
|
};
|
|
96
|
+
const VCPU_TO_GHZ = 2.4;
|
|
96
97
|
const MB_TO_GHZ = {
|
|
97
98
|
128: 0.2,
|
|
98
99
|
256: 0.4,
|
|
99
100
|
512: 0.8,
|
|
100
101
|
1024: 1.4,
|
|
101
|
-
2048:
|
|
102
|
-
4096:
|
|
103
|
-
8192:
|
|
102
|
+
2048: 1 * VCPU_TO_GHZ,
|
|
103
|
+
4096: 2 * VCPU_TO_GHZ,
|
|
104
|
+
8192: 2 * VCPU_TO_GHZ,
|
|
105
|
+
16384: 4 * VCPU_TO_GHZ,
|
|
106
|
+
32768: 8 * VCPU_TO_GHZ,
|
|
104
107
|
};
|
|
105
108
|
function canCalculateMinInstanceCost(endpoint) {
|
|
106
109
|
if (!endpoint.minInstances) {
|
|
@@ -136,19 +136,13 @@ async function promptForMinInstances(options, want, have) {
|
|
|
136
136
|
const cost = pricing.monthlyMinInstanceCost(backend.allEndpoints(want)).toFixed(2);
|
|
137
137
|
costLine = `With these options, your minimum bill will be $${cost} in a 30-day month`;
|
|
138
138
|
}
|
|
139
|
-
let cudAnnotation = "";
|
|
140
|
-
if (backend.someEndpoint(want, (fn) => fn.platform === "gcfv2" && !!fn.minInstances)) {
|
|
141
|
-
cudAnnotation =
|
|
142
|
-
"\nThis bill can be lowered with a one year commitment. See https://cloud.google.com/run/cud for more";
|
|
143
|
-
}
|
|
144
139
|
const warnMessage = "The following functions have reserved minimum instances. This will " +
|
|
145
140
|
"reduce the frequency of cold starts but increases the minimum cost. " +
|
|
146
141
|
"You will be charged for the memory allocation and a fraction of the " +
|
|
147
142
|
"CPU allocation of instances while they are idle.\n\n" +
|
|
148
143
|
functionLines +
|
|
149
144
|
"\n\n" +
|
|
150
|
-
costLine
|
|
151
|
-
cudAnnotation;
|
|
145
|
+
costLine;
|
|
152
146
|
utils.logLabeledWarning("functions", warnMessage);
|
|
153
147
|
const proceed = await (0, prompt_1.promptOnce)({
|
|
154
148
|
type: "confirm",
|
|
@@ -13,7 +13,7 @@ async function handler(op) {
|
|
|
13
13
|
((_b = (_a = err.context) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode) ||
|
|
14
14
|
((_c = err.original) === null || _c === void 0 ? void 0 : _c.code) ||
|
|
15
15
|
((_f = (_e = (_d = err.original) === null || _d === void 0 ? void 0 : _d.context) === null || _e === void 0 ? void 0 : _e.response) === null || _f === void 0 ? void 0 : _f.statusCode);
|
|
16
|
-
if (code === 429 || code === 409) {
|
|
16
|
+
if (code === 429 || code === 409 || code === 503) {
|
|
17
17
|
throw err;
|
|
18
18
|
}
|
|
19
19
|
op.error = err;
|
|
@@ -21,6 +21,8 @@ const reporter = require("./reporter");
|
|
|
21
21
|
const run = require("../../../gcp/run");
|
|
22
22
|
const scheduler = require("../../../gcp/cloudscheduler");
|
|
23
23
|
const utils = require("../../../utils");
|
|
24
|
+
const services = require("../services");
|
|
25
|
+
const v1_1 = require("../../../functions/events/v1");
|
|
24
26
|
const gcfV1PollerOptions = {
|
|
25
27
|
apiOrigin: api_1.functionsOrigin,
|
|
26
28
|
apiVersion: gcf.API_VERSION,
|
|
@@ -35,14 +37,14 @@ const gcfV2PollerOptions = {
|
|
|
35
37
|
};
|
|
36
38
|
const DEFAULT_GCFV2_CONCURRENCY = 80;
|
|
37
39
|
const rethrowAs = (endpoint, op) => (err) => {
|
|
40
|
+
logger_1.logger.error(err.message);
|
|
38
41
|
throw new reporter.DeploymentError(endpoint, op, err);
|
|
39
42
|
};
|
|
40
43
|
class Fabricator {
|
|
41
44
|
constructor(args) {
|
|
42
45
|
this.executor = args.executor;
|
|
43
46
|
this.functionExecutor = args.functionExecutor;
|
|
44
|
-
this.
|
|
45
|
-
this.storage = args.storage;
|
|
47
|
+
this.sources = args.sources;
|
|
46
48
|
this.appEngineLocation = args.appEngineLocation;
|
|
47
49
|
}
|
|
48
50
|
async applyPlan(plan) {
|
|
@@ -151,12 +153,13 @@ class Fabricator {
|
|
|
151
153
|
}
|
|
152
154
|
}
|
|
153
155
|
async createV1Function(endpoint, scraper) {
|
|
154
|
-
var _a;
|
|
155
|
-
|
|
156
|
+
var _a, _b;
|
|
157
|
+
const sourceUrl = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.sourceUrl;
|
|
158
|
+
if (!sourceUrl) {
|
|
156
159
|
logger_1.logger.debug("Precondition failed. Cannot create a GCF function without sourceUrl");
|
|
157
160
|
throw new Error("Precondition failed");
|
|
158
161
|
}
|
|
159
|
-
const apiFunction = gcf.functionFromEndpoint(endpoint,
|
|
162
|
+
const apiFunction = gcf.functionFromEndpoint(endpoint, sourceUrl);
|
|
160
163
|
if (apiFunction.httpsTrigger) {
|
|
161
164
|
apiFunction.httpsTrigger.securityLevel = "SECURE_ALWAYS";
|
|
162
165
|
}
|
|
@@ -164,10 +167,10 @@ class Fabricator {
|
|
|
164
167
|
const resultFunction = await this.functionExecutor
|
|
165
168
|
.run(async () => {
|
|
166
169
|
const op = await gcf.createFunction(apiFunction);
|
|
167
|
-
return poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `create-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
|
|
170
|
+
return poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `create-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
|
|
168
171
|
})
|
|
169
172
|
.catch(rethrowAs(endpoint, "create"));
|
|
170
|
-
endpoint.uri = (
|
|
173
|
+
endpoint.uri = (_b = resultFunction === null || resultFunction === void 0 ? void 0 : resultFunction.httpsTrigger) === null || _b === void 0 ? void 0 : _b.url;
|
|
171
174
|
if (backend.isHttpsTriggered(endpoint)) {
|
|
172
175
|
const invoker = endpoint.httpsTrigger.invoker || ["public"];
|
|
173
176
|
if (!invoker.includes("private")) {
|
|
@@ -195,15 +198,24 @@ class Fabricator {
|
|
|
195
198
|
.catch(rethrowAs(endpoint, "set invoker"));
|
|
196
199
|
}
|
|
197
200
|
}
|
|
201
|
+
else if (backend.isBlockingTriggered(endpoint) &&
|
|
202
|
+
v1_1.AUTH_BLOCKING_EVENTS.includes(endpoint.blockingTrigger.eventType)) {
|
|
203
|
+
await this.executor
|
|
204
|
+
.run(async () => {
|
|
205
|
+
await gcf.setInvokerCreate(endpoint.project, backend.functionName(endpoint), ["public"]);
|
|
206
|
+
})
|
|
207
|
+
.catch(rethrowAs(endpoint, "set invoker"));
|
|
208
|
+
}
|
|
198
209
|
}
|
|
199
210
|
async createV2Function(endpoint) {
|
|
200
|
-
var _a;
|
|
201
|
-
|
|
211
|
+
var _a, _b;
|
|
212
|
+
const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
|
|
213
|
+
if (!storage) {
|
|
202
214
|
logger_1.logger.debug("Precondition failed. Cannot create a GCFv2 function without storage");
|
|
203
215
|
throw new Error("Precondition failed");
|
|
204
216
|
}
|
|
205
|
-
const apiFunction = gcfV2.functionFromEndpoint(endpoint,
|
|
206
|
-
const topic = (
|
|
217
|
+
const apiFunction = gcfV2.functionFromEndpoint(endpoint, storage);
|
|
218
|
+
const topic = (_b = apiFunction.eventTrigger) === null || _b === void 0 ? void 0 : _b.pubsubTopic;
|
|
207
219
|
if (topic) {
|
|
208
220
|
await this.executor
|
|
209
221
|
.run(async () => {
|
|
@@ -224,7 +236,7 @@ class Fabricator {
|
|
|
224
236
|
const resultFunction = await this.functionExecutor
|
|
225
237
|
.run(async () => {
|
|
226
238
|
const op = await gcfV2.createFunction(apiFunction);
|
|
227
|
-
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `create-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
239
|
+
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `create-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
228
240
|
})
|
|
229
241
|
.catch(rethrowAs(endpoint, "create"));
|
|
230
242
|
endpoint.uri = resultFunction.serviceConfig.uri;
|
|
@@ -252,26 +264,33 @@ class Fabricator {
|
|
|
252
264
|
.catch(rethrowAs(endpoint, "set invoker"));
|
|
253
265
|
}
|
|
254
266
|
}
|
|
267
|
+
else if (backend.isBlockingTriggered(endpoint) &&
|
|
268
|
+
v1_1.AUTH_BLOCKING_EVENTS.includes(endpoint.blockingTrigger.eventType)) {
|
|
269
|
+
await this.executor
|
|
270
|
+
.run(() => run.setInvokerCreate(endpoint.project, serviceName, ["public"]))
|
|
271
|
+
.catch(rethrowAs(endpoint, "set invoker"));
|
|
272
|
+
}
|
|
255
273
|
const mem = endpoint.availableMemoryMb || backend.DEFAULT_MEMORY;
|
|
256
274
|
if (mem >= backend.MIN_MEMORY_FOR_CONCURRENCY && endpoint.concurrency !== 1) {
|
|
257
275
|
await this.setConcurrency(endpoint, serviceName, endpoint.concurrency || DEFAULT_GCFV2_CONCURRENCY);
|
|
258
276
|
}
|
|
259
277
|
}
|
|
260
278
|
async updateV1Function(endpoint, scraper) {
|
|
261
|
-
var _a;
|
|
262
|
-
|
|
279
|
+
var _a, _b;
|
|
280
|
+
const sourceUrl = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.sourceUrl;
|
|
281
|
+
if (!sourceUrl) {
|
|
263
282
|
logger_1.logger.debug("Precondition failed. Cannot update a GCF function without sourceUrl");
|
|
264
283
|
throw new Error("Precondition failed");
|
|
265
284
|
}
|
|
266
|
-
const apiFunction = gcf.functionFromEndpoint(endpoint,
|
|
285
|
+
const apiFunction = gcf.functionFromEndpoint(endpoint, sourceUrl);
|
|
267
286
|
apiFunction.sourceToken = await scraper.tokenPromise();
|
|
268
287
|
const resultFunction = await this.functionExecutor
|
|
269
288
|
.run(async () => {
|
|
270
289
|
const op = await gcf.updateFunction(apiFunction);
|
|
271
|
-
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `update-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
|
|
290
|
+
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `update-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name, onPoll: scraper.poller }));
|
|
272
291
|
})
|
|
273
292
|
.catch(rethrowAs(endpoint, "update"));
|
|
274
|
-
endpoint.uri = (
|
|
293
|
+
endpoint.uri = (_b = resultFunction === null || resultFunction === void 0 ? void 0 : resultFunction.httpsTrigger) === null || _b === void 0 ? void 0 : _b.url;
|
|
275
294
|
let invoker;
|
|
276
295
|
if (backend.isHttpsTriggered(endpoint)) {
|
|
277
296
|
invoker = endpoint.httpsTrigger.invoker;
|
|
@@ -279,6 +298,10 @@ class Fabricator {
|
|
|
279
298
|
else if (backend.isTaskQueueTriggered(endpoint)) {
|
|
280
299
|
invoker = endpoint.taskQueueTrigger.invoker;
|
|
281
300
|
}
|
|
301
|
+
else if (backend.isBlockingTriggered(endpoint) &&
|
|
302
|
+
v1_1.AUTH_BLOCKING_EVENTS.includes(endpoint.blockingTrigger.eventType)) {
|
|
303
|
+
invoker = ["public"];
|
|
304
|
+
}
|
|
282
305
|
if (invoker) {
|
|
283
306
|
await this.executor
|
|
284
307
|
.run(() => gcf.setInvokerUpdate(endpoint.project, backend.functionName(endpoint), invoker))
|
|
@@ -286,19 +309,20 @@ class Fabricator {
|
|
|
286
309
|
}
|
|
287
310
|
}
|
|
288
311
|
async updateV2Function(endpoint) {
|
|
289
|
-
var _a;
|
|
290
|
-
|
|
312
|
+
var _a, _b;
|
|
313
|
+
const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
|
|
314
|
+
if (!storage) {
|
|
291
315
|
logger_1.logger.debug("Precondition failed. Cannot update a GCFv2 function without storage");
|
|
292
316
|
throw new Error("Precondition failed");
|
|
293
317
|
}
|
|
294
|
-
const apiFunction = gcfV2.functionFromEndpoint(endpoint,
|
|
295
|
-
if ((
|
|
318
|
+
const apiFunction = gcfV2.functionFromEndpoint(endpoint, storage);
|
|
319
|
+
if ((_b = apiFunction.eventTrigger) === null || _b === void 0 ? void 0 : _b.pubsubTopic) {
|
|
296
320
|
delete apiFunction.eventTrigger.pubsubTopic;
|
|
297
321
|
}
|
|
298
322
|
const resultFunction = await this.functionExecutor
|
|
299
323
|
.run(async () => {
|
|
300
324
|
const op = await gcfV2.updateFunction(apiFunction);
|
|
301
|
-
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `update-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
325
|
+
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `update-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
302
326
|
})
|
|
303
327
|
.catch(rethrowAs(endpoint, "update"));
|
|
304
328
|
endpoint.uri = resultFunction.serviceConfig.uri;
|
|
@@ -310,6 +334,10 @@ class Fabricator {
|
|
|
310
334
|
else if (backend.isTaskQueueTriggered(endpoint)) {
|
|
311
335
|
invoker = endpoint.taskQueueTrigger.invoker;
|
|
312
336
|
}
|
|
337
|
+
else if (backend.isBlockingTriggered(endpoint) &&
|
|
338
|
+
v1_1.AUTH_BLOCKING_EVENTS.includes(endpoint.blockingTrigger.eventType)) {
|
|
339
|
+
invoker = ["public"];
|
|
340
|
+
}
|
|
313
341
|
if (invoker) {
|
|
314
342
|
await this.executor
|
|
315
343
|
.run(() => run.setInvokerUpdate(endpoint.project, serviceName, invoker))
|
|
@@ -324,7 +352,7 @@ class Fabricator {
|
|
|
324
352
|
await this.functionExecutor
|
|
325
353
|
.run(async () => {
|
|
326
354
|
const op = await gcf.deleteFunction(fnName);
|
|
327
|
-
const pollerOptions = Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `delete-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name });
|
|
355
|
+
const pollerOptions = Object.assign(Object.assign({}, gcfV1PollerOptions), { pollerName: `delete-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name });
|
|
328
356
|
await poller.pollOperation(pollerOptions);
|
|
329
357
|
})
|
|
330
358
|
.catch(rethrowAs(endpoint, "delete"));
|
|
@@ -334,7 +362,7 @@ class Fabricator {
|
|
|
334
362
|
await this.functionExecutor
|
|
335
363
|
.run(async () => {
|
|
336
364
|
const op = await gcfV2.deleteFunction(fnName);
|
|
337
|
-
const pollerOptions = Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `delete-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name });
|
|
365
|
+
const pollerOptions = Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `delete-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name });
|
|
338
366
|
await poller.pollOperation(pollerOptions);
|
|
339
367
|
})
|
|
340
368
|
.catch(rethrowAs(endpoint, "delete"));
|
|
@@ -369,6 +397,9 @@ class Fabricator {
|
|
|
369
397
|
else if (backend.isTaskQueueTriggered(endpoint)) {
|
|
370
398
|
await this.upsertTaskQueue(endpoint);
|
|
371
399
|
}
|
|
400
|
+
else if (backend.isBlockingTriggered(endpoint)) {
|
|
401
|
+
await this.registerBlockingTrigger(endpoint);
|
|
402
|
+
}
|
|
372
403
|
}
|
|
373
404
|
async deleteTrigger(endpoint) {
|
|
374
405
|
if (backend.isScheduleTriggered(endpoint)) {
|
|
@@ -385,6 +416,9 @@ class Fabricator {
|
|
|
385
416
|
else if (backend.isTaskQueueTriggered(endpoint)) {
|
|
386
417
|
await this.disableTaskQueue(endpoint);
|
|
387
418
|
}
|
|
419
|
+
else if (backend.isBlockingTriggered(endpoint)) {
|
|
420
|
+
await this.unregisterBlockingTrigger(endpoint);
|
|
421
|
+
}
|
|
388
422
|
}
|
|
389
423
|
async upsertScheduleV1(endpoint) {
|
|
390
424
|
const job = scheduler.jobFromEndpoint(endpoint, this.appEngineLocation);
|
|
@@ -406,6 +440,11 @@ class Fabricator {
|
|
|
406
440
|
.catch(rethrowAs(endpoint, "set invoker"));
|
|
407
441
|
}
|
|
408
442
|
}
|
|
443
|
+
async registerBlockingTrigger(endpoint) {
|
|
444
|
+
await this.executor
|
|
445
|
+
.run(() => services.serviceForEndpoint(endpoint).registerTrigger(endpoint))
|
|
446
|
+
.catch(rethrowAs(endpoint, "register blocking trigger"));
|
|
447
|
+
}
|
|
409
448
|
async deleteScheduleV1(endpoint) {
|
|
410
449
|
const job = scheduler.jobFromEndpoint(endpoint, this.appEngineLocation);
|
|
411
450
|
await this.executor
|
|
@@ -427,10 +466,15 @@ class Fabricator {
|
|
|
427
466
|
.run(() => cloudtasks.updateQueue(update))
|
|
428
467
|
.catch(rethrowAs(endpoint, "disable task queue"));
|
|
429
468
|
}
|
|
469
|
+
async unregisterBlockingTrigger(endpoint) {
|
|
470
|
+
await this.executor
|
|
471
|
+
.run(() => services.serviceForEndpoint(endpoint).unregisterTrigger(endpoint))
|
|
472
|
+
.catch(rethrowAs(endpoint, "unregister blocking trigger"));
|
|
473
|
+
}
|
|
430
474
|
logOpStart(op, endpoint) {
|
|
431
475
|
const runtime = (0, runtimes_1.getHumanFriendlyRuntimeName)(endpoint.runtime);
|
|
432
476
|
const label = helper.getFunctionLabel(endpoint);
|
|
433
|
-
utils.
|
|
477
|
+
utils.logLabeledBullet("functions", `${op} ${runtime} function ${clc.bold(label)}...`);
|
|
434
478
|
}
|
|
435
479
|
logOpSuccess(op, endpoint) {
|
|
436
480
|
const label = helper.getFunctionLabel(endpoint);
|
|
@@ -21,7 +21,21 @@ async function release(context, options, payload) {
|
|
|
21
21
|
if (!context.config) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (!payload.functions) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!context.sources) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let plan = {};
|
|
31
|
+
for (const [codebase, { wantBackend, haveBackend }] of Object.entries(payload.functions)) {
|
|
32
|
+
plan = Object.assign(Object.assign({}, plan), planner.createDeploymentPlan({
|
|
33
|
+
codebase,
|
|
34
|
+
wantBackend,
|
|
35
|
+
haveBackend,
|
|
36
|
+
filters: context.filters,
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
25
39
|
const fnsToDelete = Object.values(plan)
|
|
26
40
|
.map((regionalChanges) => regionalChanges.endpointsToDelete)
|
|
27
41
|
.reduce(functional_1.reduceFlat, []);
|
|
@@ -40,15 +54,15 @@ async function release(context, options, payload) {
|
|
|
40
54
|
const fab = new fabricator.Fabricator({
|
|
41
55
|
functionExecutor,
|
|
42
56
|
executor: new executor.QueueExecutor({}),
|
|
43
|
-
|
|
44
|
-
storage: context.storage,
|
|
57
|
+
sources: context.sources,
|
|
45
58
|
appEngineLocation: (0, functionsConfig_1.getAppEngineLocation)(context.firebaseConfig),
|
|
46
59
|
});
|
|
47
60
|
const summary = await fab.applyPlan(plan);
|
|
48
61
|
await reporter.logAndTrackDeployStats(summary);
|
|
49
62
|
reporter.printErrors(summary);
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
const wantBackend = backend.merge(...Object.values(payload.functions).map((p) => p.wantBackend));
|
|
64
|
+
printTriggerUrls(wantBackend);
|
|
65
|
+
const haveEndpoints = backend.allEndpoints(wantBackend);
|
|
52
66
|
const deletedEndpoints = Object.values(plan)
|
|
53
67
|
.map((r) => r.endpointsToDelete)
|
|
54
68
|
.reduce(functional_1.reduceFlat, []);
|
|
@@ -89,7 +103,7 @@ function printTriggerUrls(results) {
|
|
|
89
103
|
}
|
|
90
104
|
for (const httpsFunc of httpsFunctions) {
|
|
91
105
|
if (!httpsFunc.uri) {
|
|
92
|
-
logger_1.logger.debug("
|
|
106
|
+
logger_1.logger.debug("Not printing URL for HTTPS function. Typically this means it didn't match a filter or we failed deployment");
|
|
93
107
|
continue;
|
|
94
108
|
}
|
|
95
109
|
logger_1.logger.info(clc.bold("Function URL"), `(${(0, functionsDeployHelper_1.getFunctionLabel)(httpsFunc)}):`, httpsFunc.uri);
|