No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

prompts.js 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.promptForMinInstances = exports.promptForFunctionDeletion = exports.promptForFailurePolicies = void 0;
  4. const clc = require("colorette");
  5. const functionsDeployHelper_1 = require("./functionsDeployHelper");
  6. const error_1 = require("../../error");
  7. const prompt_1 = require("../../prompt");
  8. const logger_1 = require("../../logger");
  9. const backend = require("./backend");
  10. const pricing = require("./pricing");
  11. const utils = require("../../utils");
  12. async function promptForFailurePolicies(options, want, have) {
  13. const retryEndpoints = backend.allEndpoints(want).filter((e) => {
  14. return backend.isEventTriggered(e) && e.eventTrigger.retry;
  15. });
  16. if (retryEndpoints.length === 0) {
  17. return;
  18. }
  19. const newRetryEndpoints = retryEndpoints.filter((endpoint) => {
  20. var _a;
  21. const existing = (_a = have.endpoints[endpoint.region]) === null || _a === void 0 ? void 0 : _a[endpoint.id];
  22. return !(existing && backend.isEventTriggered(existing) && existing.eventTrigger.retry);
  23. });
  24. if (newRetryEndpoints.length === 0) {
  25. return;
  26. }
  27. const warnMessage = "The following functions will newly be retried in case of failure: " +
  28. clc.bold(newRetryEndpoints.sort(backend.compareFunctions).map(functionsDeployHelper_1.getFunctionLabel).join(", ")) +
  29. ". " +
  30. "Retried executions are billed as any other execution, and functions are retried repeatedly until they either successfully execute or the maximum retry period has elapsed, which can be up to 7 days. " +
  31. "For safety, you might want to ensure that your functions are idempotent; see https://firebase.google.com/docs/functions/retries to learn more.";
  32. utils.logLabeledWarning("functions", warnMessage);
  33. if (options.force) {
  34. return;
  35. }
  36. if (options.nonInteractive) {
  37. throw new error_1.FirebaseError("Pass the --force option to deploy functions with a failure policy", {
  38. exit: 1,
  39. });
  40. }
  41. const proceed = await (0, prompt_1.promptOnce)({
  42. type: "confirm",
  43. name: "confirm",
  44. default: false,
  45. message: "Would you like to proceed with deployment?",
  46. });
  47. if (!proceed) {
  48. throw new error_1.FirebaseError("Deployment canceled.", { exit: 1 });
  49. }
  50. }
  51. exports.promptForFailurePolicies = promptForFailurePolicies;
  52. async function promptForFunctionDeletion(functionsToDelete, force, nonInteractive) {
  53. let shouldDeleteFns = true;
  54. if (functionsToDelete.length === 0 || force) {
  55. return true;
  56. }
  57. const deleteList = functionsToDelete
  58. .sort(backend.compareFunctions)
  59. .map((fn) => "\t" + (0, functionsDeployHelper_1.getFunctionLabel)(fn))
  60. .join("\n");
  61. if (nonInteractive) {
  62. const deleteCommands = functionsToDelete
  63. .map((func) => {
  64. return "\tfirebase functions:delete " + func.id + " --region " + func.region;
  65. })
  66. .join("\n");
  67. throw new error_1.FirebaseError("The following functions are found in your project but do not exist in your local source code:\n" +
  68. deleteList +
  69. "\n\nAborting because deletion cannot proceed in non-interactive mode. To fix, manually delete the functions by running:\n" +
  70. clc.bold(deleteCommands));
  71. }
  72. else {
  73. logger_1.logger.info("\nThe following functions are found in your project but do not exist in your local source code:\n" +
  74. deleteList +
  75. "\n\nIf you are renaming a function or changing its region, it is recommended that you create the new " +
  76. "function first before deleting the old one to prevent event loss. For more info, visit " +
  77. clc.underline("https://firebase.google.com/docs/functions/manage-functions#modify" + "\n"));
  78. shouldDeleteFns = await (0, prompt_1.promptOnce)({
  79. type: "confirm",
  80. name: "confirm",
  81. default: false,
  82. message: "Would you like to proceed with deletion? Selecting no will continue the rest of the deployments.",
  83. });
  84. }
  85. return shouldDeleteFns;
  86. }
  87. exports.promptForFunctionDeletion = promptForFunctionDeletion;
  88. async function promptForMinInstances(options, want, have) {
  89. if (options.force) {
  90. return;
  91. }
  92. const increasesCost = backend.someEndpoint(want, (wantE) => {
  93. var _a;
  94. if (!pricing.canCalculateMinInstanceCost(wantE)) {
  95. return true;
  96. }
  97. const wantCost = pricing.monthlyMinInstanceCost([wantE]);
  98. const haveE = (_a = have.endpoints[wantE.region]) === null || _a === void 0 ? void 0 : _a[wantE.id];
  99. let haveCost;
  100. if (!haveE) {
  101. haveCost = 0;
  102. }
  103. else if (!pricing.canCalculateMinInstanceCost(wantE)) {
  104. return true;
  105. }
  106. else {
  107. haveCost = pricing.monthlyMinInstanceCost([haveE]);
  108. }
  109. return wantCost > haveCost;
  110. });
  111. if (!increasesCost) {
  112. return;
  113. }
  114. if (options.nonInteractive) {
  115. throw new error_1.FirebaseError("Pass the --force option to deploy functions that increase the minimum bill", {
  116. exit: 1,
  117. });
  118. }
  119. const functionLines = backend
  120. .allEndpoints(want)
  121. .filter((fn) => fn.minInstances)
  122. .sort(backend.compareFunctions)
  123. .map((fn) => {
  124. return (`\t${(0, functionsDeployHelper_1.getFunctionLabel)(fn)}: ${fn.minInstances} instances, ` +
  125. backend.memoryOptionDisplayName(fn.availableMemoryMb || backend.DEFAULT_MEMORY) +
  126. " of memory each");
  127. })
  128. .join("\n");
  129. let costLine;
  130. if (backend.someEndpoint(want, (fn) => !pricing.canCalculateMinInstanceCost(fn))) {
  131. costLine =
  132. "Cannot calculate the minimum monthly bill for this configuration. Consider running " +
  133. clc.bold("npm install -g firebase-tools");
  134. }
  135. else {
  136. const cost = pricing.monthlyMinInstanceCost(backend.allEndpoints(want)).toFixed(2);
  137. costLine = `With these options, your minimum bill will be $${cost} in a 30-day month`;
  138. }
  139. const warnMessage = "The following functions have reserved minimum instances. This will " +
  140. "reduce the frequency of cold starts but increases the minimum cost. " +
  141. "You will be charged for the memory allocation and a fraction of the " +
  142. "CPU allocation of instances while they are idle.\n\n" +
  143. functionLines +
  144. "\n\n" +
  145. costLine;
  146. utils.logLabeledWarning("functions", warnMessage);
  147. const proceed = await (0, prompt_1.promptOnce)({
  148. type: "confirm",
  149. name: "confirm",
  150. default: false,
  151. message: "Would you like to proceed with deployment?",
  152. });
  153. if (!proceed) {
  154. throw new error_1.FirebaseError("Deployment canceled.", { exit: 1 });
  155. }
  156. }
  157. exports.promptForMinInstances = promptForMinInstances;