firebase-tools 13.6.0 → 13.6.1

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.
Files changed (49) hide show
  1. package/lib/apphosting/config.js +31 -0
  2. package/lib/apphosting/githubConnections.js +261 -0
  3. package/lib/{init/features/apphosting → apphosting}/index.js +21 -17
  4. package/lib/{init/features/apphosting → apphosting}/repo.js +9 -9
  5. package/lib/apphosting/secrets/dialogs.js +169 -0
  6. package/lib/apphosting/secrets/index.js +98 -0
  7. package/lib/commands/apphosting-backends-create.js +4 -2
  8. package/lib/commands/apphosting-backends-delete.js +1 -1
  9. package/lib/commands/apphosting-secrets-describe.js +29 -0
  10. package/lib/commands/apphosting-secrets-grantaccess.js +45 -0
  11. package/lib/commands/apphosting-secrets-set.js +102 -0
  12. package/lib/commands/functions-secrets-access.js +2 -2
  13. package/lib/commands/functions-secrets-describe.js +14 -0
  14. package/lib/commands/functions-secrets-destroy.js +2 -2
  15. package/lib/commands/functions-secrets-get.js +3 -17
  16. package/lib/commands/functions-secrets-prune.js +2 -1
  17. package/lib/commands/functions-secrets-set.js +2 -2
  18. package/lib/commands/index.js +5 -0
  19. package/lib/deploy/functions/checkIam.js +3 -6
  20. package/lib/deploy/functions/containerCleaner.js +1 -11
  21. package/lib/deploy/functions/params.js +2 -2
  22. package/lib/deploy/functions/prepare.js +12 -3
  23. package/lib/deploy/functions/release/fabricator.js +5 -5
  24. package/lib/deploy/functions/runtimes/index.js +6 -43
  25. package/lib/deploy/functions/runtimes/node/index.js +3 -2
  26. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +15 -34
  27. package/lib/deploy/functions/runtimes/python/index.js +11 -7
  28. package/lib/deploy/functions/runtimes/supported.js +135 -0
  29. package/lib/emulator/controller.js +8 -1
  30. package/lib/emulator/functionsEmulator.js +2 -2
  31. package/lib/emulator/hub.js +5 -0
  32. package/lib/extensions/emulator/specHelper.js +4 -3
  33. package/lib/functional.js +2 -2
  34. package/lib/functions/secrets.js +40 -22
  35. package/lib/gcp/apphosting.js +15 -2
  36. package/lib/gcp/cloudbuild.js +7 -3
  37. package/lib/gcp/cloudfunctions.js +5 -5
  38. package/lib/gcp/cloudfunctionsv2.js +3 -3
  39. package/lib/gcp/cloudscheduler.js +2 -2
  40. package/lib/gcp/computeEngine.js +7 -0
  41. package/lib/gcp/devConnect.js +24 -11
  42. package/lib/gcp/iam.js +9 -1
  43. package/lib/gcp/secretManager.js +53 -13
  44. package/lib/gcp/serviceusage.js +21 -5
  45. package/lib/init/features/functions/python.js +4 -3
  46. package/lib/init/features/index.js +1 -1
  47. package/package.json +1 -1
  48. package/schema/firebase-config.json +12 -2
  49. /package/lib/{init/features/apphosting → apphosting}/constants.js +0 -0
@@ -1,31 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRuntimeChoice = exports.DEPRECATED_NODE_VERSION_INFO = exports.UNSUPPORTED_NODE_VERSION_PACKAGE_JSON_MSG = exports.UNSUPPORTED_NODE_VERSION_FIREBASE_JSON_MSG = exports.RUNTIME_NOT_SET = void 0;
3
+ exports.getRuntimeChoice = exports.RUNTIME_NOT_SET = void 0;
4
4
  const path = require("path");
5
- const clc = require("colorette");
6
5
  const error_1 = require("../../../../error");
7
- const runtimes = require("../../runtimes");
6
+ const supported = require("../supported");
8
7
  const cjson = require("cjson");
9
- const ENGINE_RUNTIMES = {
10
- 6: "nodejs6",
11
- 8: "nodejs8",
12
- 10: "nodejs10",
13
- 12: "nodejs12",
14
- 14: "nodejs14",
15
- 16: "nodejs16",
16
- 18: "nodejs18",
17
- 20: "nodejs20",
18
- };
19
- const ENGINE_RUNTIMES_NAMES = Object.values(ENGINE_RUNTIMES);
20
- exports.RUNTIME_NOT_SET = "`runtime` field is required but was not found in firebase.json.\n" +
8
+ const supportedNodeVersions = Object.keys(supported.RUNTIMES)
9
+ .filter((s) => supported.runtimeIsLanguage(s, "nodejs"))
10
+ .filter((s) => !supported.isDecommissioned(s))
11
+ .map((s) => s.substring("nodejs".length));
12
+ exports.RUNTIME_NOT_SET = "`runtime` field is required but was not found in firebase.json or package.json.\n" +
21
13
  "To fix this, add the following lines to the `functions` section of your firebase.json:\n" +
22
- '"runtime": "nodejs18"\n';
23
- exports.UNSUPPORTED_NODE_VERSION_FIREBASE_JSON_MSG = clc.bold(`functions.runtime value is unsupported. ` +
24
- `Valid choices are: ${clc.bold("nodejs{10|12|14|16|18|20}")}.`);
25
- exports.UNSUPPORTED_NODE_VERSION_PACKAGE_JSON_MSG = clc.bold(`package.json in functions directory has an engines field which is unsupported. ` +
26
- `Valid choices are: ${clc.bold('{"node": 10|12|14|16|18|20}')}`);
27
- exports.DEPRECATED_NODE_VERSION_INFO = `\n\nDeploys to runtimes below Node.js 10 are now disabled in the Firebase CLI. ` +
28
- `${clc.bold(`Existing Node.js 8 functions ${clc.underline("will stop executing at a future date")}`)}. Update existing functions to Node.js 10 or greater as soon as possible.`;
14
+ `"runtime": "${supported.latest("nodejs")}" or set the "engine" field in package.json\n`;
29
15
  function getRuntimeChoiceFromPackageJson(sourceDir) {
30
16
  const packageJsonPath = path.join(sourceDir, "package.json");
31
17
  let loaded;
@@ -39,19 +25,14 @@ function getRuntimeChoiceFromPackageJson(sourceDir) {
39
25
  if (!engines || !engines.node) {
40
26
  throw new error_1.FirebaseError(exports.RUNTIME_NOT_SET);
41
27
  }
42
- return ENGINE_RUNTIMES[engines.node];
43
- }
44
- function getRuntimeChoice(sourceDir, runtimeFromConfig) {
45
- const runtime = runtimeFromConfig || getRuntimeChoiceFromPackageJson(sourceDir);
46
- const errorMessage = (runtimeFromConfig
47
- ? exports.UNSUPPORTED_NODE_VERSION_FIREBASE_JSON_MSG
48
- : exports.UNSUPPORTED_NODE_VERSION_PACKAGE_JSON_MSG) + exports.DEPRECATED_NODE_VERSION_INFO;
49
- if (!runtime || !ENGINE_RUNTIMES_NAMES.includes(runtime)) {
50
- throw new error_1.FirebaseError(errorMessage, { exit: 1 });
51
- }
52
- if (runtimes.isDeprecatedRuntime(runtime) || !runtimes.isValidRuntime(runtime)) {
53
- throw new error_1.FirebaseError(errorMessage, { exit: 1 });
28
+ const runtime = `nodejs${engines.node}`;
29
+ if (!supported.isRuntime(runtime)) {
30
+ throw new error_1.FirebaseError(`Detected node engine ${engines.node} in package.json, which is not a ` +
31
+ `supported version. Valid versions are ${supportedNodeVersions.join(", ")}`);
54
32
  }
55
33
  return runtime;
56
34
  }
35
+ function getRuntimeChoice(sourceDir, runtimeFromConfig) {
36
+ return runtimeFromConfig || getRuntimeChoiceFromPackageJson(sourceDir);
37
+ }
57
38
  exports.getRuntimeChoice = getRuntimeChoice;
@@ -1,27 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Delegate = exports.getPythonBinary = exports.tryCreateDelegate = exports.LATEST_VERSION = void 0;
3
+ exports.Delegate = exports.getPythonBinary = exports.tryCreateDelegate = void 0;
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  const node_fetch_1 = require("node-fetch");
7
7
  const util_1 = require("util");
8
8
  const portfinder = require("portfinder");
9
- const runtimes = require("..");
10
9
  const discovery = require("../discovery");
10
+ const supported = require("../supported");
11
11
  const logger_1 = require("../../../../logger");
12
12
  const python_1 = require("../../../../functions/python");
13
13
  const error_1 = require("../../../../error");
14
- exports.LATEST_VERSION = "python312";
14
+ const functional_1 = require("../../../../functional");
15
15
  async function tryCreateDelegate(context) {
16
+ var _a;
16
17
  const requirementsTextPath = path.join(context.sourceDir, "requirements.txt");
17
18
  if (!(await (0, util_1.promisify)(fs.exists)(requirementsTextPath))) {
18
19
  logger_1.logger.debug("Customer code is not Python code.");
19
20
  return;
20
21
  }
21
- const runtime = context.runtime ? context.runtime : exports.LATEST_VERSION;
22
- if (!runtimes.isValidRuntime(runtime)) {
22
+ const runtime = (_a = context.runtime) !== null && _a !== void 0 ? _a : supported.latest("python");
23
+ if (!supported.isRuntime(runtime)) {
23
24
  throw new error_1.FirebaseError(`Runtime ${runtime} is not a valid Python runtime`);
24
25
  }
26
+ if (!supported.runtimeIsLanguage(runtime, "python")) {
27
+ throw new error_1.FirebaseError(`Internal error. Trying to construct a python runtime delegate for runtime ${runtime}`, { exit: 1 });
28
+ }
25
29
  return Promise.resolve(new Delegate(context.projectId, context.sourceDir, runtime));
26
30
  }
27
31
  exports.tryCreateDelegate = tryCreateDelegate;
@@ -38,7 +42,7 @@ function getPythonBinary(runtime) {
38
42
  else if (runtime === "python312") {
39
43
  return "python3.12";
40
44
  }
41
- return "python";
45
+ (0, functional_1.assertExhaustive)(runtime, `Unhandled python runtime ${runtime}`);
42
46
  }
43
47
  exports.getPythonBinary = getPythonBinary;
44
48
  class Delegate {
@@ -46,7 +50,7 @@ class Delegate {
46
50
  this.projectId = projectId;
47
51
  this.sourceDir = sourceDir;
48
52
  this.runtime = runtime;
49
- this.name = "python";
53
+ this.language = "python";
50
54
  this._bin = "";
51
55
  this._modulesDir = "";
52
56
  }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.guardVersionSupport = exports.isDecommissioned = exports.latest = exports.runtimeIsLanguage = exports.isRuntime = exports.RUNTIMES = void 0;
4
+ const error_1 = require("../../../error");
5
+ const utils = require("../../../utils");
6
+ function runtimes(r) {
7
+ return r;
8
+ }
9
+ exports.RUNTIMES = runtimes({
10
+ nodejs6: {
11
+ friendly: "Node.js 6",
12
+ status: "decommissioned",
13
+ deprecationDate: "2019-04-17",
14
+ decommissionDate: "2020-08-01",
15
+ },
16
+ nodejs8: {
17
+ friendly: "Node.js 8",
18
+ status: "decommissioned",
19
+ deprecationDate: "2020-06-05",
20
+ decommissionDate: "2021-02-01",
21
+ },
22
+ nodejs10: {
23
+ friendly: "Node.js 10",
24
+ status: "GA",
25
+ deprecationDate: "2024-01-30",
26
+ decommissionDate: "2025-01-30",
27
+ },
28
+ nodejs12: {
29
+ friendly: "Node.js 12",
30
+ status: "GA",
31
+ deprecationDate: "2024-01-30",
32
+ decommissionDate: "2025-01-30",
33
+ },
34
+ nodejs14: {
35
+ friendly: "Node.js 14",
36
+ status: "GA",
37
+ deprecationDate: "2024-01-30",
38
+ decommissionDate: "2025-01-30",
39
+ },
40
+ nodejs16: {
41
+ friendly: "Node.js 16",
42
+ status: "GA",
43
+ deprecationDate: "2024-01-30",
44
+ decommissionDate: "2025-01-30",
45
+ },
46
+ nodejs18: {
47
+ friendly: "Node.js 18",
48
+ status: "GA",
49
+ deprecationDate: "2025-04-30",
50
+ decommissionDate: "2025-10-31",
51
+ },
52
+ nodejs20: {
53
+ friendly: "Node.js 20",
54
+ status: "GA",
55
+ deprecationDate: "2026-04-30",
56
+ decommissionDate: "2026-10-31",
57
+ },
58
+ python310: {
59
+ friendly: "Python 3.10",
60
+ status: "GA",
61
+ deprecationDate: "2026-10-04",
62
+ decommissionDate: "2027-04-30",
63
+ },
64
+ python311: {
65
+ friendly: "Python 3.11",
66
+ status: "GA",
67
+ deprecationDate: "2027-10-24",
68
+ decommissionDate: "2028-04-30",
69
+ },
70
+ python312: {
71
+ friendly: "Python 3.12",
72
+ status: "GA",
73
+ deprecationDate: "2028-10-02",
74
+ decommissionDate: "2029-04-30",
75
+ },
76
+ });
77
+ function isRuntime(maybe) {
78
+ return maybe in exports.RUNTIMES;
79
+ }
80
+ exports.isRuntime = isRuntime;
81
+ function runtimeIsLanguage(runtime, language) {
82
+ return runtime.startsWith(language);
83
+ }
84
+ exports.runtimeIsLanguage = runtimeIsLanguage;
85
+ function latest(language, runtimes = Object.keys(exports.RUNTIMES)) {
86
+ const sorted = runtimes
87
+ .filter((s) => runtimeIsLanguage(s, language))
88
+ .sort((left, right) => {
89
+ const leftVersion = +left.substring(language.length);
90
+ const rightVersion = +right.substring(language.length);
91
+ if (isNaN(leftVersion) || isNaN(rightVersion)) {
92
+ throw new error_1.FirebaseError("Internal error. Runtime or language names are malformed", {
93
+ exit: 1,
94
+ });
95
+ }
96
+ return leftVersion - rightVersion;
97
+ });
98
+ const latest = utils.last(sorted);
99
+ if (!latest) {
100
+ throw new error_1.FirebaseError(`Internal error trying to find the latest supported runtime for ${language}`, { exit: 1 });
101
+ }
102
+ return latest;
103
+ }
104
+ exports.latest = latest;
105
+ function isDecommissioned(runtime, now = new Date()) {
106
+ const cutoff = new Date(exports.RUNTIMES[runtime].decommissionDate);
107
+ return cutoff < now;
108
+ }
109
+ exports.isDecommissioned = isDecommissioned;
110
+ function guardVersionSupport(runtime, now = new Date()) {
111
+ const { deprecationDate, decommissionDate } = exports.RUNTIMES[runtime];
112
+ const decommission = new Date(decommissionDate);
113
+ if (now >= decommission) {
114
+ throw new error_1.FirebaseError(`Runtime ${exports.RUNTIMES[runtime].friendly} was decommissioned on ${decommissionDate}. To deploy ` +
115
+ "you must first upgrade your runtime version.", { exit: 1 });
116
+ }
117
+ const deprecation = new Date(deprecationDate);
118
+ if (now >= deprecation) {
119
+ utils.logLabeledWarning("functions", `Runtime ${exports.RUNTIMES[runtime].friendly} was deprecated on ${deprecationDate} and will be ` +
120
+ `decommissioned on ${decommissionDate}, after which you will not be able ` +
121
+ "to deploy without upgrading. Consider upgrading now to avoid disruption. See " +
122
+ "https://cloud.google.com/functions/docs/runtime-support for full " +
123
+ "details on the lifecycle policy");
124
+ return;
125
+ }
126
+ const warning = new Date(deprecation.getTime() - 90 * 24 * 60 * 60 * 1000);
127
+ if (now >= warning) {
128
+ utils.logLabeledWarning("functions", `Runtime ${exports.RUNTIMES[runtime].friendly} will be deprecated on ${deprecationDate} and will be ` +
129
+ `decommissioned on ${decommissionDate}, after which you will not be able ` +
130
+ "to deploy without upgrading. Consider upgrading now to avoid disruption. See " +
131
+ "https://cloud.google.com/functions/docs/runtime-support for full " +
132
+ "details on the lifecycle policy");
133
+ }
134
+ }
135
+ exports.guardVersionSupport = guardVersionSupport;
@@ -41,6 +41,7 @@ const downloadableEmulators_1 = require("./downloadableEmulators");
41
41
  const frameworks_1 = require("../frameworks");
42
42
  const experiments = require("../experiments");
43
43
  const portUtils_1 = require("./portUtils");
44
+ const supported_1 = require("../deploy/functions/runtimes/supported");
44
45
  const START_LOGGING_EMULATOR = utils.envOverride("START_LOGGING_EMULATOR", "false", (val) => val === "true");
45
46
  async function exportOnExit(options) {
46
47
  const exportOnExitDir = options.exportOnExit;
@@ -308,7 +309,13 @@ async function startAll(options, showUI = true, runningTestScript = false) {
308
309
  utils.assertIsStringOrUndefined(options.extDevDir);
309
310
  for (const cfg of functionsCfg) {
310
311
  const functionsDir = path.join(projectDir, cfg.source);
311
- const runtime = (_e = options.extDevRuntime) !== null && _e !== void 0 ? _e : cfg.runtime;
312
+ let runtime = ((_e = options.extDevRuntime) !== null && _e !== void 0 ? _e : cfg.runtime);
313
+ if (!runtime) {
314
+ runtime = (0, supported_1.latest)("nodejs");
315
+ }
316
+ if (!(0, supported_1.isRuntime)(runtime)) {
317
+ throw new error_1.FirebaseError(`Cannot load functions from ${functionsDir} because it has invalid runtime ${runtime}`);
318
+ }
312
319
  emulatableBackends.push({
313
320
  functionsDir,
314
321
  runtime,
@@ -297,9 +297,9 @@ class FunctionsEmulator {
297
297
  runtime: emulatableBackend.runtime,
298
298
  };
299
299
  const runtimeDelegate = await runtimes.getRuntimeDelegate(runtimeDelegateContext);
300
- logger_1.logger.debug(`Validating ${runtimeDelegate.name} source`);
300
+ logger_1.logger.debug(`Validating ${runtimeDelegate.language} source`);
301
301
  await runtimeDelegate.validate();
302
- logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
302
+ logger_1.logger.debug(`Building ${runtimeDelegate.language} source`);
303
303
  await runtimeDelegate.build();
304
304
  emulatableBackend.runtime = runtimeDelegate.runtime;
305
305
  emulatableBackend.bin = runtimeDelegate.bin;
@@ -53,6 +53,11 @@ class EmulatorHub extends ExpressBasedEmulator_1.ExpressBasedEmulator {
53
53
  res.json(body);
54
54
  });
55
55
  app.post(EmulatorHub.PATH_EXPORT, async (req, res) => {
56
+ if (req.headers.origin) {
57
+ res.status(403).json({
58
+ message: `Export cannot be triggered by external callers.`,
59
+ });
60
+ }
56
61
  const path = req.body.path;
57
62
  const initiatedBy = req.body.initiatedBy || "unknown";
58
63
  utils.logLabeledBullet("emulators", `Received export request. Exporting data to ${path}.`);
@@ -4,6 +4,7 @@ exports.getRuntime = exports.DEFAULT_RUNTIME = exports.getFunctionProperties = e
4
4
  const yaml = require("js-yaml");
5
5
  const path = require("path");
6
6
  const fs = require("fs-extra");
7
+ const supported = require("../../deploy/functions/runtimes/supported");
7
8
  const error_1 = require("../../error");
8
9
  const extensionsHelper_1 = require("../extensionsHelper");
9
10
  const utils_1 = require("../utils");
@@ -77,7 +78,7 @@ function getFunctionProperties(resources) {
77
78
  return resources.map((r) => r.properties);
78
79
  }
79
80
  exports.getFunctionProperties = getFunctionProperties;
80
- exports.DEFAULT_RUNTIME = "nodejs14";
81
+ exports.DEFAULT_RUNTIME = supported.latest("nodejs");
81
82
  function getRuntime(resources) {
82
83
  if (resources.length === 0) {
83
84
  return exports.DEFAULT_RUNTIME;
@@ -88,7 +89,7 @@ function getRuntime(resources) {
88
89
  if (!runtime) {
89
90
  return exports.DEFAULT_RUNTIME;
90
91
  }
91
- if (!/^(nodejs)?([0-9]+)/.test(runtime)) {
92
+ if (!supported.runtimeIsLanguage(runtime, "nodejs")) {
92
93
  invalidRuntimes.push(runtime);
93
94
  return exports.DEFAULT_RUNTIME;
94
95
  }
@@ -97,6 +98,6 @@ function getRuntime(resources) {
97
98
  if (invalidRuntimes.length) {
98
99
  throw new error_1.FirebaseError(`The following runtimes are not supported by the Emulator Suite: ${invalidRuntimes.join(", ")}. \n Only Node runtimes are supported.`);
99
100
  }
100
- return runtimes.sort()[runtimes.length - 1];
101
+ return supported.latest("nodejs", runtimes);
101
102
  }
102
103
  exports.getRuntime = getRuntime;
package/lib/functional.js CHANGED
@@ -52,8 +52,8 @@ const zipIn = (other) => (elem, ndx) => {
52
52
  return [elem, other[ndx]];
53
53
  };
54
54
  exports.zipIn = zipIn;
55
- function assertExhaustive(val) {
56
- throw new Error(`Never has a value (${val}).`);
55
+ function assertExhaustive(val, message) {
56
+ throw new Error(message || `Never has a value (${val}).`);
57
57
  }
58
58
  exports.assertExhaustive = assertExhaustive;
59
59
  function partition(arr, predicate) {
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.versionInUse = exports.inUse = exports.getSecretVersions = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.ensureApi = exports.labels = exports.isFirebaseManaged = void 0;
3
+ exports.describeSecret = exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.versionInUse = exports.inUse = exports.getSecretVersions = exports.of = exports.ensureSecret = exports.ensureValidKey = void 0;
4
4
  const utils = require("../utils");
5
5
  const poller = require("../operation-poller");
6
6
  const gcfV1 = require("../gcp/cloudfunctions");
7
7
  const gcfV2 = require("../gcp/cloudfunctionsv2");
8
- const ensureApiEnabled = require("../ensureApiEnabled");
9
8
  const api_1 = require("../api");
10
9
  const secretManager_1 = require("../gcp/secretManager");
11
10
  const error_1 = require("../error");
@@ -14,8 +13,10 @@ const prompt_1 = require("../prompt");
14
13
  const env_1 = require("./env");
15
14
  const logger_1 = require("../logger");
16
15
  const functional_1 = require("../functional");
16
+ const secretManager_2 = require("../gcp/secretManager");
17
+ const secretManager_3 = require("../gcp/secretManager");
17
18
  const projectUtils_1 = require("../projectUtils");
18
- const FIREBASE_MANAGED = "firebase-managed";
19
+ const Table = require("cli-table");
19
20
  const gcfV1PollerOptions = {
20
21
  apiOrigin: (0, api_1.functionsOrigin)(),
21
22
  apiVersion: "v1",
@@ -28,25 +29,12 @@ const gcfV2PollerOptions = {
28
29
  masterTimeout: 25 * 60 * 1000,
29
30
  maxBackoff: 10000,
30
31
  };
31
- function isFirebaseManaged(secret) {
32
- return Object.keys(secret.labels || []).includes(FIREBASE_MANAGED);
33
- }
34
- exports.isFirebaseManaged = isFirebaseManaged;
35
- function labels() {
36
- return { [FIREBASE_MANAGED]: "true" };
37
- }
38
- exports.labels = labels;
39
32
  function toUpperSnakeCase(key) {
40
33
  return key
41
34
  .replace(/[.-]/g, "_")
42
35
  .replace(/([a-z])([A-Z])/g, "$1_$2")
43
36
  .toUpperCase();
44
37
  }
45
- function ensureApi(options) {
46
- const projectId = (0, projectUtils_1.needProjectId)(options);
47
- return ensureApiEnabled.ensure(projectId, (0, api_1.secretManagerOrigin)(), "secretmanager", true);
48
- }
49
- exports.ensureApi = ensureApi;
50
38
  async function ensureValidKey(key, options) {
51
39
  const transformedKey = toUpperSnakeCase(key);
52
40
  if (transformedKey !== key) {
@@ -76,18 +64,34 @@ exports.ensureValidKey = ensureValidKey;
76
64
  async function ensureSecret(projectId, name, options) {
77
65
  try {
78
66
  const secret = await (0, secretManager_1.getSecret)(projectId, name);
79
- if (!isFirebaseManaged(secret)) {
67
+ if ((0, secretManager_1.isAppHostingManaged)(secret)) {
68
+ (0, utils_1.logWarning)("Your secret is managed by Firebase App Hosting. Continuing will disable automatic deletion of old versions.");
69
+ const stopTracking = await (0, prompt_1.promptOnce)({
70
+ name: "doNotTrack",
71
+ type: "confirm",
72
+ default: false,
73
+ message: "Do you wish to continue?",
74
+ }, options);
75
+ if (stopTracking) {
76
+ delete secret.labels[secretManager_2.FIREBASE_MANAGED];
77
+ await (0, secretManager_1.patchSecret)(secret.projectId, secret.name, secret.labels);
78
+ }
79
+ else {
80
+ throw new Error("A secret cannot be managed by both Firebase App Hosting and Cloud Functions for Firebase");
81
+ }
82
+ }
83
+ else if (!(0, secretManager_2.isFunctionsManaged)(secret)) {
80
84
  if (!options.force) {
81
- (0, utils_1.logWarning)("Your secret is not managed by Firebase. " +
85
+ (0, utils_1.logWarning)("Your secret is not managed by Cloud Functions for Firebase. " +
82
86
  "Firebase managed secrets are automatically pruned to reduce your monthly cost for using Secret Manager. ");
83
87
  const confirm = await (0, prompt_1.promptOnce)({
84
88
  name: "updateLabels",
85
89
  type: "confirm",
86
90
  default: true,
87
- message: `Would you like to have your secret ${secret.name} managed by Firebase?`,
91
+ message: `Would you like to have your secret ${secret.name} managed by Cloud Functions for Firebase?`,
88
92
  }, options);
89
93
  if (confirm) {
90
- return (0, secretManager_1.patchSecret)(projectId, secret.name, Object.assign(Object.assign({}, secret.labels), labels()));
94
+ return (0, secretManager_1.patchSecret)(projectId, secret.name, Object.assign(Object.assign({}, secret.labels), (0, secretManager_3.labels)()));
91
95
  }
92
96
  }
93
97
  }
@@ -98,7 +102,7 @@ async function ensureSecret(projectId, name, options) {
98
102
  throw err;
99
103
  }
100
104
  }
101
- return await (0, secretManager_1.createSecret)(projectId, name, labels());
105
+ return await (0, secretManager_1.createSecret)(projectId, name, (0, secretManager_3.labels)());
102
106
  }
103
107
  exports.ensureSecret = ensureSecret;
104
108
  function of(endpoints) {
@@ -139,7 +143,7 @@ async function pruneSecrets(projectInfo, endpoints) {
139
143
  const { projectId, projectNumber } = projectInfo;
140
144
  const pruneKey = (name, version) => `${name}@${version}`;
141
145
  const prunedSecrets = new Set();
142
- const haveSecrets = await (0, secretManager_1.listSecrets)(projectId, `labels.${FIREBASE_MANAGED}=true`);
146
+ const haveSecrets = await (0, secretManager_1.listSecrets)(projectId, `labels.${secretManager_2.FIREBASE_MANAGED}=true`);
143
147
  for (const secret of haveSecrets) {
144
148
  const versions = await (0, secretManager_1.listSecretVersions)(projectId, secret.name, `NOT state: DESTROYED`);
145
149
  for (const version of versions) {
@@ -237,3 +241,17 @@ async function updateEndpointSecret(projectInfo, secretVersion, endpoint) {
237
241
  }
238
242
  }
239
243
  exports.updateEndpointSecret = updateEndpointSecret;
244
+ async function describeSecret(key, options) {
245
+ const projectId = (0, projectUtils_1.needProjectId)(options);
246
+ const versions = await (0, secretManager_1.listSecretVersions)(projectId, key);
247
+ const table = new Table({
248
+ head: ["Version", "State"],
249
+ style: { head: ["yellow"] },
250
+ });
251
+ for (const version of versions) {
252
+ table.push([version.versionId, version.state]);
253
+ }
254
+ logger_1.logger.info(table.toString());
255
+ return { secrets: versions };
256
+ }
257
+ exports.describeSecret = describeSecret;
@@ -31,9 +31,22 @@ async function getBackend(projectId, location, backendId) {
31
31
  }
32
32
  exports.getBackend = getBackend;
33
33
  async function listBackends(projectId, location) {
34
+ var _a;
34
35
  const name = `projects/${projectId}/locations/${location}/backends`;
35
- const res = await exports.client.get(name);
36
- return res.body;
36
+ let pageToken;
37
+ const res = {
38
+ backends: [],
39
+ unreachable: [],
40
+ };
41
+ do {
42
+ const queryParams = pageToken ? { pageToken } : {};
43
+ const int = await exports.client.get(name, { queryParams });
44
+ res.backends.push(...(int.body.backends || []));
45
+ (_a = res.unreachable) === null || _a === void 0 ? void 0 : _a.push(...(int.body.unreachable || []));
46
+ pageToken = int.body.nextPageToken;
47
+ } while (pageToken);
48
+ res.unreachable = [...new Set(res.unreachable)];
49
+ return res;
37
50
  }
38
51
  exports.listBackends = listBackends;
39
52
  async function deleteBackend(projectId, location, backendId) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serviceAgentEmail = exports.deleteRepository = exports.getRepository = exports.createRepository = exports.fetchLinkableRepositories = exports.deleteConnection = exports.listConnections = exports.getConnection = exports.createConnection = void 0;
3
+ exports.getDefaultServiceAgent = exports.getDefaultServiceAccount = exports.deleteRepository = exports.getRepository = exports.createRepository = exports.fetchLinkableRepositories = exports.deleteConnection = exports.listConnections = exports.getConnection = exports.createConnection = void 0;
4
4
  const apiv2_1 = require("../apiv2");
5
5
  const api_1 = require("../api");
6
6
  const PAGE_SIZE_MAX = 100;
@@ -74,7 +74,11 @@ async function deleteRepository(projectId, location, connectionId, repositoryId)
74
74
  return res.body;
75
75
  }
76
76
  exports.deleteRepository = deleteRepository;
77
- function serviceAgentEmail(projectNumber) {
77
+ function getDefaultServiceAccount(projectNumber) {
78
+ return `${projectNumber}@cloudbuild.gserviceaccount.com`;
79
+ }
80
+ exports.getDefaultServiceAccount = getDefaultServiceAccount;
81
+ function getDefaultServiceAgent(projectNumber) {
78
82
  return `service-${projectNumber}@gcp-sa-cloudbuild.iam.gserviceaccount.com`;
79
83
  }
80
- exports.serviceAgentEmail = serviceAgentEmail;
84
+ exports.getDefaultServiceAgent = getDefaultServiceAgent;
@@ -7,7 +7,7 @@ const logger_1 = require("../logger");
7
7
  const backend = require("../deploy/functions/backend");
8
8
  const utils = require("../utils");
9
9
  const proto = require("./proto");
10
- const runtimes = require("../deploy/functions/runtimes");
10
+ const supported = require("../deploy/functions/runtimes/supported");
11
11
  const projectConfig = require("../functions/projectConfig");
12
12
  const apiv2_1 = require("../apiv2");
13
13
  const api_1 = require("../api");
@@ -241,8 +241,8 @@ function endpointFromFunction(gcfFunction) {
241
241
  uri = gcfFunction.httpsTrigger.url;
242
242
  securityLevel = gcfFunction.httpsTrigger.securityLevel;
243
243
  }
244
- if (!runtimes.isValidRuntime(gcfFunction.runtime)) {
245
- logger_1.logger.debug("GCFv1 function has a deprecated runtime:", JSON.stringify(gcfFunction, null, 2));
244
+ if (!supported.isRuntime(gcfFunction.runtime)) {
245
+ logger_1.logger.debug("GCF 1st gen function has unsupported runtime:", JSON.stringify(gcfFunction, null, 2));
246
246
  }
247
247
  const endpoint = Object.assign(Object.assign({ platform: "gcfv1", id,
248
248
  project,
@@ -273,9 +273,9 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
273
273
  if (endpoint.platform !== "gcfv1") {
274
274
  throw new error_1.FirebaseError("Trying to create a v1 CloudFunction with v2 API. This should never happen");
275
275
  }
276
- if (!runtimes.isValidRuntime(endpoint.runtime)) {
276
+ if (!supported.isRuntime(endpoint.runtime)) {
277
277
  throw new error_1.FirebaseError("Failed internal assertion. Trying to deploy a new function with a deprecated runtime." +
278
- " This should never happen");
278
+ " This should never happen", { exit: 1 });
279
279
  }
280
280
  const gcfFunction = {
281
281
  name: backend.functionName(endpoint),
@@ -7,7 +7,7 @@ const api_1 = require("../api");
7
7
  const logger_1 = require("../logger");
8
8
  const v2_1 = require("../functions/events/v2");
9
9
  const backend = require("../deploy/functions/backend");
10
- const runtimes = require("../deploy/functions/runtimes");
10
+ const supported = require("../deploy/functions/runtimes/supported");
11
11
  const proto = require("./proto");
12
12
  const utils = require("../utils");
13
13
  const projectConfig = require("../functions/projectConfig");
@@ -175,7 +175,7 @@ function functionFromEndpoint(endpoint) {
175
175
  if (endpoint.platform !== "gcfv2") {
176
176
  throw new error_1.FirebaseError("Trying to create a v2 CloudFunction with v1 API. This should never happen");
177
177
  }
178
- if (!runtimes.isValidRuntime(endpoint.runtime)) {
178
+ if (!supported.isRuntime(endpoint.runtime)) {
179
179
  throw new error_1.FirebaseError("Failed internal assertion. Trying to deploy a new function with a deprecated runtime." +
180
180
  " This should never happen");
181
181
  }
@@ -337,7 +337,7 @@ function endpointFromFunction(gcfFunction) {
337
337
  else {
338
338
  trigger = { httpsTrigger: {} };
339
339
  }
340
- if (!runtimes.isValidRuntime(gcfFunction.buildConfig.runtime)) {
340
+ if (!supported.isRuntime(gcfFunction.buildConfig.runtime)) {
341
341
  logger_1.logger.debug("GCFv2 function has a deprecated runtime:", JSON.stringify(gcfFunction, null, 2));
342
342
  }
343
343
  const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
@@ -8,7 +8,7 @@ const api_1 = require("../api");
8
8
  const apiv2_1 = require("../apiv2");
9
9
  const backend = require("../deploy/functions/backend");
10
10
  const proto = require("./proto");
11
- const checkIam_1 = require("../deploy/functions/checkIam");
11
+ const gce = require("../gcp/computeEngine");
12
12
  const functional_1 = require("../functional");
13
13
  const VERSION = "v1";
14
14
  const DEFAULT_TIME_ZONE_V1 = "America/Los_Angeles";
@@ -130,7 +130,7 @@ function jobFromEndpoint(endpoint, location, projectNumber) {
130
130
  uri: endpoint.uri,
131
131
  httpMethod: "POST",
132
132
  oidcToken: {
133
- serviceAccountEmail: (_a = endpoint.serviceAccount) !== null && _a !== void 0 ? _a : (0, checkIam_1.getDefaultComputeServiceAgent)(projectNumber),
133
+ serviceAccountEmail: (_a = endpoint.serviceAccount) !== null && _a !== void 0 ? _a : gce.getDefaultServiceAccount(projectNumber),
134
134
  },
135
135
  };
136
136
  }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDefaultServiceAccount = void 0;
4
+ function getDefaultServiceAccount(projectNumber) {
5
+ return `${projectNumber}-compute@developer.gserviceaccount.com`;
6
+ }
7
+ exports.getDefaultServiceAccount = getDefaultServiceAccount;