firebase-tools 9.20.0 → 9.21.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/CHANGELOG.md +3 -1
- package/lib/apiv2.js +4 -2
- package/lib/commands/crashlytics-symbols-upload.js +1 -1
- package/lib/commands/ext-dev-unpublish.js +10 -3
- package/lib/commands/functions-delete.js +53 -42
- package/lib/commands/functions-list.js +11 -11
- package/lib/deploy/functions/backend.js +77 -115
- package/lib/deploy/functions/checkIam.js +8 -8
- package/lib/deploy/functions/deploy.js +4 -10
- package/lib/deploy/functions/functionsDeployHelper.js +3 -68
- package/lib/deploy/functions/prepare.js +61 -29
- package/lib/deploy/functions/pricing.js +17 -17
- package/lib/deploy/functions/prompts.js +22 -21
- package/lib/deploy/functions/release/executor.js +39 -0
- package/lib/deploy/functions/release/fabricator.js +362 -0
- package/lib/deploy/functions/release/index.js +69 -0
- package/lib/deploy/functions/release/planner.js +159 -0
- package/lib/deploy/functions/release/reporter.js +162 -0
- package/lib/deploy/functions/release/sourceTokenScraper.js +28 -0
- package/lib/deploy/functions/release/timer.js +14 -0
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +102 -127
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +22 -43
- package/lib/deploy/functions/triggerRegionHelper.js +28 -20
- package/lib/deploy/functions/validate.js +1 -24
- package/lib/emulator/auth/apiSpec.js +37 -6
- package/lib/emulator/auth/operations.js +18 -8
- package/lib/emulator/auth/server.js +16 -2
- package/lib/emulator/auth/state.js +34 -15
- package/lib/emulator/downloadableEmulators.js +7 -7
- package/lib/emulator/functionsEmulator.js +15 -3
- package/lib/emulator/storage/cloudFunctions.js +37 -7
- package/lib/extensions/extensionsHelper.js +1 -1
- package/lib/gcp/cloudfunctions.js +1 -68
- package/lib/gcp/cloudfunctionsv2.js +2 -94
- package/lib/gcp/cloudscheduler.js +22 -16
- package/lib/gcp/pubsub.js +1 -9
- package/lib/utils.js +30 -1
- package/package.json +1 -1
- package/lib/deploy/functions/deploymentPlanner.js +0 -113
- package/lib/deploy/functions/deploymentTimer.js +0 -23
- package/lib/deploy/functions/errorHandler.js +0 -75
- package/lib/deploy/functions/release.js +0 -116
- package/lib/deploy/functions/tasks.js +0 -324
- package/lib/functions/listFunctions.js +0 -10
- package/lib/functionsDelete.js +0 -60
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.jobFromEndpoint = exports.createOrReplaceJob = exports.updateJob = exports.getJob = exports.deleteJob = exports.createJob = exports.assertValidJob = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
7
7
|
const api = require("../api");
|
|
8
8
|
const backend = require("../deploy/functions/backend");
|
|
9
9
|
const proto = require("./proto");
|
|
10
|
+
const functional_1 = require("../functional");
|
|
10
11
|
const VERSION = "v1beta1";
|
|
11
12
|
const DEFAULT_TIME_ZONE = "America/Los_Angeles";
|
|
12
13
|
function assertValidJob(job) {
|
|
@@ -86,21 +87,26 @@ function isIdentical(job, otherJob) {
|
|
|
86
87
|
job.timeZone === otherJob.timeZone &&
|
|
87
88
|
_.isEqual(job.retryConfig, otherJob.retryConfig));
|
|
88
89
|
}
|
|
89
|
-
function
|
|
90
|
-
const job = {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
function jobFromEndpoint(endpoint, appEngineLocation) {
|
|
91
|
+
const job = {};
|
|
92
|
+
if (endpoint.platform === "gcfv1") {
|
|
93
|
+
const id = backend.scheduleIdForFunction(endpoint);
|
|
94
|
+
const region = appEngineLocation;
|
|
95
|
+
job.name = `projects/${endpoint.project}/locations/${region}/jobs/${id}`;
|
|
96
|
+
job.pubsubTarget = {
|
|
97
|
+
topicName: `projects/${endpoint.project}/topics/${id}`,
|
|
98
|
+
attributes: {
|
|
99
|
+
scheduled: "true",
|
|
100
|
+
},
|
|
101
|
+
};
|
|
97
102
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
103
|
+
else if (endpoint.platform === "gcfv2") {
|
|
104
|
+
throw new error_1.FirebaseError("Do not know how to create a scheduled GCFv2 function");
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
functional_1.assertExhaustive(endpoint.platform);
|
|
108
|
+
}
|
|
109
|
+
proto.copyIfPresent(job, endpoint.scheduleTrigger, "schedule", "retryConfig", "timeZone");
|
|
104
110
|
return job;
|
|
105
111
|
}
|
|
106
|
-
exports.
|
|
112
|
+
exports.jobFromEndpoint = jobFromEndpoint;
|
package/lib/gcp/pubsub.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.deleteTopic = exports.updateTopic = exports.getTopic = exports.createTopic = void 0;
|
|
4
4
|
const apiv2_1 = require("../apiv2");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
|
-
const backend = require("../deploy/functions/backend");
|
|
7
6
|
const proto = require("./proto");
|
|
8
7
|
const API_VERSION = "v1";
|
|
9
8
|
const client = new apiv2_1.Client({
|
|
@@ -33,10 +32,3 @@ async function deleteTopic(name) {
|
|
|
33
32
|
await client.delete(name);
|
|
34
33
|
}
|
|
35
34
|
exports.deleteTopic = deleteTopic;
|
|
36
|
-
function topicFromSpec(spec) {
|
|
37
|
-
return {
|
|
38
|
-
name: backend.topicName(spec),
|
|
39
|
-
labels: Object.assign({}, spec.labels),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
exports.topicFromSpec = topicFromSpec;
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.reject = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
3
|
+
exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const url = require("url");
|
|
6
6
|
const clc = require("cli-color");
|
|
@@ -108,6 +108,35 @@ function reject(message, options) {
|
|
|
108
108
|
return Promise.reject(new error_1.FirebaseError(message, options));
|
|
109
109
|
}
|
|
110
110
|
exports.reject = reject;
|
|
111
|
+
function allSettled(promises) {
|
|
112
|
+
if (!promises.length) {
|
|
113
|
+
return Promise.resolve([]);
|
|
114
|
+
}
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
let remaining = promises.length;
|
|
117
|
+
const results = [];
|
|
118
|
+
for (let i = 0; i < promises.length; i++) {
|
|
119
|
+
void Promise.resolve(promises[i])
|
|
120
|
+
.then((result) => {
|
|
121
|
+
results[i] = {
|
|
122
|
+
status: "fulfilled",
|
|
123
|
+
value: result,
|
|
124
|
+
};
|
|
125
|
+
}, (err) => {
|
|
126
|
+
results[i] = {
|
|
127
|
+
status: "rejected",
|
|
128
|
+
reason: err,
|
|
129
|
+
};
|
|
130
|
+
})
|
|
131
|
+
.then(() => {
|
|
132
|
+
if (!--remaining) {
|
|
133
|
+
resolve(results);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
exports.allSettled = allSettled;
|
|
111
140
|
function explainStdin() {
|
|
112
141
|
if (IS_WINDOWS) {
|
|
113
142
|
throw new error_1.FirebaseError("STDIN input is not available on Windows.", {
|
package/package.json
CHANGED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createDeploymentPlan = exports.calculateRegionalFunctionChanges = exports.allRegions = exports.functionsByRegion = void 0;
|
|
4
|
-
const functionsDeployHelper_1 = require("./functionsDeployHelper");
|
|
5
|
-
const validate_1 = require("./validate");
|
|
6
|
-
const deploymentTool_1 = require("../../deploymentTool");
|
|
7
|
-
const utils_1 = require("../../utils");
|
|
8
|
-
const backend = require("./backend");
|
|
9
|
-
const gcfv2 = require("../../gcp/cloudfunctionsv2");
|
|
10
|
-
function functionsByRegion(allFunctions) {
|
|
11
|
-
const partitioned = {};
|
|
12
|
-
for (const fn of allFunctions) {
|
|
13
|
-
partitioned[fn.region] = partitioned[fn.region] || [];
|
|
14
|
-
partitioned[fn.region].push(fn);
|
|
15
|
-
}
|
|
16
|
-
return partitioned;
|
|
17
|
-
}
|
|
18
|
-
exports.functionsByRegion = functionsByRegion;
|
|
19
|
-
function allRegions(spec, existing) {
|
|
20
|
-
return Object.keys(Object.assign(Object.assign({}, spec), existing));
|
|
21
|
-
}
|
|
22
|
-
exports.allRegions = allRegions;
|
|
23
|
-
const matchesId = (hasId) => (test) => {
|
|
24
|
-
return hasId.id === test.id;
|
|
25
|
-
};
|
|
26
|
-
function calculateRegionalFunctionChanges(want, have, options) {
|
|
27
|
-
want = want.filter((fn) => functionsDeployHelper_1.functionMatchesAnyGroup(fn, options.filters));
|
|
28
|
-
have = have.filter((fn) => functionsDeployHelper_1.functionMatchesAnyGroup(fn, options.filters));
|
|
29
|
-
let upgradedToGCFv2WithoutSettingConcurrency = false;
|
|
30
|
-
const functionsToCreate = want.filter((fn) => !have.some(matchesId(fn)));
|
|
31
|
-
const functionsToUpdate = want
|
|
32
|
-
.filter((fn) => {
|
|
33
|
-
const haveFn = have.find(matchesId(fn));
|
|
34
|
-
if (!haveFn) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
validate_1.checkForInvalidChangeOfTrigger(fn, haveFn);
|
|
38
|
-
if (!options.overwriteEnvs) {
|
|
39
|
-
fn.environmentVariables = Object.assign(Object.assign({}, haveFn.environmentVariables), fn.environmentVariables);
|
|
40
|
-
}
|
|
41
|
-
if (haveFn.platform === "gcfv1" && fn.platform === "gcfv2" && !fn.concurrency) {
|
|
42
|
-
upgradedToGCFv2WithoutSettingConcurrency = true;
|
|
43
|
-
}
|
|
44
|
-
return true;
|
|
45
|
-
})
|
|
46
|
-
.map((fn) => {
|
|
47
|
-
const haveFn = have.find(matchesId(fn));
|
|
48
|
-
const deleteAndRecreate = needsDeleteAndRecreate(haveFn, fn);
|
|
49
|
-
return {
|
|
50
|
-
func: fn,
|
|
51
|
-
deleteAndRecreate,
|
|
52
|
-
};
|
|
53
|
-
});
|
|
54
|
-
const functionsToDelete = have
|
|
55
|
-
.filter((fn) => !want.some(matchesId(fn)))
|
|
56
|
-
.filter((fn) => deploymentTool_1.isFirebaseManaged(fn.labels || {}));
|
|
57
|
-
if (upgradedToGCFv2WithoutSettingConcurrency) {
|
|
58
|
-
utils_1.logLabeledBullet("functions", "You are updating one or more functions to Google Cloud Functions v2, " +
|
|
59
|
-
"which introduces support for concurrent execution. New functions " +
|
|
60
|
-
"default to 80 concurrent executions, but existing functions keep the " +
|
|
61
|
-
"old default of 1. You can change this with the 'concurrency' option.");
|
|
62
|
-
}
|
|
63
|
-
return { functionsToCreate, functionsToUpdate, functionsToDelete };
|
|
64
|
-
}
|
|
65
|
-
exports.calculateRegionalFunctionChanges = calculateRegionalFunctionChanges;
|
|
66
|
-
function createDeploymentPlan(want, have, options) {
|
|
67
|
-
const deployment = {
|
|
68
|
-
regionalDeployments: {},
|
|
69
|
-
schedulesToUpsert: [],
|
|
70
|
-
schedulesToDelete: [],
|
|
71
|
-
topicsToDelete: [],
|
|
72
|
-
};
|
|
73
|
-
const wantRegionalFunctions = functionsByRegion(want.cloudFunctions);
|
|
74
|
-
const haveRegionalFunctions = functionsByRegion(have.cloudFunctions);
|
|
75
|
-
for (const region of allRegions(wantRegionalFunctions, haveRegionalFunctions)) {
|
|
76
|
-
const want = wantRegionalFunctions[region] || [];
|
|
77
|
-
const have = haveRegionalFunctions[region] || [];
|
|
78
|
-
deployment.regionalDeployments[region] = calculateRegionalFunctionChanges(want, have, options);
|
|
79
|
-
}
|
|
80
|
-
deployment.schedulesToUpsert = want.schedules.filter((schedule) => functionsDeployHelper_1.functionMatchesAnyGroup(schedule.targetService, options.filters));
|
|
81
|
-
deployment.schedulesToDelete = have.schedules
|
|
82
|
-
.filter((schedule) => !want.schedules.some(matchesId(schedule)))
|
|
83
|
-
.filter((schedule) => functionsDeployHelper_1.functionMatchesAnyGroup(schedule.targetService, options.filters));
|
|
84
|
-
deployment.topicsToDelete = have.topics
|
|
85
|
-
.filter((topic) => !want.topics.some(matchesId(topic)))
|
|
86
|
-
.filter((topic) => functionsDeployHelper_1.functionMatchesAnyGroup(topic.targetService, options.filters));
|
|
87
|
-
return deployment;
|
|
88
|
-
}
|
|
89
|
-
exports.createDeploymentPlan = createDeploymentPlan;
|
|
90
|
-
function needsDeleteAndRecreate(exFn, fn) {
|
|
91
|
-
return changedV2PubSubTopic(exFn, fn);
|
|
92
|
-
}
|
|
93
|
-
function changedV2PubSubTopic(exFn, fn) {
|
|
94
|
-
if (exFn.platform !== "gcfv2") {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
if (fn.platform !== "gcfv2") {
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
if (!backend.isEventTrigger(exFn.trigger)) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
if (!backend.isEventTrigger(fn.trigger)) {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
if (exFn.trigger.eventType !== gcfv2.PUBSUB_PUBLISH_EVENT) {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
if (fn.trigger.eventType != gcfv2.PUBSUB_PUBLISH_EVENT) {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
return exFn.trigger.eventFilters["resource"] != fn.trigger.eventFilters["resource"];
|
|
113
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DeploymentTimer = void 0;
|
|
4
|
-
const logger_1 = require("../../logger");
|
|
5
|
-
const track = require("../../track");
|
|
6
|
-
class DeploymentTimer {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.timings = {};
|
|
9
|
-
}
|
|
10
|
-
startTimer(name, type) {
|
|
11
|
-
this.timings[name] = { type: type, t0: process.hrtime() };
|
|
12
|
-
}
|
|
13
|
-
endTimer(name) {
|
|
14
|
-
if (!this.timings[name]) {
|
|
15
|
-
logger_1.logger.debug("[functions] no timer initialized for", name);
|
|
16
|
-
return 0;
|
|
17
|
-
}
|
|
18
|
-
const duration = process.hrtime(this.timings[name].t0);
|
|
19
|
-
track("Functions Deploy (Duration)", this.timings[name].type, duration[0] * 1000 + Math.round(duration[1] * 1e-6));
|
|
20
|
-
return duration[0] * 1000 * Math.round(duration[1] * 1e-6);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.DeploymentTimer = DeploymentTimer;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ErrorHandler = void 0;
|
|
4
|
-
const clc = require("cli-color");
|
|
5
|
-
const logger_1 = require("../../logger");
|
|
6
|
-
const functionsDeployHelper_1 = require("./functionsDeployHelper");
|
|
7
|
-
const error_1 = require("../../error");
|
|
8
|
-
class ErrorHandler {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.errors = [];
|
|
11
|
-
this.warnings = [];
|
|
12
|
-
}
|
|
13
|
-
record(level, functionName, operationType, message) {
|
|
14
|
-
const info = {
|
|
15
|
-
functionName,
|
|
16
|
-
operationType,
|
|
17
|
-
message,
|
|
18
|
-
};
|
|
19
|
-
if (level === "error") {
|
|
20
|
-
this.errors.push(info);
|
|
21
|
-
}
|
|
22
|
-
else if (level === "warning") {
|
|
23
|
-
this.warnings.push(info);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
printErrors() {
|
|
27
|
-
if (this.errors.length === 0) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
logger_1.logger.info("");
|
|
31
|
-
logger_1.logger.info("Functions deploy had errors with the following functions:");
|
|
32
|
-
for (const failedDeployment of this.errors) {
|
|
33
|
-
logger_1.logger.info(`\t${functionsDeployHelper_1.getFunctionLabel(failedDeployment.functionName)}`);
|
|
34
|
-
}
|
|
35
|
-
const failedIamCalls = this.errors.filter((e) => e.operationType === "set invoker");
|
|
36
|
-
if (failedIamCalls.length) {
|
|
37
|
-
logger_1.logger.info("");
|
|
38
|
-
logger_1.logger.info("Unable to set the invoker for the IAM policy on the following functions:");
|
|
39
|
-
for (const failedDep of failedIamCalls) {
|
|
40
|
-
logger_1.logger.info(`\t${failedDep.functionName}`);
|
|
41
|
-
}
|
|
42
|
-
logger_1.logger.info("");
|
|
43
|
-
logger_1.logger.info("Some common causes of this:");
|
|
44
|
-
logger_1.logger.info("");
|
|
45
|
-
logger_1.logger.info("- You may not have the roles/functions.admin IAM role. Note that roles/functions.developer does not allow you to change IAM policies.");
|
|
46
|
-
logger_1.logger.info("");
|
|
47
|
-
logger_1.logger.info("- An organization policy that restricts Network Access on your project.");
|
|
48
|
-
}
|
|
49
|
-
logger_1.logger.info("");
|
|
50
|
-
logger_1.logger.info("To try redeploying those functions, run:");
|
|
51
|
-
logger_1.logger.info(" " +
|
|
52
|
-
clc.bold("firebase deploy --only ") +
|
|
53
|
-
clc.bold('"') +
|
|
54
|
-
clc.bold(this.errors
|
|
55
|
-
.map((failedDeployment) => `functions:${functionsDeployHelper_1.getFunctionId(failedDeployment.functionName).replace(/-/g, ".")}`)
|
|
56
|
-
.join(",")) +
|
|
57
|
-
clc.bold('"'));
|
|
58
|
-
logger_1.logger.info("");
|
|
59
|
-
logger_1.logger.info("To continue deploying other features (such as database), run:");
|
|
60
|
-
logger_1.logger.info(" " + clc.bold("firebase deploy --except functions"));
|
|
61
|
-
for (const failedDeployment of this.errors) {
|
|
62
|
-
logger_1.logger.debug(`\tError during ${failedDeployment.operationType} for ${failedDeployment.functionName}: ${failedDeployment.message}`);
|
|
63
|
-
}
|
|
64
|
-
throw new error_1.FirebaseError("Functions did not deploy properly.");
|
|
65
|
-
}
|
|
66
|
-
printWarnings() {
|
|
67
|
-
if (this.warnings.length === 0) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
for (const failedDeployment of this.warnings) {
|
|
71
|
-
logger_1.logger.debug(`\tWarning during${failedDeployment.operationType} for ${failedDeployment.functionName}: ${failedDeployment.message}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
exports.ErrorHandler = ErrorHandler;
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.release = void 0;
|
|
4
|
-
const queue_1 = require("../../throttler/queue");
|
|
5
|
-
const deploymentPlanner_1 = require("./deploymentPlanner");
|
|
6
|
-
const functionsConfig_1 = require("../../functionsConfig");
|
|
7
|
-
const env_1 = require("../../functions/env");
|
|
8
|
-
const prompts_1 = require("./prompts");
|
|
9
|
-
const deploymentTimer_1 = require("./deploymentTimer");
|
|
10
|
-
const errorHandler_1 = require("./errorHandler");
|
|
11
|
-
const previews_1 = require("../../previews");
|
|
12
|
-
const backend = require("./backend");
|
|
13
|
-
const containerCleaner = require("./containerCleaner");
|
|
14
|
-
const helper = require("./functionsDeployHelper");
|
|
15
|
-
const tasks = require("./tasks");
|
|
16
|
-
const utils = require("../../utils");
|
|
17
|
-
const track_1 = require("../../track");
|
|
18
|
-
async function release(context, options, payload) {
|
|
19
|
-
if (!options.config.has("functions")) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const projectId = context.projectId;
|
|
23
|
-
const sourceUrl = context.uploadUrl;
|
|
24
|
-
const functionsSource = options.config.get("functions.source");
|
|
25
|
-
const appEngineLocation = functionsConfig_1.getAppEngineLocation(context.firebaseConfig);
|
|
26
|
-
const timer = new deploymentTimer_1.DeploymentTimer();
|
|
27
|
-
const errorHandler = new errorHandler_1.ErrorHandler();
|
|
28
|
-
const fullDeployment = deploymentPlanner_1.createDeploymentPlan(payload.functions.backend, await backend.existingBackend(context), {
|
|
29
|
-
filters: context.filters,
|
|
30
|
-
overwriteEnvs: previews_1.previews.dotenv &&
|
|
31
|
-
env_1.hasUserEnvs({
|
|
32
|
-
functionsSource: options.config.path(functionsSource),
|
|
33
|
-
projectId,
|
|
34
|
-
projectAlias: options.projectAlias,
|
|
35
|
-
}),
|
|
36
|
-
});
|
|
37
|
-
const cloudFunctionsQueue = new queue_1.default({
|
|
38
|
-
retries: 30,
|
|
39
|
-
backoff: 20000,
|
|
40
|
-
concurrency: 40,
|
|
41
|
-
maxBackoff: 40000,
|
|
42
|
-
handler: tasks.functionsDeploymentHandler(timer, errorHandler),
|
|
43
|
-
});
|
|
44
|
-
const schedulerQueue = new queue_1.default({
|
|
45
|
-
handler: tasks.schedulerDeploymentHandler(errorHandler),
|
|
46
|
-
});
|
|
47
|
-
const pubSubQueue = new queue_1.default({
|
|
48
|
-
handler: tasks.schedulerDeploymentHandler(errorHandler),
|
|
49
|
-
});
|
|
50
|
-
const regionPromises = [];
|
|
51
|
-
const taskParams = {
|
|
52
|
-
projectId,
|
|
53
|
-
sourceUrl,
|
|
54
|
-
storage: context.storage,
|
|
55
|
-
errorHandler,
|
|
56
|
-
};
|
|
57
|
-
const allFnsToDelete = Object.values(fullDeployment.regionalDeployments).reduce((accum, region) => [...accum, ...region.functionsToDelete], []);
|
|
58
|
-
const shouldDeleteFunctions = await prompts_1.promptForFunctionDeletion(allFnsToDelete, options.force, options.nonInteractive);
|
|
59
|
-
if (!shouldDeleteFunctions) {
|
|
60
|
-
fullDeployment.schedulesToDelete = fullDeployment.schedulesToDelete.filter((schedule) => {
|
|
61
|
-
return !allFnsToDelete.find(backend.sameFunctionName(schedule.targetService));
|
|
62
|
-
});
|
|
63
|
-
fullDeployment.topicsToDelete = fullDeployment.topicsToDelete.filter((topic) => {
|
|
64
|
-
return !allFnsToDelete.find(backend.sameFunctionName(topic.targetService));
|
|
65
|
-
});
|
|
66
|
-
for (const regionalDeployment of Object.values(fullDeployment.regionalDeployments)) {
|
|
67
|
-
regionalDeployment.functionsToDelete = [];
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
for (const [region, deployment] of Object.entries(fullDeployment.regionalDeployments)) {
|
|
71
|
-
regionPromises.push(tasks.runRegionalFunctionDeployment(taskParams, region, deployment, cloudFunctionsQueue));
|
|
72
|
-
}
|
|
73
|
-
for (const schedule of fullDeployment.schedulesToUpsert) {
|
|
74
|
-
const task = tasks.upsertScheduleTask(taskParams, schedule, appEngineLocation);
|
|
75
|
-
void schedulerQueue.run(task);
|
|
76
|
-
}
|
|
77
|
-
for (const schedule of fullDeployment.schedulesToDelete) {
|
|
78
|
-
const task = tasks.deleteScheduleTask(taskParams, schedule, appEngineLocation);
|
|
79
|
-
void schedulerQueue.run(task);
|
|
80
|
-
}
|
|
81
|
-
for (const topic of fullDeployment.topicsToDelete) {
|
|
82
|
-
const task = tasks.deleteTopicTask(taskParams, topic);
|
|
83
|
-
void pubSubQueue.run(task);
|
|
84
|
-
}
|
|
85
|
-
const queuePromises = [cloudFunctionsQueue.wait(), schedulerQueue.wait(), pubSubQueue.wait()];
|
|
86
|
-
cloudFunctionsQueue.process();
|
|
87
|
-
schedulerQueue.process();
|
|
88
|
-
pubSubQueue.process();
|
|
89
|
-
schedulerQueue.close();
|
|
90
|
-
pubSubQueue.close();
|
|
91
|
-
await Promise.all(regionPromises);
|
|
92
|
-
cloudFunctionsQueue.close();
|
|
93
|
-
try {
|
|
94
|
-
await Promise.all(queuePromises);
|
|
95
|
-
}
|
|
96
|
-
catch (err) {
|
|
97
|
-
utils.reject("Exceeded maximum retries while deploying functions. " +
|
|
98
|
-
"If you are deploying a large number of functions, " +
|
|
99
|
-
"please deploy your functions in batches by using the --only flag, " +
|
|
100
|
-
"and wait a few minutes before deploying again. " +
|
|
101
|
-
"Go to https://firebase.google.com/docs/cli/#partial_deploys to learn more.", {
|
|
102
|
-
original: err,
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
const functions = payload.functions.backend.cloudFunctions;
|
|
106
|
-
const gcfv1 = functions.find((fn) => fn.platform === "gcfv1");
|
|
107
|
-
const gcfv2 = functions.find((fn) => fn.platform === "gcfv2");
|
|
108
|
-
const tag = gcfv1 && gcfv2 ? "v1+v2" : gcfv1 ? "v1" : "v2";
|
|
109
|
-
track_1.track("functions_codebase_deploy", tag, functions.length);
|
|
110
|
-
helper.logAndTrackDeployStats(cloudFunctionsQueue, errorHandler);
|
|
111
|
-
await containerCleaner.cleanupBuildImages(payload.functions.backend.cloudFunctions);
|
|
112
|
-
await helper.printTriggerUrls(context, payload.functions.backend);
|
|
113
|
-
errorHandler.printWarnings();
|
|
114
|
-
errorHandler.printErrors();
|
|
115
|
-
}
|
|
116
|
-
exports.release = release;
|