firebase-tools 9.19.0 → 9.23.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 +1 -3
- package/lib/api.js +3 -0
- package/lib/apiv2.js +7 -4
- package/lib/commands/crashlytics-symbols-upload.js +146 -0
- package/lib/commands/deploy.js +9 -1
- package/lib/commands/ext-configure.js +3 -1
- package/lib/commands/ext-dev-deprecate.js +63 -0
- package/lib/commands/ext-dev-undeprecate.js +56 -0
- package/lib/commands/ext-dev-unpublish.js +10 -3
- package/lib/commands/ext-export.js +44 -0
- package/lib/commands/ext-install.js +24 -3
- package/lib/commands/ext-uninstall.js +6 -0
- package/lib/commands/ext-update.js +10 -3
- package/lib/commands/functions-config-export.js +115 -0
- package/lib/commands/functions-delete.js +47 -25
- package/lib/commands/functions-list.js +12 -12
- package/lib/commands/index.js +9 -0
- package/lib/commands/init.js +3 -0
- package/lib/config.js +3 -2
- package/lib/deploy/extensions/args.js +2 -0
- package/lib/deploy/extensions/deploy.js +49 -0
- package/lib/deploy/extensions/deploymentSummary.js +52 -0
- package/lib/deploy/extensions/errors.js +31 -0
- package/lib/deploy/extensions/index.js +8 -0
- package/lib/deploy/extensions/params.js +39 -0
- package/lib/deploy/extensions/planner.js +94 -0
- package/lib/deploy/extensions/prepare.js +111 -0
- package/lib/deploy/extensions/release.js +43 -0
- package/lib/deploy/extensions/secrets.js +150 -0
- package/lib/deploy/extensions/tasks.js +98 -0
- package/lib/deploy/extensions/validate.js +17 -0
- package/lib/deploy/functions/backend.js +93 -115
- package/lib/deploy/functions/checkIam.js +8 -8
- package/lib/deploy/functions/containerCleaner.js +71 -14
- package/lib/deploy/functions/deploy.js +4 -10
- package/lib/deploy/functions/functionsDeployHelper.js +3 -68
- package/lib/deploy/functions/prepare.js +63 -27
- 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 +422 -0
- package/lib/deploy/functions/release/index.js +73 -0
- package/lib/deploy/functions/release/planner.js +162 -0
- package/lib/deploy/functions/release/reporter.js +165 -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 +129 -126
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +41 -45
- package/lib/deploy/functions/triggerRegionHelper.js +40 -0
- package/lib/deploy/functions/validate.js +1 -24
- package/lib/deploy/index.js +10 -1
- package/lib/downloadUtils.js +37 -0
- package/lib/emulator/auth/apiSpec.js +549 -6
- package/lib/emulator/auth/handlers.js +4 -3
- package/lib/emulator/auth/operations.js +154 -14
- package/lib/emulator/auth/server.js +26 -15
- package/lib/emulator/auth/state.js +151 -13
- package/lib/emulator/download.js +2 -31
- package/lib/emulator/downloadableEmulators.js +7 -7
- package/lib/emulator/functionsEmulator.js +18 -4
- package/lib/emulator/functionsEmulatorRuntime.js +29 -7
- package/lib/emulator/storage/cloudFunctions.js +37 -7
- package/lib/extensions/askUserForConsent.js +14 -1
- package/lib/extensions/askUserForParam.js +81 -4
- package/lib/extensions/checkProjectBilling.js +7 -7
- package/lib/extensions/export.js +107 -0
- package/lib/extensions/extensionsApi.js +104 -21
- package/lib/extensions/extensionsHelper.js +6 -2
- package/lib/extensions/listExtensions.js +16 -11
- package/lib/extensions/paramHelper.js +9 -6
- package/lib/extensions/provisioningHelper.js +16 -3
- package/lib/extensions/refs.js +9 -1
- package/lib/extensions/secretsUtils.js +59 -0
- package/lib/extensions/updateHelper.js +12 -2
- package/lib/extensions/versionHelper.js +14 -0
- package/lib/extensions/warnings.js +33 -1
- package/lib/functional.js +8 -1
- package/lib/functions/env.js +10 -4
- package/lib/functions/runtimeConfigExport.js +137 -0
- package/lib/gcp/artifactregistry.js +16 -0
- package/lib/gcp/cloudfunctions.js +20 -74
- package/lib/gcp/cloudfunctionsv2.js +12 -90
- package/lib/gcp/cloudscheduler.js +22 -16
- package/lib/gcp/cloudtasks.js +143 -0
- package/lib/gcp/docker.js +7 -1
- package/lib/gcp/proto.js +2 -2
- package/lib/gcp/pubsub.js +1 -9
- package/lib/gcp/secretManager.js +132 -0
- package/lib/gcp/storage.js +16 -0
- package/lib/projectUtils.js +10 -1
- package/lib/requireInteractive.js +12 -0
- package/lib/utils.js +30 -1
- package/package.json +5 -4
- package/schema/firebase-config.json +9 -0
- 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,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;
|
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.schedulerDeploymentHandler = exports.deleteTopicTask = exports.deleteScheduleTask = exports.upsertScheduleTask = exports.runRegionalFunctionDeployment = exports.functionsDeploymentHandler = exports.deleteFunctionTask = exports.updateFunctionTask = exports.createFunctionTask = void 0;
|
|
4
|
-
const clc = require("cli-color");
|
|
5
|
-
const logger_1 = require("../../logger");
|
|
6
|
-
const operation_poller_1 = require("../../operation-poller");
|
|
7
|
-
const api_1 = require("../../api");
|
|
8
|
-
const runtimes_1 = require("./runtimes");
|
|
9
|
-
const backend = require("./backend");
|
|
10
|
-
const cloudscheduler = require("../../gcp/cloudscheduler");
|
|
11
|
-
const deploymentTool = require("../../deploymentTool");
|
|
12
|
-
const gcf = require("../../gcp/cloudfunctions");
|
|
13
|
-
const gcfV2 = require("../../gcp/cloudfunctionsv2");
|
|
14
|
-
const cloudrun = require("../../gcp/run");
|
|
15
|
-
const helper = require("./functionsDeployHelper");
|
|
16
|
-
const pubsub = require("../../gcp/pubsub");
|
|
17
|
-
const utils = require("../../utils");
|
|
18
|
-
const error_1 = require("../../error");
|
|
19
|
-
const track_1 = require("../../track");
|
|
20
|
-
const gcfV1PollerOptions = {
|
|
21
|
-
apiOrigin: api_1.functionsOrigin,
|
|
22
|
-
apiVersion: gcf.API_VERSION,
|
|
23
|
-
masterTimeout: 25 * 60 * 1000,
|
|
24
|
-
};
|
|
25
|
-
const gcfV2PollerOptions = {
|
|
26
|
-
apiOrigin: api_1.functionsV2Origin,
|
|
27
|
-
apiVersion: gcfV2.API_VERSION,
|
|
28
|
-
masterTimeout: 25 * 60 * 1000,
|
|
29
|
-
};
|
|
30
|
-
const pollerOptionsByPlatform = {
|
|
31
|
-
gcfv1: gcfV1PollerOptions,
|
|
32
|
-
gcfv2: gcfV2PollerOptions,
|
|
33
|
-
};
|
|
34
|
-
function createFunctionTask(params, fn, sourceToken, onPoll) {
|
|
35
|
-
const fnName = backend.functionName(fn);
|
|
36
|
-
const run = async () => {
|
|
37
|
-
var _a;
|
|
38
|
-
utils.logBullet(clc.bold.cyan("functions: ") +
|
|
39
|
-
"creating " +
|
|
40
|
-
runtimes_1.getHumanFriendlyRuntimeName(fn.runtime) +
|
|
41
|
-
" function " +
|
|
42
|
-
clc.bold(helper.getFunctionLabel(fn)) +
|
|
43
|
-
"...");
|
|
44
|
-
let op;
|
|
45
|
-
if (fn.platform === "gcfv1") {
|
|
46
|
-
const apiFunction = gcf.functionFromSpec(fn, params.sourceUrl);
|
|
47
|
-
if (sourceToken) {
|
|
48
|
-
apiFunction.sourceToken = sourceToken;
|
|
49
|
-
}
|
|
50
|
-
op = await gcf.createFunction(apiFunction);
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
const apiFunction = gcfV2.functionFromSpec(fn, params.storage[fn.region]);
|
|
54
|
-
if ((_a = apiFunction.eventTrigger) === null || _a === void 0 ? void 0 : _a.pubsubTopic) {
|
|
55
|
-
try {
|
|
56
|
-
await pubsub.getTopic(apiFunction.eventTrigger.pubsubTopic);
|
|
57
|
-
}
|
|
58
|
-
catch (err) {
|
|
59
|
-
if (err.status !== 404) {
|
|
60
|
-
throw new error_1.FirebaseError("Unexpected error looking for Pub/Sub topic", {
|
|
61
|
-
original: err,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
await pubsub.createTopic({
|
|
65
|
-
name: apiFunction.eventTrigger.pubsubTopic,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
op = await gcfV2.createFunction(apiFunction);
|
|
70
|
-
}
|
|
71
|
-
const cloudFunction = await operation_poller_1.pollOperation(Object.assign(Object.assign({}, pollerOptionsByPlatform[fn.platform]), { pollerName: `create-${fnName}`, operationResourceName: op.name, onPoll }));
|
|
72
|
-
if (!backend.isEventTrigger(fn.trigger)) {
|
|
73
|
-
const invoker = fn.trigger.invoker || ["public"];
|
|
74
|
-
if (invoker[0] !== "private") {
|
|
75
|
-
try {
|
|
76
|
-
if (fn.platform === "gcfv1") {
|
|
77
|
-
await gcf.setInvokerCreate(params.projectId, fnName, invoker);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
const serviceName = cloudFunction.serviceConfig.service;
|
|
81
|
-
cloudrun.setInvokerCreate(params.projectId, serviceName, invoker);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (err) {
|
|
85
|
-
params.errorHandler.record("error", fnName, "set invoker", err.message);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (fn.platform !== "gcfv1") {
|
|
90
|
-
await setConcurrency(cloudFunction.serviceConfig.service, fn.concurrency || 80);
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
return {
|
|
94
|
-
run,
|
|
95
|
-
data: fn,
|
|
96
|
-
operationType: "create",
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
exports.createFunctionTask = createFunctionTask;
|
|
100
|
-
function updateFunctionTask(params, fn, sourceToken, onPoll) {
|
|
101
|
-
const fnName = backend.functionName(fn);
|
|
102
|
-
const run = async () => {
|
|
103
|
-
var _a;
|
|
104
|
-
utils.logBullet(clc.bold.cyan("functions: ") +
|
|
105
|
-
"updating " +
|
|
106
|
-
runtimes_1.getHumanFriendlyRuntimeName(fn.runtime) +
|
|
107
|
-
" function " +
|
|
108
|
-
clc.bold(helper.getFunctionLabel(fn)) +
|
|
109
|
-
"...");
|
|
110
|
-
let opName;
|
|
111
|
-
if (fn.platform == "gcfv1") {
|
|
112
|
-
const apiFunction = gcf.functionFromSpec(fn, params.sourceUrl);
|
|
113
|
-
if (sourceToken) {
|
|
114
|
-
apiFunction.sourceToken = sourceToken;
|
|
115
|
-
}
|
|
116
|
-
opName = (await gcf.updateFunction(apiFunction)).name;
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
const apiFunction = gcfV2.functionFromSpec(fn, params.storage[fn.region]);
|
|
120
|
-
if ((_a = apiFunction.eventTrigger) === null || _a === void 0 ? void 0 : _a.pubsubTopic) {
|
|
121
|
-
delete apiFunction.eventTrigger.pubsubTopic;
|
|
122
|
-
}
|
|
123
|
-
opName = (await gcfV2.updateFunction(apiFunction)).name;
|
|
124
|
-
}
|
|
125
|
-
const pollerOptions = Object.assign(Object.assign({}, pollerOptionsByPlatform[fn.platform]), { pollerName: `update-${fnName}`, operationResourceName: opName, onPoll });
|
|
126
|
-
const cloudFunction = await operation_poller_1.pollOperation(pollerOptions);
|
|
127
|
-
if (!backend.isEventTrigger(fn.trigger) && fn.trigger.invoker) {
|
|
128
|
-
try {
|
|
129
|
-
if (fn.platform === "gcfv1") {
|
|
130
|
-
await gcf.setInvokerUpdate(params.projectId, fnName, fn.trigger.invoker);
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
const serviceName = cloudFunction.serviceConfig.service;
|
|
134
|
-
cloudrun.setInvokerUpdate(params.projectId, serviceName, fn.trigger.invoker);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
catch (err) {
|
|
138
|
-
params.errorHandler.record("error", fnName, "set invoker", err.message);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
if ("concurrency" in fn) {
|
|
142
|
-
if (fn.platform === "gcfv1") {
|
|
143
|
-
throw new error_1.FirebaseError("Precondition failed: GCFv1 does not support concurrency");
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
await setConcurrency(cloudFunction.serviceConfig.service, fn.concurrency || 80);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
return {
|
|
151
|
-
run,
|
|
152
|
-
data: fn,
|
|
153
|
-
operationType: "update",
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
exports.updateFunctionTask = updateFunctionTask;
|
|
157
|
-
function deleteFunctionTask(params, fn) {
|
|
158
|
-
const fnName = backend.functionName(fn);
|
|
159
|
-
const run = async () => {
|
|
160
|
-
utils.logBullet(clc.bold.cyan("functions: ") +
|
|
161
|
-
"deleting function " +
|
|
162
|
-
clc.bold(helper.getFunctionLabel(fnName)) +
|
|
163
|
-
"...");
|
|
164
|
-
let res;
|
|
165
|
-
if (fn.platform == "gcfv1") {
|
|
166
|
-
res = await gcf.deleteFunction(fnName);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
res = await gcfV2.deleteFunction(fnName);
|
|
170
|
-
}
|
|
171
|
-
const pollerOptions = Object.assign(Object.assign({}, pollerOptionsByPlatform[fn.platform]), { pollerName: `delete-${fnName}`, operationResourceName: res.name });
|
|
172
|
-
await operation_poller_1.pollOperation(pollerOptions);
|
|
173
|
-
};
|
|
174
|
-
return {
|
|
175
|
-
run,
|
|
176
|
-
data: fn,
|
|
177
|
-
operationType: "delete",
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
exports.deleteFunctionTask = deleteFunctionTask;
|
|
181
|
-
async function setConcurrency(name, concurrency) {
|
|
182
|
-
const err = null;
|
|
183
|
-
while (true) {
|
|
184
|
-
const service = await cloudrun.getService(name);
|
|
185
|
-
delete service.status;
|
|
186
|
-
delete service.spec.template.metadata.name;
|
|
187
|
-
service.spec.template.spec.containerConcurrency = concurrency;
|
|
188
|
-
try {
|
|
189
|
-
await cloudrun.replaceService(name, service);
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
catch (err) {
|
|
193
|
-
if (err.status !== 409) {
|
|
194
|
-
throw new error_1.FirebaseError("Unexpected error while trying to set concurrency", {
|
|
195
|
-
original: err,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
function functionsDeploymentHandler(timer, errorHandler) {
|
|
202
|
-
return async (task) => {
|
|
203
|
-
var _a, _b, _c, _d;
|
|
204
|
-
let result;
|
|
205
|
-
const fnName = backend.functionName(task.data);
|
|
206
|
-
try {
|
|
207
|
-
timer.startTimer(fnName, task.operationType);
|
|
208
|
-
result = await task.run();
|
|
209
|
-
helper.printSuccess(task.data, task.operationType);
|
|
210
|
-
const duration = timer.endTimer(fnName);
|
|
211
|
-
track_1.track("function_deploy_success", backend.triggerTag(task.data), duration);
|
|
212
|
-
}
|
|
213
|
-
catch (err) {
|
|
214
|
-
if (((_c = (_b = (_a = err.original) === null || _a === void 0 ? void 0 : _a.context) === null || _b === void 0 ? void 0 : _b.response) === null || _c === void 0 ? void 0 : _c.statusCode) === 429) {
|
|
215
|
-
throw err;
|
|
216
|
-
}
|
|
217
|
-
errorHandler.record("error", fnName, task.operationType, ((_d = err.original) === null || _d === void 0 ? void 0 : _d.message) || "");
|
|
218
|
-
const duration = timer.endTimer(fnName);
|
|
219
|
-
track_1.track("function_deploy_failure", backend.triggerTag(task.data), duration);
|
|
220
|
-
}
|
|
221
|
-
return result;
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
exports.functionsDeploymentHandler = functionsDeploymentHandler;
|
|
225
|
-
async function runRegionalFunctionDeployment(params, region, regionalDeployment, queue) {
|
|
226
|
-
let resolveToken;
|
|
227
|
-
const getRealToken = new Promise((resolve) => (resolveToken = resolve));
|
|
228
|
-
let firstToken = true;
|
|
229
|
-
const getToken = () => {
|
|
230
|
-
if (firstToken) {
|
|
231
|
-
firstToken = false;
|
|
232
|
-
return Promise.resolve(undefined);
|
|
233
|
-
}
|
|
234
|
-
return getRealToken;
|
|
235
|
-
};
|
|
236
|
-
const onPollFn = (op) => {
|
|
237
|
-
var _a, _b;
|
|
238
|
-
if (((_a = op.metadata) === null || _a === void 0 ? void 0 : _a.sourceToken) || op.done) {
|
|
239
|
-
logger_1.logger.debug(`Got sourceToken ${op.metadata.sourceToken} for region ${region}`);
|
|
240
|
-
resolveToken((_b = op.metadata) === null || _b === void 0 ? void 0 : _b.sourceToken);
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
const deploy = async (functionSpec, createTask) => {
|
|
244
|
-
functionSpec.labels = Object.assign(Object.assign({}, (functionSpec.labels || {})), deploymentTool.labels());
|
|
245
|
-
let task;
|
|
246
|
-
if (functionSpec.platform == "gcfv2") {
|
|
247
|
-
task = createTask(params, functionSpec, undefined, () => undefined);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
const sourceToken = await getToken();
|
|
251
|
-
task = createTask(params, functionSpec, sourceToken, onPollFn);
|
|
252
|
-
}
|
|
253
|
-
return queue.run(task);
|
|
254
|
-
};
|
|
255
|
-
const deploys = [];
|
|
256
|
-
deploys.push(...regionalDeployment.functionsToCreate.map((fn) => deploy(fn, createFunctionTask)));
|
|
257
|
-
deploys.push(...regionalDeployment.functionsToUpdate.map(async (update) => {
|
|
258
|
-
if (update.deleteAndRecreate) {
|
|
259
|
-
await queue.run(deleteFunctionTask(params, update.func));
|
|
260
|
-
return deploy(update.func, createFunctionTask);
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
return deploy(update.func, updateFunctionTask);
|
|
264
|
-
}
|
|
265
|
-
}));
|
|
266
|
-
await Promise.all(deploys);
|
|
267
|
-
const deletes = regionalDeployment.functionsToDelete.map(async (fn) => {
|
|
268
|
-
const task = deleteFunctionTask(params, fn);
|
|
269
|
-
await queue.run(task);
|
|
270
|
-
});
|
|
271
|
-
await Promise.all(deletes);
|
|
272
|
-
}
|
|
273
|
-
exports.runRegionalFunctionDeployment = runRegionalFunctionDeployment;
|
|
274
|
-
function upsertScheduleTask(params, schedule, appEngineLocation) {
|
|
275
|
-
const run = async () => {
|
|
276
|
-
const job = cloudscheduler.jobFromSpec(schedule, appEngineLocation);
|
|
277
|
-
await cloudscheduler.createOrReplaceJob(job);
|
|
278
|
-
};
|
|
279
|
-
return {
|
|
280
|
-
run,
|
|
281
|
-
data: schedule,
|
|
282
|
-
operationType: "upsert schedule",
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
exports.upsertScheduleTask = upsertScheduleTask;
|
|
286
|
-
function deleteScheduleTask(params, schedule, appEngineLocation) {
|
|
287
|
-
const run = async () => {
|
|
288
|
-
const jobName = backend.scheduleName(schedule, appEngineLocation);
|
|
289
|
-
await cloudscheduler.deleteJob(jobName);
|
|
290
|
-
};
|
|
291
|
-
return {
|
|
292
|
-
run,
|
|
293
|
-
data: schedule,
|
|
294
|
-
operationType: "delete schedule",
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
exports.deleteScheduleTask = deleteScheduleTask;
|
|
298
|
-
function deleteTopicTask(params, topic) {
|
|
299
|
-
const run = async () => {
|
|
300
|
-
const topicName = backend.topicName(topic);
|
|
301
|
-
await pubsub.deleteTopic(topicName);
|
|
302
|
-
};
|
|
303
|
-
return {
|
|
304
|
-
run,
|
|
305
|
-
data: topic,
|
|
306
|
-
operationType: "delete topic",
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
exports.deleteTopicTask = deleteTopicTask;
|
|
310
|
-
exports.schedulerDeploymentHandler = (errorHandler) => async (task) => {
|
|
311
|
-
try {
|
|
312
|
-
const result = await task.run();
|
|
313
|
-
helper.printSuccess(task.data.targetService, task.operationType);
|
|
314
|
-
return result;
|
|
315
|
-
}
|
|
316
|
-
catch (err) {
|
|
317
|
-
if (err.status === 429) {
|
|
318
|
-
throw err;
|
|
319
|
-
}
|
|
320
|
-
else if (err.status !== 404) {
|
|
321
|
-
errorHandler.record("error", backend.functionName(task.data.targetService), task.operationType, err.message || "");
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.listFunctions = void 0;
|
|
4
|
-
const backend = require("../deploy/functions/backend");
|
|
5
|
-
async function listFunctions(context) {
|
|
6
|
-
const functionSpecs = (await backend.existingBackend(context, true)).cloudFunctions;
|
|
7
|
-
functionSpecs.sort(backend.compareFunctions);
|
|
8
|
-
return { functions: functionSpecs };
|
|
9
|
-
}
|
|
10
|
-
exports.listFunctions = listFunctions;
|
package/lib/functionsDelete.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deleteFunctions = void 0;
|
|
4
|
-
const helper = require("./deploy/functions/functionsDeployHelper");
|
|
5
|
-
const queue_1 = require("./throttler/queue");
|
|
6
|
-
const tasks = require("./deploy/functions/tasks");
|
|
7
|
-
const deploymentTimer_1 = require("./deploy/functions/deploymentTimer");
|
|
8
|
-
const errorHandler_1 = require("./deploy/functions/errorHandler");
|
|
9
|
-
async function deleteFunctions(functionsToDelete, schedulesToDelete, topicsToDelete, appEngineLocation) {
|
|
10
|
-
const timer = new deploymentTimer_1.DeploymentTimer();
|
|
11
|
-
const errorHandler = new errorHandler_1.ErrorHandler();
|
|
12
|
-
const cloudFunctionsQueue = new queue_1.Queue({
|
|
13
|
-
handler: tasks.functionsDeploymentHandler(timer, errorHandler),
|
|
14
|
-
retries: 30,
|
|
15
|
-
backoff: 10000,
|
|
16
|
-
concurrency: 40,
|
|
17
|
-
maxBackoff: 40000,
|
|
18
|
-
});
|
|
19
|
-
const schedulerQueue = new queue_1.Queue({
|
|
20
|
-
handler: tasks.schedulerDeploymentHandler(errorHandler),
|
|
21
|
-
});
|
|
22
|
-
const topicQueue = new queue_1.Queue({
|
|
23
|
-
handler: tasks.schedulerDeploymentHandler(errorHandler),
|
|
24
|
-
});
|
|
25
|
-
functionsToDelete.forEach((fn) => {
|
|
26
|
-
const taskParams = {
|
|
27
|
-
projectId: fn.project,
|
|
28
|
-
errorHandler,
|
|
29
|
-
};
|
|
30
|
-
const deleteFunctionTask = tasks.deleteFunctionTask(taskParams, fn);
|
|
31
|
-
void cloudFunctionsQueue.run(deleteFunctionTask);
|
|
32
|
-
});
|
|
33
|
-
schedulesToDelete.forEach((schedule) => {
|
|
34
|
-
const taskParams = {
|
|
35
|
-
projectId: schedule.project,
|
|
36
|
-
errorHandler,
|
|
37
|
-
};
|
|
38
|
-
const deleteSchedulerTask = tasks.deleteScheduleTask(taskParams, schedule, appEngineLocation);
|
|
39
|
-
void schedulerQueue.run(deleteSchedulerTask);
|
|
40
|
-
});
|
|
41
|
-
topicsToDelete.forEach((topic) => {
|
|
42
|
-
const taskParams = {
|
|
43
|
-
projectId: topic.project,
|
|
44
|
-
errorHandler,
|
|
45
|
-
};
|
|
46
|
-
const deleteTopicTask = tasks.deleteTopicTask(taskParams, topic);
|
|
47
|
-
void topicQueue.run(deleteTopicTask);
|
|
48
|
-
});
|
|
49
|
-
const queuePromises = [cloudFunctionsQueue.wait(), schedulerQueue.wait(), topicQueue.wait()];
|
|
50
|
-
cloudFunctionsQueue.close();
|
|
51
|
-
schedulerQueue.close();
|
|
52
|
-
topicQueue.close();
|
|
53
|
-
cloudFunctionsQueue.process();
|
|
54
|
-
schedulerQueue.process();
|
|
55
|
-
topicQueue.process();
|
|
56
|
-
await Promise.all(queuePromises);
|
|
57
|
-
helper.logAndTrackDeployStats(cloudFunctionsQueue, errorHandler);
|
|
58
|
-
errorHandler.printErrors();
|
|
59
|
-
}
|
|
60
|
-
exports.deleteFunctions = deleteFunctions;
|