@datadog/datadog-ci 2.18.0 → 2.19.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.
Files changed (302) hide show
  1. package/dist/cli.d.ts +3 -1
  2. package/dist/cli.js +9 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/cloud-run/cli.d.ts +1 -0
  5. package/dist/commands/cloud-run/cli.js +5 -0
  6. package/dist/commands/cloud-run/cli.js.map +1 -0
  7. package/dist/commands/cloud-run/constants.d.ts +1 -0
  8. package/dist/commands/cloud-run/constants.js +22 -0
  9. package/dist/commands/cloud-run/constants.js.map +1 -0
  10. package/dist/commands/cloud-run/flare.d.ts +91 -0
  11. package/dist/commands/cloud-run/flare.js +634 -0
  12. package/dist/commands/cloud-run/flare.js.map +1 -0
  13. package/dist/commands/cloud-run/interfaces.d.ts +27 -0
  14. package/dist/commands/cloud-run/interfaces.js +3 -0
  15. package/dist/commands/cloud-run/interfaces.js.map +1 -0
  16. package/dist/commands/cloud-run/renderer.d.ts +4 -0
  17. package/dist/commands/cloud-run/renderer.js +42 -0
  18. package/dist/commands/cloud-run/renderer.js.map +1 -0
  19. package/dist/commands/dsyms/renderer.js +6 -6
  20. package/dist/commands/dsyms/renderer.js.map +1 -1
  21. package/dist/commands/dsyms/upload.d.ts +5 -5
  22. package/dist/commands/dsyms/upload.js +66 -42
  23. package/dist/commands/dsyms/upload.js.map +1 -1
  24. package/dist/commands/dsyms/utils.d.ts +1 -1
  25. package/dist/commands/dsyms/utils.js +3 -3
  26. package/dist/commands/dsyms/utils.js.map +1 -1
  27. package/dist/commands/flutter-symbols/helpers.js +8 -4
  28. package/dist/commands/flutter-symbols/helpers.js.map +1 -1
  29. package/dist/commands/flutter-symbols/renderer.js +2 -2
  30. package/dist/commands/flutter-symbols/renderer.js.map +1 -1
  31. package/dist/commands/flutter-symbols/upload.d.ts +13 -13
  32. package/dist/commands/flutter-symbols/upload.js +66 -66
  33. package/dist/commands/flutter-symbols/upload.js.map +1 -1
  34. package/dist/commands/gate/api.js +4 -2
  35. package/dist/commands/gate/api.js.map +1 -1
  36. package/dist/commands/gate/evaluate.d.ts +18 -6
  37. package/dist/commands/gate/evaluate.js +116 -40
  38. package/dist/commands/gate/evaluate.js.map +1 -1
  39. package/dist/commands/gate/interfaces.d.ts +5 -0
  40. package/dist/commands/gate/renderer.js +16 -14
  41. package/dist/commands/gate/renderer.js.map +1 -1
  42. package/dist/commands/gate/utils.d.ts +1 -0
  43. package/dist/commands/gate/utils.js +8 -4
  44. package/dist/commands/gate/utils.js.map +1 -1
  45. package/dist/commands/git-metadata/git.d.ts +1 -1
  46. package/dist/commands/git-metadata/git.js +7 -3
  47. package/dist/commands/git-metadata/git.js.map +1 -1
  48. package/dist/commands/git-metadata/gitdb.d.ts +1 -1
  49. package/dist/commands/git-metadata/gitdb.js +7 -7
  50. package/dist/commands/git-metadata/gitdb.js.map +1 -1
  51. package/dist/commands/git-metadata/index.js +5 -1
  52. package/dist/commands/git-metadata/index.js.map +1 -1
  53. package/dist/commands/git-metadata/library.d.ts +1 -1
  54. package/dist/commands/git-metadata/library.js +13 -13
  55. package/dist/commands/git-metadata/library.js.map +1 -1
  56. package/dist/commands/git-metadata/upload.d.ts +5 -5
  57. package/dist/commands/git-metadata/upload.js +30 -32
  58. package/dist/commands/git-metadata/upload.js.map +1 -1
  59. package/dist/commands/junit/api.js +4 -4
  60. package/dist/commands/junit/api.js.map +1 -1
  61. package/dist/commands/junit/id.js +1 -1
  62. package/dist/commands/junit/id.js.map +1 -1
  63. package/dist/commands/junit/renderer.d.ts +1 -1
  64. package/dist/commands/junit/renderer.js +3 -3
  65. package/dist/commands/junit/renderer.js.map +1 -1
  66. package/dist/commands/junit/upload.d.ts +12 -11
  67. package/dist/commands/junit/upload.js +74 -63
  68. package/dist/commands/junit/upload.js.map +1 -1
  69. package/dist/commands/junit/utils.d.ts +1 -2
  70. package/dist/commands/junit/utils.js +5 -10
  71. package/dist/commands/junit/utils.js.map +1 -1
  72. package/dist/commands/lambda/constants.d.ts +13 -11
  73. package/dist/commands/lambda/constants.js +41 -70
  74. package/dist/commands/lambda/constants.js.map +1 -1
  75. package/dist/commands/lambda/flare.d.ts +25 -74
  76. package/dist/commands/lambda/flare.js +182 -332
  77. package/dist/commands/lambda/flare.js.map +1 -1
  78. package/dist/commands/lambda/functions/commons.d.ts +8 -14
  79. package/dist/commands/lambda/functions/commons.js +57 -69
  80. package/dist/commands/lambda/functions/commons.js.map +1 -1
  81. package/dist/commands/lambda/functions/instrument.js +66 -65
  82. package/dist/commands/lambda/functions/instrument.js.map +1 -1
  83. package/dist/commands/lambda/functions/uninstrument.js +38 -37
  84. package/dist/commands/lambda/functions/uninstrument.js.map +1 -1
  85. package/dist/commands/lambda/functions/versionChecker.d.ts +2 -2
  86. package/dist/commands/lambda/instrument.d.ts +22 -20
  87. package/dist/commands/lambda/instrument.js +78 -69
  88. package/dist/commands/lambda/instrument.js.map +1 -1
  89. package/dist/commands/lambda/loggroup.js +8 -8
  90. package/dist/commands/lambda/loggroup.js.map +1 -1
  91. package/dist/commands/lambda/prompt.d.ts +1 -4
  92. package/dist/commands/lambda/prompt.js +34 -71
  93. package/dist/commands/lambda/prompt.js.map +1 -1
  94. package/dist/commands/lambda/renderers/__mocks__/instrument-uninstrument-renderer.d.ts +2 -0
  95. package/dist/commands/lambda/renderers/__mocks__/instrument-uninstrument-renderer.js +11 -0
  96. package/dist/commands/lambda/renderers/__mocks__/instrument-uninstrument-renderer.js.map +1 -0
  97. package/dist/commands/lambda/renderers/common-renderer.d.ts +0 -26
  98. package/dist/commands/lambda/renderers/common-renderer.js +4 -32
  99. package/dist/commands/lambda/renderers/common-renderer.js.map +1 -1
  100. package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.d.ts +2 -2
  101. package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.js +57 -49
  102. package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.js.map +1 -1
  103. package/dist/commands/lambda/tags.js +7 -7
  104. package/dist/commands/lambda/tags.js.map +1 -1
  105. package/dist/commands/lambda/uninstrument.d.ts +25 -7
  106. package/dist/commands/lambda/uninstrument.js +59 -49
  107. package/dist/commands/lambda/uninstrument.js.map +1 -1
  108. package/dist/commands/metric/metric.d.ts +4 -3
  109. package/dist/commands/metric/metric.js +10 -9
  110. package/dist/commands/metric/metric.js.map +1 -1
  111. package/dist/commands/react-native/codepush.d.ts +11 -10
  112. package/dist/commands/react-native/codepush.js +17 -19
  113. package/dist/commands/react-native/codepush.js.map +1 -1
  114. package/dist/commands/react-native/interfaces.d.ts +1 -1
  115. package/dist/commands/react-native/renderer.js +6 -6
  116. package/dist/commands/react-native/renderer.js.map +1 -1
  117. package/dist/commands/react-native/upload.d.ts +12 -12
  118. package/dist/commands/react-native/upload.js +67 -45
  119. package/dist/commands/react-native/upload.js.map +1 -1
  120. package/dist/commands/react-native/utils.js +2 -1
  121. package/dist/commands/react-native/utils.js.map +1 -1
  122. package/dist/commands/react-native/validation.js +1 -1
  123. package/dist/commands/react-native/validation.js.map +1 -1
  124. package/dist/commands/react-native/xcode.d.ts +6 -6
  125. package/dist/commands/react-native/xcode.js +25 -29
  126. package/dist/commands/react-native/xcode.js.map +1 -1
  127. package/dist/commands/sarif/api.js +6 -22
  128. package/dist/commands/sarif/api.js.map +1 -1
  129. package/dist/commands/sarif/renderer.d.ts +1 -1
  130. package/dist/commands/sarif/renderer.js +1 -1
  131. package/dist/commands/sarif/renderer.js.map +1 -1
  132. package/dist/commands/sarif/upload.d.ts +6 -6
  133. package/dist/commands/sarif/upload.js +46 -37
  134. package/dist/commands/sarif/upload.js.map +1 -1
  135. package/dist/commands/sbom/api.d.ts +7 -0
  136. package/dist/commands/sbom/api.js +49 -0
  137. package/dist/commands/sbom/api.js.map +1 -0
  138. package/dist/commands/sbom/cli.d.ts +1 -0
  139. package/dist/commands/sbom/cli.js +5 -0
  140. package/dist/commands/sbom/cli.js.map +1 -0
  141. package/dist/commands/sbom/constants.d.ts +2 -0
  142. package/dist/commands/sbom/constants.js +6 -0
  143. package/dist/commands/sbom/constants.js.map +1 -0
  144. package/dist/commands/sbom/json-schema/cyclonedx/bom-1.4.schema.json +1687 -0
  145. package/dist/commands/sbom/json-schema/jsf/jsf-0.82.schema.json +244 -0
  146. package/dist/commands/sbom/json-schema/spdx/spdx.schema.json +507 -0
  147. package/dist/commands/sbom/protobuf/bom-1.4.d.ts +11788 -0
  148. package/dist/commands/sbom/protobuf/bom-1.4.js +5161 -0
  149. package/dist/commands/sbom/protobuf/bom-1.4.js.map +1 -0
  150. package/dist/commands/sbom/protobuf/custom_message.d.ts +11 -0
  151. package/dist/commands/sbom/protobuf/custom_message.js +3 -0
  152. package/dist/commands/sbom/protobuf/custom_message.js.map +1 -0
  153. package/dist/commands/sbom/protobuf/google/protobuf/duration.d.ts +110 -0
  154. package/dist/commands/sbom/protobuf/google/protobuf/duration.js +126 -0
  155. package/dist/commands/sbom/protobuf/google/protobuf/duration.js.map +1 -0
  156. package/dist/commands/sbom/protobuf/google/protobuf/timestamp.d.ts +139 -0
  157. package/dist/commands/sbom/protobuf/google/protobuf/timestamp.js +126 -0
  158. package/dist/commands/sbom/protobuf/google/protobuf/timestamp.js.map +1 -0
  159. package/dist/commands/sbom/protobuf/sbom_intake.d.ts +53 -0
  160. package/dist/commands/sbom/protobuf/sbom_intake.js +383 -0
  161. package/dist/commands/sbom/protobuf/sbom_intake.js.map +1 -0
  162. package/dist/commands/sbom/types.d.ts +4 -0
  163. package/dist/commands/sbom/types.js +3 -0
  164. package/dist/commands/sbom/types.js.map +1 -0
  165. package/dist/commands/sbom/upload.d.ts +16 -0
  166. package/dist/commands/sbom/upload.js +134 -0
  167. package/dist/commands/sbom/upload.js.map +1 -0
  168. package/dist/commands/sbom/validation.d.ts +12 -0
  169. package/dist/commands/sbom/validation.js +51 -0
  170. package/dist/commands/sbom/validation.js.map +1 -0
  171. package/dist/commands/sourcemaps/renderer.js +6 -6
  172. package/dist/commands/sourcemaps/renderer.js.map +1 -1
  173. package/dist/commands/sourcemaps/upload.d.ts +10 -10
  174. package/dist/commands/sourcemaps/upload.js +61 -38
  175. package/dist/commands/sourcemaps/upload.js.map +1 -1
  176. package/dist/commands/sourcemaps/validation.js +4 -4
  177. package/dist/commands/sourcemaps/validation.js.map +1 -1
  178. package/dist/commands/stepfunctions/awsCommands.js +10 -10
  179. package/dist/commands/stepfunctions/awsCommands.js.map +1 -1
  180. package/dist/commands/stepfunctions/helpers.d.ts +4 -4
  181. package/dist/commands/stepfunctions/helpers.js +4 -4
  182. package/dist/commands/stepfunctions/helpers.js.map +1 -1
  183. package/dist/commands/stepfunctions/instrument.d.ts +5 -4
  184. package/dist/commands/stepfunctions/instrument.js +30 -31
  185. package/dist/commands/stepfunctions/instrument.js.map +1 -1
  186. package/dist/commands/stepfunctions/uninstrument.d.ts +6 -1
  187. package/dist/commands/stepfunctions/uninstrument.js +23 -23
  188. package/dist/commands/stepfunctions/uninstrument.js.map +1 -1
  189. package/dist/commands/synthetics/api.d.ts +1 -1
  190. package/dist/commands/synthetics/api.js +11 -11
  191. package/dist/commands/synthetics/api.js.map +1 -1
  192. package/dist/commands/synthetics/errors.d.ts +3 -3
  193. package/dist/commands/synthetics/index.js +5 -1
  194. package/dist/commands/synthetics/index.js.map +1 -1
  195. package/dist/commands/synthetics/interfaces.d.ts +8 -7
  196. package/dist/commands/synthetics/interfaces.js +2 -2
  197. package/dist/commands/synthetics/interfaces.js.map +1 -1
  198. package/dist/commands/synthetics/mobile.d.ts +1 -1
  199. package/dist/commands/synthetics/mobile.js +26 -20
  200. package/dist/commands/synthetics/mobile.js.map +1 -1
  201. package/dist/commands/synthetics/reporters/default.d.ts +2 -2
  202. package/dist/commands/synthetics/reporters/default.js +17 -19
  203. package/dist/commands/synthetics/reporters/default.js.map +1 -1
  204. package/dist/commands/synthetics/reporters/junit.d.ts +2 -2
  205. package/dist/commands/synthetics/reporters/junit.js +11 -11
  206. package/dist/commands/synthetics/reporters/junit.js.map +1 -1
  207. package/dist/commands/synthetics/run-tests-command.d.ts +21 -19
  208. package/dist/commands/synthetics/run-tests-command.js +108 -42
  209. package/dist/commands/synthetics/run-tests-command.js.map +1 -1
  210. package/dist/commands/synthetics/run-tests-lib.d.ts +1 -1
  211. package/dist/commands/synthetics/run-tests-lib.js +16 -16
  212. package/dist/commands/synthetics/run-tests-lib.js.map +1 -1
  213. package/dist/commands/synthetics/tunnel/crypto.js +3 -3
  214. package/dist/commands/synthetics/tunnel/crypto.js.map +1 -1
  215. package/dist/commands/synthetics/tunnel/tunnel.js +11 -11
  216. package/dist/commands/synthetics/tunnel/tunnel.js.map +1 -1
  217. package/dist/commands/synthetics/tunnel/websocket.d.ts +1 -0
  218. package/dist/commands/synthetics/tunnel/websocket.js +7 -3
  219. package/dist/commands/synthetics/tunnel/websocket.js.map +1 -1
  220. package/dist/commands/synthetics/upload-application-command.d.ts +10 -8
  221. package/dist/commands/synthetics/upload-application-command.js +36 -13
  222. package/dist/commands/synthetics/upload-application-command.js.map +1 -1
  223. package/dist/commands/synthetics/utils.d.ts +12 -12
  224. package/dist/commands/synthetics/utils.js +52 -47
  225. package/dist/commands/synthetics/utils.js.map +1 -1
  226. package/dist/commands/tag/tag.d.ts +4 -3
  227. package/dist/commands/tag/tag.js +10 -9
  228. package/dist/commands/tag/tag.js.map +1 -1
  229. package/dist/commands/trace/api.js +4 -4
  230. package/dist/commands/trace/api.js.map +1 -1
  231. package/dist/commands/trace/interfaces.d.ts +1 -1
  232. package/dist/commands/trace/trace.d.ts +5 -4
  233. package/dist/commands/trace/trace.js +11 -10
  234. package/dist/commands/trace/trace.js.map +1 -1
  235. package/dist/commands/version/cli.js +6 -5
  236. package/dist/commands/version/cli.js.map +1 -1
  237. package/dist/constants.d.ts +17 -0
  238. package/dist/constants.js +65 -1
  239. package/dist/constants.js.map +1 -1
  240. package/dist/helpers/api.d.ts +5 -0
  241. package/dist/helpers/api.js +16 -0
  242. package/dist/helpers/api.js.map +1 -0
  243. package/dist/helpers/base-intake-url.d.ts +1 -1
  244. package/dist/helpers/ci.d.ts +13 -13
  245. package/dist/helpers/ci.js +17 -17
  246. package/dist/helpers/ci.js.map +1 -1
  247. package/dist/helpers/config.d.ts +5 -0
  248. package/dist/helpers/config.js +3 -0
  249. package/dist/helpers/config.js.map +1 -0
  250. package/dist/helpers/flare.d.ts +41 -0
  251. package/dist/helpers/flare.js +191 -0
  252. package/dist/helpers/flare.js.map +1 -0
  253. package/dist/helpers/fs.d.ts +31 -0
  254. package/dist/helpers/fs.js +117 -0
  255. package/dist/helpers/fs.js.map +1 -0
  256. package/dist/helpers/git/format-git-sourcemaps-data.js +7 -3
  257. package/dist/helpers/git/format-git-sourcemaps-data.js.map +1 -1
  258. package/dist/helpers/git/format-git-span-data.js +6 -6
  259. package/dist/helpers/git/format-git-span-data.js.map +1 -1
  260. package/dist/helpers/git/get-git-data.js +3 -3
  261. package/dist/helpers/git/get-git-data.js.map +1 -1
  262. package/dist/helpers/interfaces.d.ts +9 -3
  263. package/dist/helpers/logger.js +1 -1
  264. package/dist/helpers/logger.js.map +1 -1
  265. package/dist/helpers/plist.d.ts +1 -1
  266. package/dist/helpers/plist.js +1 -1
  267. package/dist/helpers/plist.js.map +1 -1
  268. package/dist/helpers/prompt.d.ts +7 -0
  269. package/dist/helpers/prompt.js +57 -0
  270. package/dist/helpers/prompt.js.map +1 -0
  271. package/dist/helpers/renderer.d.ts +60 -0
  272. package/dist/helpers/renderer.js +98 -0
  273. package/dist/helpers/renderer.js.map +1 -0
  274. package/dist/helpers/retry.d.ts +1 -1
  275. package/dist/helpers/retry.js +3 -3
  276. package/dist/helpers/retry.js.map +1 -1
  277. package/dist/helpers/tags.d.ts +8 -0
  278. package/dist/helpers/tags.js +27 -1
  279. package/dist/helpers/tags.js.map +1 -1
  280. package/dist/helpers/upload.js +3 -3
  281. package/dist/helpers/upload.js.map +1 -1
  282. package/dist/helpers/user-provided-git.js +6 -6
  283. package/dist/helpers/user-provided-git.js.map +1 -1
  284. package/dist/helpers/utils.d.ts +12 -5
  285. package/dist/helpers/utils.js +57 -25
  286. package/dist/helpers/utils.js.map +1 -1
  287. package/dist/helpers/validation.d.ts +3 -1
  288. package/dist/helpers/validation.js +27 -1
  289. package/dist/helpers/validation.js.map +1 -1
  290. package/dist/helpers/version.d.ts +4 -0
  291. package/dist/helpers/version.js +9 -0
  292. package/dist/helpers/version.js.map +1 -0
  293. package/dist/index.d.ts +4 -4
  294. package/dist/index.js +11 -8
  295. package/dist/index.js.map +1 -1
  296. package/package.json +28 -13
  297. package/dist/commands/lambda/renderers/flare-renderer.d.ts +0 -9
  298. package/dist/commands/lambda/renderers/flare-renderer.js +0 -22
  299. package/dist/commands/lambda/renderers/flare-renderer.js.map +0 -1
  300. package/dist/helpers/file.d.ts +0 -1
  301. package/dist/helpers/file.js +0 -9
  302. package/dist/helpers/file.js.map +0 -1
@@ -0,0 +1,634 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.generateInsightsFile = exports.getRecentRevisions = exports.saveLogsFile = exports.getLogs = exports.summarizeConfig = exports.maskConfig = exports.getCloudRunServiceConfig = exports.checkAuthentication = exports.CloudRunFlareCommand = exports.MAX_LOGS = void 0;
39
+ const fs_1 = __importDefault(require("fs"));
40
+ const path_1 = __importDefault(require("path"));
41
+ const process_1 = __importDefault(require("process"));
42
+ const util_1 = __importDefault(require("util"));
43
+ const logging_1 = require("@google-cloud/logging");
44
+ const run_1 = require("@google-cloud/run");
45
+ const chalk_1 = __importDefault(require("chalk"));
46
+ const clipanion_1 = require("clipanion");
47
+ const google_auth_library_1 = require("google-auth-library");
48
+ const constants_1 = require("../../constants");
49
+ const flare_1 = require("../../helpers/flare");
50
+ const fs_2 = require("../../helpers/fs");
51
+ const prompt_1 = require("../../helpers/prompt");
52
+ const helpersRenderer = __importStar(require("../../helpers/renderer"));
53
+ const renderer_1 = require("../../helpers/renderer");
54
+ const utils_1 = require("../../helpers/utils");
55
+ const version_1 = require("../../helpers/version");
56
+ const flare_2 = require("../lambda/flare");
57
+ const constants_2 = require("./constants");
58
+ const renderer_2 = require("./renderer");
59
+ const SERVICE_CONFIG_FILE_NAME = 'service_config.json';
60
+ const FLARE_ZIP_FILE_NAME = 'cloud-run-flare-output.zip';
61
+ const ALL_LOGS_FILE_NAME = 'all_logs.csv';
62
+ const WARNING_LOGS_FILE_NAME = 'warning_logs.csv';
63
+ const ERRORS_LOGS_FILE_NAME = 'error_logs.csv';
64
+ const DEBUG_LOGS_FILE_NAME = 'debug_logs.csv';
65
+ // What's the maximum number of revisions we want to include? Too many revisions will flood the INSIGHTS.md file
66
+ const MAX_REVISIONS = 10;
67
+ // Must be in range 0 - 1000. If more logs are needed, pagination must be implemented
68
+ exports.MAX_LOGS = 1000;
69
+ // How old the logs can be in minutes. Skip older logs
70
+ const MAX_LOG_AGE_MINUTES = 1440;
71
+ const FILTER_ORDER = 'timestamp asc';
72
+ // Types of log files to create
73
+ const LOG_CONFIGS = [
74
+ { type: 'total', fileName: ALL_LOGS_FILE_NAME },
75
+ { type: 'warning', severityFilter: ' AND severity>="WARNING"', fileName: WARNING_LOGS_FILE_NAME },
76
+ { type: 'error', severityFilter: ' AND severity>="ERROR"', fileName: ERRORS_LOGS_FILE_NAME },
77
+ { type: 'debug', severityFilter: ' AND severity="DEBUG"', fileName: DEBUG_LOGS_FILE_NAME },
78
+ ];
79
+ class CloudRunFlareCommand extends clipanion_1.Command {
80
+ constructor() {
81
+ super(...arguments);
82
+ this.isDryRun = clipanion_1.Option.Boolean('-d,--dry,--dry-run', false);
83
+ this.withLogs = clipanion_1.Option.Boolean('--with-logs', false);
84
+ this.service = clipanion_1.Option.String('-s,--service');
85
+ this.project = clipanion_1.Option.String('-p,--project');
86
+ this.region = clipanion_1.Option.String('-r,--region,-l,--location');
87
+ this.caseId = clipanion_1.Option.String('-c,--case-id');
88
+ this.email = clipanion_1.Option.String('-e,--email');
89
+ this.start = clipanion_1.Option.String('--start');
90
+ this.end = clipanion_1.Option.String('--end');
91
+ }
92
+ /**
93
+ * Entry point for the `cloud-run flare` command.
94
+ * Gathers Cloud Run service configuration and sends it to Datadog.
95
+ * @returns 0 if the command ran successfully, 1 otherwise.
96
+ */
97
+ execute() {
98
+ var _a;
99
+ return __awaiter(this, void 0, void 0, function* () {
100
+ this.context.stdout.write(helpersRenderer.renderFlareHeader('Cloud Run', this.isDryRun));
101
+ const errorMessages = [];
102
+ // Validate service
103
+ if (this.service === undefined) {
104
+ errorMessages.push(helpersRenderer.renderError('No service specified. [-s,--service]'));
105
+ }
106
+ // Validate project
107
+ if (this.project === undefined) {
108
+ errorMessages.push(helpersRenderer.renderError('No project specified. [-p,--project]'));
109
+ }
110
+ // Validate region
111
+ if (this.region === undefined) {
112
+ errorMessages.push(helpersRenderer.renderError('No region specified. [-r,--region]'));
113
+ }
114
+ // Validate Datadog API key
115
+ this.apiKey = (_a = process_1.default.env[constants_1.CI_API_KEY_ENV_VAR]) !== null && _a !== void 0 ? _a : process_1.default.env[constants_1.API_KEY_ENV_VAR];
116
+ if (this.apiKey === undefined) {
117
+ errorMessages.push(helpersRenderer.renderError('No Datadog API key specified. Set an API key with the DATADOG_API_KEY environment variable.'));
118
+ }
119
+ // Validate case ID
120
+ if (this.caseId === undefined) {
121
+ errorMessages.push(helpersRenderer.renderError('No case ID specified. [-c,--case-id]'));
122
+ }
123
+ // Validate email
124
+ if (this.email === undefined) {
125
+ errorMessages.push(helpersRenderer.renderError('No email specified. [-e,--email]'));
126
+ }
127
+ // Validate start/end flags if both are specified
128
+ let startMillis;
129
+ let endMillis;
130
+ try {
131
+ ;
132
+ [startMillis, endMillis] = (0, flare_1.validateStartEndFlags)(this.start, this.end);
133
+ }
134
+ catch (err) {
135
+ if (err instanceof Error) {
136
+ errorMessages.push(helpersRenderer.renderError(err.message));
137
+ }
138
+ }
139
+ // If there are errors, print them and exit
140
+ if (errorMessages.length > 0) {
141
+ for (const message of errorMessages) {
142
+ this.context.stderr.write(message);
143
+ }
144
+ return 1;
145
+ }
146
+ // Verify GCP credentials
147
+ this.context.stdout.write(chalk_1.default.bold('\n🔑 Verifying GCP credentials...\n'));
148
+ const authenticated = yield (0, exports.checkAuthentication)();
149
+ if (!authenticated) {
150
+ this.context.stderr.write((0, renderer_2.renderAuthenticationInstructions)());
151
+ return 1;
152
+ }
153
+ this.context.stdout.write('GCP credentials verified!\n');
154
+ // Get and print service configuration
155
+ this.context.stdout.write(chalk_1.default.bold('\n🔍 Fetching service configuration...\n'));
156
+ const runClient = new run_1.ServicesClient();
157
+ let config;
158
+ try {
159
+ config = yield (0, exports.getCloudRunServiceConfig)(runClient, this.service, this.project, this.region);
160
+ }
161
+ catch (err) {
162
+ if (err instanceof Error) {
163
+ this.context.stderr.write(helpersRenderer.renderError(`Unable to fetch service configuration: ${err.message}`));
164
+ }
165
+ return 1;
166
+ }
167
+ config = (0, exports.maskConfig)(config);
168
+ const summarizedConfig = (0, exports.summarizeConfig)(config);
169
+ // 10 is the depth when inspecting the config file. Cloud-run configs have high depth, so
170
+ // we must raise the depth from the default depth of 2.
171
+ const summarizedConfigStr = util_1.default.inspect(summarizedConfig, false, 10, true);
172
+ this.context.stdout.write(`\n${summarizedConfigStr}\n`);
173
+ this.context.stdout.write(chalk_1.default.italic(`(This is a summary of the configuration. The full configuration will be saved in "${SERVICE_CONFIG_FILE_NAME}".)\n`));
174
+ // Get project files
175
+ this.context.stdout.write(chalk_1.default.bold('\n📁 Searching for project files in current directory...\n'));
176
+ const projectFilePaths = yield (0, flare_1.getProjectFiles)(constants_1.FLARE_PROJECT_FILES);
177
+ this.context.stdout.write((0, renderer_1.renderProjectFiles)(projectFilePaths));
178
+ // Additional files
179
+ this.context.stdout.write('\n');
180
+ const additionalFilePaths = new Set();
181
+ let confirmAdditionalFiles;
182
+ try {
183
+ confirmAdditionalFiles = yield (0, prompt_1.requestConfirmation)('Do you want to specify any additional files to flare?', false);
184
+ }
185
+ catch (err) {
186
+ if (err instanceof Error) {
187
+ this.context.stderr.write(helpersRenderer.renderError(err.message));
188
+ }
189
+ return 1;
190
+ }
191
+ while (confirmAdditionalFiles) {
192
+ this.context.stdout.write('\n');
193
+ let filePath;
194
+ try {
195
+ filePath = yield (0, prompt_1.requestFilePath)();
196
+ }
197
+ catch (err) {
198
+ if (err instanceof Error) {
199
+ this.context.stderr.write(helpersRenderer.renderError(err.message));
200
+ }
201
+ return 1;
202
+ }
203
+ if (filePath === '') {
204
+ this.context.stdout.write((0, renderer_1.renderAdditionalFiles)(additionalFilePaths));
205
+ break;
206
+ }
207
+ try {
208
+ filePath = (0, flare_1.validateFilePath)(filePath, projectFilePaths, additionalFilePaths);
209
+ additionalFilePaths.add(filePath);
210
+ const fileName = path_1.default.basename(filePath);
211
+ this.context.stdout.write(`• Added file '${fileName}'\n`);
212
+ }
213
+ catch (err) {
214
+ if (err instanceof Error) {
215
+ this.context.stderr.write(err.message);
216
+ }
217
+ }
218
+ }
219
+ // Get recent revisions, which will be used to generate insights file
220
+ this.context.stdout.write(chalk_1.default.bold('\n🌧 Fetching recent revisions...\n'));
221
+ let revisions = [];
222
+ try {
223
+ revisions = yield (0, exports.getRecentRevisions)(this.service, this.region, this.project);
224
+ this.context.stdout.write(`• Found ${revisions.length} revisions\n`);
225
+ }
226
+ catch (err) {
227
+ const errorDetails = err instanceof Error ? err.message : '';
228
+ this.context.stdout.write(helpersRenderer.renderSoftWarning(`Unable to fetch recent revisions. ${errorDetails}`));
229
+ }
230
+ // Get logs
231
+ const logFileMappings = new Map();
232
+ if (this.withLogs) {
233
+ this.context.stdout.write(chalk_1.default.bold('\n📖 Getting logs...\n'));
234
+ const logClient = new logging_1.Logging({ projectId: this.project });
235
+ for (const logConfig of LOG_CONFIGS) {
236
+ try {
237
+ const logs = yield (0, exports.getLogs)(logClient, this.service, this.region, startMillis, endMillis, logConfig.severityFilter);
238
+ if (logs.length === 0) {
239
+ this.context.stdout.write(`• No ${logConfig.type} logs were found\n`);
240
+ }
241
+ else {
242
+ this.context.stdout.write(`• Found ${logs.length} ${logConfig.type} logs\n`);
243
+ logFileMappings.set(logConfig.fileName, logs);
244
+ }
245
+ }
246
+ catch (err) {
247
+ const msg = err instanceof Error ? err.message : '';
248
+ this.context.stderr.write(`• Unable to get ${logConfig.type} logs: ${msg}\n`);
249
+ }
250
+ }
251
+ }
252
+ try {
253
+ // Create folders
254
+ const rootFolderPath = path_1.default.join(process_1.default.cwd(), constants_1.FLARE_OUTPUT_DIRECTORY);
255
+ const logsFolderPath = path_1.default.join(rootFolderPath, constants_1.LOGS_DIRECTORY);
256
+ const projectFilesFolderPath = path_1.default.join(rootFolderPath, constants_1.PROJECT_FILES_DIRECTORY);
257
+ const additionalFilesFolderPath = path_1.default.join(rootFolderPath, constants_1.ADDITIONAL_FILES_DIRECTORY);
258
+ this.context.stdout.write(chalk_1.default.bold(`\n💾 Saving files to ${rootFolderPath}...\n`));
259
+ if (fs_1.default.existsSync(rootFolderPath)) {
260
+ (0, fs_2.deleteFolder)(rootFolderPath);
261
+ }
262
+ const subFolders = [];
263
+ if (logFileMappings.size > 0) {
264
+ subFolders.push(logsFolderPath);
265
+ }
266
+ if (projectFilePaths.size > 0) {
267
+ subFolders.push(projectFilesFolderPath);
268
+ }
269
+ if (additionalFilePaths.size > 0) {
270
+ subFolders.push(additionalFilesFolderPath);
271
+ }
272
+ (0, fs_2.createDirectories)(rootFolderPath, subFolders);
273
+ // Write config file
274
+ const configFilePath = path_1.default.join(rootFolderPath, SERVICE_CONFIG_FILE_NAME);
275
+ (0, fs_2.writeFile)(configFilePath, JSON.stringify(config, undefined, 2));
276
+ this.context.stdout.write(`• Saved function config to ./${SERVICE_CONFIG_FILE_NAME}\n`);
277
+ // Write logs
278
+ for (const [fileName, logs] of logFileMappings) {
279
+ const logFilePath = path_1.default.join(logsFolderPath, fileName);
280
+ (0, exports.saveLogsFile)(logs, logFilePath);
281
+ this.context.stdout.write(`• Saved logs to ./${constants_1.LOGS_DIRECTORY}/${fileName}\n`);
282
+ }
283
+ // Write project files
284
+ for (const filePath of projectFilePaths) {
285
+ const fileName = path_1.default.basename(filePath);
286
+ const newFilePath = path_1.default.join(projectFilesFolderPath, fileName);
287
+ fs_1.default.copyFileSync(filePath, newFilePath);
288
+ this.context.stdout.write(`• Copied ${fileName} to ./${constants_1.PROJECT_FILES_DIRECTORY}/${fileName}\n`);
289
+ }
290
+ // Write additional files
291
+ const additionalFilesMap = (0, flare_2.getUniqueFileNames)(additionalFilePaths);
292
+ for (const [originalFilePath, newFileName] of additionalFilesMap) {
293
+ const originalFileName = path_1.default.basename(originalFilePath);
294
+ const newFilePath = path_1.default.join(additionalFilesFolderPath, newFileName);
295
+ fs_1.default.copyFileSync(originalFilePath, newFilePath);
296
+ this.context.stdout.write(`• Copied ${originalFileName} to ./${constants_1.ADDITIONAL_FILES_DIRECTORY}/${newFileName}\n`);
297
+ }
298
+ // Write insights file
299
+ try {
300
+ const insightsFilePath = path_1.default.join(rootFolderPath, constants_1.INSIGHTS_FILE_NAME);
301
+ (0, exports.generateInsightsFile)(insightsFilePath, this.isDryRun, config, this.service, this.region, this.project, revisions);
302
+ this.context.stdout.write(`• Saved insights file to ./${constants_1.INSIGHTS_FILE_NAME}\n`);
303
+ }
304
+ catch (err) {
305
+ const errorDetails = err instanceof Error ? err.message : '';
306
+ this.context.stdout.write(helpersRenderer.renderSoftWarning(`Unable to create INSIGHTS.md file. ${errorDetails}`));
307
+ }
308
+ // Exit if dry run
309
+ const outputMsg = `\nℹ️ Your output files are located at: ${rootFolderPath}\n\n`;
310
+ if (this.isDryRun) {
311
+ this.context.stdout.write('\n🚫 The flare files were not sent because the command was executed in dry run mode.');
312
+ this.context.stdout.write(outputMsg);
313
+ return 0;
314
+ }
315
+ // Confirm before sending
316
+ this.context.stdout.write('\n');
317
+ const confirmSendFiles = yield (0, prompt_1.requestConfirmation)('Are you sure you want to send the flare file to Datadog Support?', false);
318
+ if (!confirmSendFiles) {
319
+ this.context.stdout.write('\n🚫 The flare files were not sent based on your selection.');
320
+ this.context.stdout.write(outputMsg);
321
+ return 0;
322
+ }
323
+ // Zip folder
324
+ const zipPath = path_1.default.join(rootFolderPath, FLARE_ZIP_FILE_NAME);
325
+ yield (0, fs_2.zipContents)(rootFolderPath, zipPath);
326
+ // Send to Datadog
327
+ this.context.stdout.write(chalk_1.default.bold('\n🚀 Sending to Datadog Support...\n'));
328
+ yield (0, flare_1.sendToDatadog)(zipPath, this.caseId, this.email, this.apiKey, rootFolderPath);
329
+ this.context.stdout.write(chalk_1.default.bold('\n✅ Successfully sent flare file to Datadog Support!\n'));
330
+ // Delete contents
331
+ (0, fs_2.deleteFolder)(rootFolderPath);
332
+ }
333
+ catch (err) {
334
+ if (err instanceof Error) {
335
+ this.context.stderr.write(helpersRenderer.renderError(err.message));
336
+ }
337
+ return 1;
338
+ }
339
+ return 0;
340
+ });
341
+ }
342
+ }
343
+ exports.CloudRunFlareCommand = CloudRunFlareCommand;
344
+ CloudRunFlareCommand.paths = [['cloud-run', 'flare']];
345
+ CloudRunFlareCommand.usage = clipanion_1.Command.Usage({
346
+ category: 'Serverless',
347
+ description: 'Gather Cloud Run service configuration and sends it to Datadog.',
348
+ });
349
+ /**
350
+ * Check if the user is authenticated with GCP.
351
+ * @returns true if the user is authenticated, false otherwise
352
+ */
353
+ const checkAuthentication = () => __awaiter(void 0, void 0, void 0, function* () {
354
+ const auth = new google_auth_library_1.GoogleAuth();
355
+ try {
356
+ yield auth.getApplicationDefault();
357
+ return true;
358
+ }
359
+ catch (_) {
360
+ return false;
361
+ }
362
+ });
363
+ exports.checkAuthentication = checkAuthentication;
364
+ /**
365
+ * Call the google-cloud run sdk to get the configuration
366
+ * for the given service.
367
+ * @param runClient the google-cloud run sdk client
368
+ * @param serviceName the name of the service
369
+ * @param projectName the project where the service is deployed
370
+ * @param region the region where the service is deployed
371
+ * @returns the configuration for the given service
372
+ */
373
+ const getCloudRunServiceConfig = (runClient, serviceName, projectName, region) => __awaiter(void 0, void 0, void 0, function* () {
374
+ const request = {
375
+ name: runClient.servicePath(projectName, region, serviceName),
376
+ };
377
+ const [response] = yield runClient.getService(request);
378
+ return response;
379
+ });
380
+ exports.getCloudRunServiceConfig = getCloudRunServiceConfig;
381
+ /**
382
+ * Masks environment variables in a Cloud Run service configuration.
383
+ * Makes a copy as to not modify the config in place.
384
+ * @param config
385
+ * @returns masked config
386
+ */
387
+ const maskConfig = (config) => {
388
+ var _a, _b;
389
+ // We stringify and parse again to make a deep copy
390
+ const configCopy = JSON.parse(JSON.stringify(config));
391
+ const containers = (_a = configCopy.template) === null || _a === void 0 ? void 0 : _a.containers;
392
+ if (!containers) {
393
+ return configCopy;
394
+ }
395
+ for (const container of containers) {
396
+ const env = (_b = container.env) !== null && _b !== void 0 ? _b : [];
397
+ for (const envVar of env) {
398
+ const name = envVar.name;
399
+ const val = envVar.value;
400
+ if (!name || !val) {
401
+ continue;
402
+ }
403
+ if (!constants_2.SKIP_MASKING_CLOUDRUN_ENV_VARS.has(name)) {
404
+ envVar.value = (0, utils_1.maskString)(val);
405
+ }
406
+ }
407
+ }
408
+ return configCopy;
409
+ };
410
+ exports.maskConfig = maskConfig;
411
+ /**
412
+ * Summarizes the Cloud Run config as to not flood the terminal
413
+ * @param config
414
+ * @returns a summarized config
415
+ */
416
+ const summarizeConfig = (config) => {
417
+ var _a;
418
+ const summarizedConfig = {};
419
+ summarizedConfig.name = config.name;
420
+ summarizedConfig.uid = config.uid;
421
+ summarizedConfig.uri = config.uri;
422
+ // Get env vars and image for each containers
423
+ const template = config.template;
424
+ if (template) {
425
+ const summarizedContainers = [];
426
+ const containers = (_a = template.containers) !== null && _a !== void 0 ? _a : [];
427
+ containers.forEach((container) => {
428
+ const summarizedContainer = {};
429
+ summarizedContainer.env = container.env;
430
+ summarizedContainer.image = container.image;
431
+ summarizedContainers.push(summarizedContainer);
432
+ });
433
+ summarizedConfig.containers = summarizedContainers;
434
+ }
435
+ return summarizedConfig;
436
+ };
437
+ exports.summarizeConfig = summarizeConfig;
438
+ /**
439
+ * Gets recent logs
440
+ * @param logClient Logging client
441
+ * @param serviceId
442
+ * @param location
443
+ * @param startMillis start time in milliseconds or undefined if no start time is specified
444
+ * @param endMillis end time in milliseconds or undefined if no end time is specified
445
+ * @param severityFilter if included, adds the string to the filter
446
+ * @returns array of logs as CloudRunLog interfaces
447
+ */
448
+ const getLogs = (logClient, serviceId, location, startMillis, endMillis, severityFilter) => __awaiter(void 0, void 0, void 0, function* () {
449
+ var _a, _b, _c, _d, _e, _f, _g, _h;
450
+ const logs = [];
451
+ // Default to the recent logs using MAX_LOG_AGE_MINUTES
452
+ const date = new Date();
453
+ date.setMinutes(date.getMinutes() - MAX_LOG_AGE_MINUTES);
454
+ let startDate = date.toISOString();
455
+ let endDate = new Date().toISOString(); // Current time
456
+ // If startMillis and endMillis are provided, use them to set the date range
457
+ if (startMillis && endMillis) {
458
+ startDate = new Date(startMillis).toISOString();
459
+ endDate = new Date(endMillis).toISOString();
460
+ }
461
+ // Query options
462
+ let filter = `resource.labels.service_name="${serviceId}" AND resource.labels.location="${location}" AND timestamp>="${startDate}" AND timestamp<="${endDate}" AND (textPayload:* OR httpRequest:*)`;
463
+ // We only want to include logs with a textPayload or logs that were an HTTP request.
464
+ // Any other logs are just audit logs which are spammy and don't have any relevant information.
465
+ filter += severityFilter !== null && severityFilter !== void 0 ? severityFilter : '';
466
+ const options = {
467
+ filter,
468
+ orderBy: FILTER_ORDER,
469
+ pageSize: exports.MAX_LOGS,
470
+ };
471
+ const [entries] = yield logClient.getEntries(options);
472
+ for (const entry of entries) {
473
+ let msg = '';
474
+ if (entry.metadata.textPayload) {
475
+ msg = entry.metadata.textPayload;
476
+ }
477
+ if (entry.metadata.httpRequest) {
478
+ const request = entry.metadata.httpRequest;
479
+ const status = (_a = request.status) !== null && _a !== void 0 ? _a : '';
480
+ let ms = 'unknown';
481
+ const latency = request.latency;
482
+ if (latency) {
483
+ ms = (Number(latency.seconds) * 1000 + Math.round(Number(latency.nanos) / 1000000)).toString();
484
+ }
485
+ const bytes = (0, utils_1.formatBytes)(Number(request.responseSize));
486
+ const method = (_b = request.requestMethod) !== null && _b !== void 0 ? _b : '';
487
+ const requestUrl = (_c = request.requestUrl) !== null && _c !== void 0 ? _c : '';
488
+ msg += `${method} ${status}. responseSize: ${bytes}. latency: ${ms} ms. requestUrl: ${requestUrl}`;
489
+ }
490
+ const log = {
491
+ severity: (_e = (_d = entry.metadata.severity) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : '',
492
+ timestamp: (_g = (_f = entry.metadata.timestamp) === null || _f === void 0 ? void 0 : _f.toString()) !== null && _g !== void 0 ? _g : '',
493
+ logName: (_h = entry.metadata.logName) !== null && _h !== void 0 ? _h : '',
494
+ message: `"${msg}"`,
495
+ };
496
+ logs.push(log);
497
+ }
498
+ return logs;
499
+ });
500
+ exports.getLogs = getLogs;
501
+ /**
502
+ * Save logs in a CSV format
503
+ * @param logs array of logs stored as CloudRunLog interfaces
504
+ * @param filePath path to save the CSV file
505
+ */
506
+ const saveLogsFile = (logs, filePath) => {
507
+ const rows = [['severity', 'timestamp', 'logName', 'message']];
508
+ logs.forEach((log) => {
509
+ const severity = `"${log.severity}"`;
510
+ const timestamp = `"${log.timestamp}"`;
511
+ const logName = `"${log.logName}"`;
512
+ const logMessage = `"${log.message}"`;
513
+ rows.push([severity, timestamp, logName, logMessage]);
514
+ });
515
+ const data = rows.join('\n');
516
+ (0, fs_2.writeFile)(filePath, data);
517
+ };
518
+ exports.saveLogsFile = saveLogsFile;
519
+ /**
520
+ * Gets recent revisions for a cloud-run service
521
+ * @param service
522
+ * @param location
523
+ * @param project
524
+ * @returns a string array of recent revisions and their deployment timestamp
525
+ */
526
+ const getRecentRevisions = (service, location, project) => __awaiter(void 0, void 0, void 0, function* () {
527
+ var _j;
528
+ const client = new run_1.RevisionsClient();
529
+ const request = {
530
+ parent: client.servicePath(project, location, service),
531
+ };
532
+ // listRevisions() returns a tuple [Revision[], Request, Response],
533
+ // so we index the first element to get the array of revisions
534
+ const revisions = (yield client.listRevisions(request))[0];
535
+ const revisionTimestampStrings = [];
536
+ let counter = 1;
537
+ for (const entry of revisions) {
538
+ const fullName = entry.name;
539
+ const timestamp = entry.createTime;
540
+ if (fullName && timestamp) {
541
+ // Get the revision name
542
+ const nameSplit = fullName.split('/');
543
+ const revisionName = nameSplit[nameSplit.length - 1];
544
+ // Format the timestamp by first converting seconds/nanos to milliseconds, then using `new Date()`
545
+ const milliseconds = Number((_j = timestamp.seconds) !== null && _j !== void 0 ? _j : 0) * 1000;
546
+ const timestampString = new Date(milliseconds).toISOString().replace('T', ' ').replace('Z', '').slice(0, -4); // Chop off the milliseconds, which will always be .000
547
+ revisionTimestampStrings.push(`\`${revisionName}\` Deployed on ${timestampString}`);
548
+ }
549
+ // Stop iterating once we reach MAX_REVISIONS
550
+ counter += 1;
551
+ if (counter > MAX_REVISIONS) {
552
+ break;
553
+ }
554
+ }
555
+ return revisionTimestampStrings;
556
+ });
557
+ exports.getRecentRevisions = getRecentRevisions;
558
+ /**
559
+ * Generate the insights file
560
+ * @param insightsFilePath path to the insights file
561
+ * @param isDryRun whether or not this is a dry run
562
+ * @param config Cloud run service configuration
563
+ * @param service
564
+ * @param location
565
+ * @param project
566
+ * @param revisions a string array of recent revisions
567
+ */
568
+ const generateInsightsFile = (insightsFilePath, isDryRun, config, service, location, project, revisions) => {
569
+ var _a, _b, _c, _d, _e, _f;
570
+ const lines = [];
571
+ // Header
572
+ lines.push('# Flare Insights');
573
+ lines.push('\n_Autogenerated file from `cloud-run flare`_ ');
574
+ if (isDryRun) {
575
+ lines.push('_This command was run in dry mode._');
576
+ }
577
+ // Cloud Run Service Configuration
578
+ lines.push('\n## Cloud Run Service Configuration');
579
+ lines.push(`**Service Name**: \`${service}\` `);
580
+ lines.push(`**Location**: \`${location}\` `);
581
+ lines.push(`**Project**: \`${project}\` `);
582
+ const description = config.description;
583
+ if (description && description.length > 0) {
584
+ lines.push(`**Description**: \`${description}\` `);
585
+ }
586
+ lines.push(`**URI**: \`${(_a = config.uri) !== null && _a !== void 0 ? _a : ''}\``);
587
+ // Environment variables
588
+ const containers = (_c = (_b = config.template) === null || _b === void 0 ? void 0 : _b.containers) !== null && _c !== void 0 ? _c : [];
589
+ for (const container of containers) {
590
+ // We want to separate environment variables by container if there are multiple containers
591
+ // We can use the container image to uniquely identify each container
592
+ lines.push(`\n**Environment Variables** (${(_d = container.image) !== null && _d !== void 0 ? _d : 'unknown image'}):`);
593
+ const envVars = new Map();
594
+ for (const envVar of (_e = container.env) !== null && _e !== void 0 ? _e : []) {
595
+ const name = envVar.name;
596
+ const value = envVar.value;
597
+ if (name && value) {
598
+ envVars.set(name, value);
599
+ }
600
+ }
601
+ if (envVars.size === 0) {
602
+ lines.push('- No environment variables found.');
603
+ }
604
+ for (const [key, value] of envVars) {
605
+ lines.push(`- \`${key}\`: \`${value}\``);
606
+ }
607
+ }
608
+ // Labels
609
+ lines.push('\n**Labels**:');
610
+ const labels = (_f = config.labels) !== null && _f !== void 0 ? _f : {};
611
+ const entries = Object.entries(labels);
612
+ if (entries.length === 0) {
613
+ lines.push('- No labels found.');
614
+ }
615
+ for (const [key, value] of entries) {
616
+ lines.push(`- \`${key}\`: \`${value}\``);
617
+ }
618
+ // Recent revisions
619
+ if (revisions.length > 0) {
620
+ lines.push('\n**Recent Revisions**:');
621
+ for (const revision of revisions) {
622
+ lines.push(`- ${revision}`);
623
+ }
624
+ }
625
+ // CLI Insights
626
+ lines.push('\n ## CLI');
627
+ lines.push(`**Run Location**: \`${process_1.default.cwd()}\` `);
628
+ lines.push(`**CLI Version**: \`${version_1.version}\` `);
629
+ const timeString = new Date().toISOString().replace('T', ' ').replace('Z', '') + ' UTC';
630
+ lines.push(`**Timestamp**: \`${timeString}\` `);
631
+ (0, fs_2.writeFile)(insightsFilePath, lines.join('\n'));
632
+ };
633
+ exports.generateInsightsFile = generateInsightsFile;
634
+ //# sourceMappingURL=flare.js.map