@datadog/datadog-ci 0.17.6-alpha → 0.17.9

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 (153) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/dist/commands/dependencies/__tests__/helpers/context.d.ts +12 -0
  3. package/dist/commands/dependencies/__tests__/helpers/stream.d.ts +2 -0
  4. package/dist/commands/dependencies/__tests__/helpers/upload.run.d.ts +13 -0
  5. package/dist/commands/dependencies/__tests__/upload.test.d.ts +1 -0
  6. package/dist/commands/dependencies/api.d.ts +2 -0
  7. package/dist/commands/dependencies/index.d.ts +1 -0
  8. package/dist/commands/dependencies/interfaces.d.ts +10 -0
  9. package/dist/commands/dependencies/renderer.d.ts +13 -0
  10. package/dist/commands/dependencies/upload.d.ts +16 -0
  11. package/dist/commands/dsyms/__tests__/upload.test.d.ts +1 -0
  12. package/dist/commands/dsyms/__tests__/utils.test.d.ts +1 -0
  13. package/dist/commands/dsyms/index.d.ts +1 -0
  14. package/dist/commands/dsyms/interfaces.d.ts +7 -0
  15. package/dist/commands/dsyms/renderer.d.ts +9 -0
  16. package/dist/commands/dsyms/upload.d.ts +11 -0
  17. package/dist/commands/dsyms/utils.d.ts +9 -0
  18. package/dist/commands/git-metadata/__tests__/git.test.d.ts +1 -0
  19. package/dist/commands/{commit → git-metadata}/__tests__/git.test.js +0 -0
  20. package/dist/commands/git-metadata/__tests__/upload.test.d.ts +1 -0
  21. package/dist/commands/{commit → git-metadata}/__tests__/upload.test.js +1 -1
  22. package/dist/commands/git-metadata/api.d.ts +3 -0
  23. package/dist/commands/{commit → git-metadata}/api.js +0 -0
  24. package/dist/commands/git-metadata/git.d.ts +8 -0
  25. package/dist/commands/{commit → git-metadata}/git.js +0 -0
  26. package/dist/commands/git-metadata/index.d.ts +1 -0
  27. package/dist/commands/{commit → git-metadata}/index.js +0 -0
  28. package/dist/commands/git-metadata/interfaces.d.ts +9 -0
  29. package/dist/commands/{commit → git-metadata}/interfaces.js +0 -0
  30. package/dist/commands/git-metadata/renderer.d.ts +8 -0
  31. package/dist/commands/{commit → git-metadata}/renderer.js +5 -8
  32. package/dist/commands/git-metadata/upload.d.ts +12 -0
  33. package/dist/commands/{commit → git-metadata}/upload.js +8 -3
  34. package/dist/commands/junit/__tests__/api.test.d.ts +1 -0
  35. package/dist/commands/junit/__tests__/upload.test.d.ts +1 -0
  36. package/dist/commands/junit/api.d.ts +8 -0
  37. package/dist/commands/junit/index.d.ts +1 -0
  38. package/dist/commands/junit/interfaces.d.ts +12 -0
  39. package/dist/commands/junit/renderer.d.ts +8 -0
  40. package/dist/commands/junit/upload.d.ts +15 -0
  41. package/dist/commands/junit/upload.js +8 -25
  42. package/dist/commands/junit/utils.d.ts +1 -0
  43. package/dist/commands/lambda/__tests__/fixtures.d.ts +42 -0
  44. package/dist/commands/lambda/__tests__/fixtures.js +73 -0
  45. package/dist/commands/lambda/__tests__/functions/commons.test.d.ts +1 -0
  46. package/dist/commands/lambda/__tests__/functions/commons.test.js +171 -0
  47. package/dist/commands/lambda/__tests__/functions/instrument.test.d.ts +1 -0
  48. package/dist/commands/lambda/__tests__/{function.test.js → functions/instrument.test.js} +355 -417
  49. package/dist/commands/lambda/__tests__/functions/uninstrument.test.d.ts +1 -0
  50. package/dist/commands/lambda/__tests__/functions/uninstrument.test.js +298 -0
  51. package/dist/commands/lambda/__tests__/instrument.test.d.ts +1 -0
  52. package/dist/commands/lambda/__tests__/instrument.test.js +270 -163
  53. package/dist/commands/lambda/__tests__/loggroup.test.d.ts +1 -0
  54. package/dist/commands/lambda/__tests__/loggroup.test.js +98 -34
  55. package/dist/commands/lambda/__tests__/tags.test.d.ts +1 -0
  56. package/dist/commands/lambda/__tests__/tags.test.js +107 -31
  57. package/dist/commands/lambda/__tests__/uninstrument.test.d.ts +1 -0
  58. package/dist/commands/lambda/__tests__/uninstrument.test.js +223 -0
  59. package/dist/commands/lambda/constants.d.ts +44 -0
  60. package/dist/commands/lambda/constants.js +2 -1
  61. package/dist/commands/lambda/functions/commons.d.ts +71 -0
  62. package/dist/commands/lambda/functions/commons.js +170 -0
  63. package/dist/commands/lambda/functions/instrument.d.ts +16 -0
  64. package/dist/commands/lambda/{function.js → functions/instrument.js} +42 -102
  65. package/dist/commands/lambda/functions/uninstrument.d.ts +6 -0
  66. package/dist/commands/lambda/functions/uninstrument.js +110 -0
  67. package/dist/commands/lambda/index.d.ts +1 -0
  68. package/dist/commands/lambda/index.js +2 -1
  69. package/dist/commands/lambda/instrument.d.ts +29 -0
  70. package/dist/commands/lambda/instrument.js +85 -40
  71. package/dist/commands/lambda/interfaces.d.ts +70 -0
  72. package/dist/commands/lambda/loggroup.d.ts +14 -0
  73. package/dist/commands/lambda/loggroup.js +27 -4
  74. package/dist/commands/lambda/tags.d.ts +6 -0
  75. package/dist/commands/lambda/tags.js +19 -3
  76. package/dist/commands/lambda/uninstrument.d.ts +11 -0
  77. package/dist/commands/lambda/uninstrument.js +127 -0
  78. package/dist/commands/sourcemaps/__tests__/git.test.d.ts +1 -0
  79. package/dist/commands/sourcemaps/__tests__/upload.test.d.ts +1 -0
  80. package/dist/commands/sourcemaps/__tests__/utils.test.d.ts +1 -0
  81. package/dist/commands/sourcemaps/git.d.ts +20 -0
  82. package/dist/commands/sourcemaps/index.d.ts +1 -0
  83. package/dist/commands/sourcemaps/interfaces.d.ts +15 -0
  84. package/dist/commands/sourcemaps/renderer.d.ts +12 -0
  85. package/dist/commands/sourcemaps/upload.d.ts +25 -0
  86. package/dist/commands/sourcemaps/utils.d.ts +3 -0
  87. package/dist/commands/sourcemaps/validation.d.ts +6 -0
  88. package/dist/commands/synthetics/__tests__/api.test.d.ts +1 -0
  89. package/dist/commands/synthetics/__tests__/cli.test.d.ts +1 -0
  90. package/dist/commands/synthetics/__tests__/cli.test.js +232 -0
  91. package/dist/commands/synthetics/__tests__/crypto.test.d.ts +1 -0
  92. package/dist/commands/synthetics/__tests__/fixtures.d.ts +71 -0
  93. package/dist/commands/synthetics/__tests__/fixtures.js +17 -2
  94. package/dist/commands/synthetics/__tests__/reporters/default.test.d.ts +1 -0
  95. package/dist/commands/synthetics/__tests__/reporters/default.test.js +5 -4
  96. package/dist/commands/synthetics/__tests__/reporters/junit.test.d.ts +1 -0
  97. package/dist/commands/synthetics/__tests__/run-test.test.d.ts +1 -0
  98. package/dist/commands/synthetics/__tests__/run-test.test.js +48 -319
  99. package/dist/commands/synthetics/__tests__/tunnel.test.d.ts +1 -0
  100. package/dist/commands/synthetics/__tests__/utils.test.d.ts +1 -0
  101. package/dist/commands/synthetics/__tests__/utils.test.js +13 -1
  102. package/dist/commands/synthetics/__tests__/websocket.test.d.ts +1 -0
  103. package/dist/commands/synthetics/__tests__/websocket.test.js +6 -5
  104. package/dist/commands/synthetics/api.d.ts +24 -0
  105. package/dist/commands/synthetics/cli.d.ts +26 -0
  106. package/dist/commands/synthetics/cli.js +229 -0
  107. package/dist/commands/synthetics/crypto.d.ts +5 -0
  108. package/dist/commands/synthetics/errors.d.ts +9 -0
  109. package/dist/commands/synthetics/errors.js +25 -0
  110. package/dist/commands/synthetics/index.d.ts +1 -0
  111. package/dist/commands/synthetics/index.js +2 -2
  112. package/dist/commands/synthetics/interfaces.d.ts +342 -0
  113. package/dist/commands/synthetics/reporters/default.d.ts +18 -0
  114. package/dist/commands/synthetics/reporters/default.js +4 -3
  115. package/dist/commands/synthetics/reporters/junit.d.ts +95 -0
  116. package/dist/commands/synthetics/run-test.d.ts +74 -0
  117. package/dist/commands/synthetics/run-test.js +135 -319
  118. package/dist/commands/synthetics/tunnel.d.ts +43 -0
  119. package/dist/commands/synthetics/utils.d.ts +27 -0
  120. package/dist/commands/synthetics/utils.js +24 -5
  121. package/dist/commands/synthetics/websocket.d.ts +38 -0
  122. package/dist/commands/trace/__tests__/trace.test.d.ts +1 -0
  123. package/dist/commands/trace/api.d.ts +6 -0
  124. package/dist/commands/trace/index.d.ts +1 -0
  125. package/dist/commands/trace/interfaces.d.ts +23 -0
  126. package/dist/commands/trace/trace.d.ts +17 -0
  127. package/dist/commands/trace/trace.js +32 -3
  128. package/dist/helpers/__tests__/ci.test.d.ts +1 -0
  129. package/dist/helpers/__tests__/ci.test.js +23 -0
  130. package/dist/helpers/__tests__/git.test.d.ts +1 -0
  131. package/dist/helpers/__tests__/retry.test.d.ts +1 -0
  132. package/dist/helpers/__tests__/retry.test.js +98 -0
  133. package/dist/helpers/__tests__/tags.test.d.ts +1 -0
  134. package/dist/helpers/__tests__/upload.test.d.ts +1 -0
  135. package/dist/helpers/__tests__/user-provided-git.test.d.ts +1 -0
  136. package/dist/helpers/__tests__/utils.test.d.ts +1 -0
  137. package/dist/helpers/apikey.d.ts +14 -0
  138. package/dist/helpers/ci.d.ts +15 -0
  139. package/dist/helpers/ci.js +13 -6
  140. package/dist/helpers/errors.d.ts +2 -0
  141. package/dist/helpers/formatting.d.ts +5 -0
  142. package/dist/helpers/git.d.ts +2 -0
  143. package/dist/helpers/interfaces.d.ts +19 -0
  144. package/dist/helpers/metrics.d.ts +11 -0
  145. package/dist/helpers/retry.d.ts +2 -0
  146. package/dist/helpers/retry.js +38 -0
  147. package/dist/helpers/tags.d.ts +28 -0
  148. package/dist/helpers/upload.d.ts +44 -0
  149. package/dist/helpers/upload.js +4 -26
  150. package/dist/helpers/user-provided-git.d.ts +1 -0
  151. package/dist/helpers/utils.d.ts +31 -0
  152. package/dist/index.d.ts +1 -0
  153. package/package.json +2 -1
@@ -0,0 +1,95 @@
1
+ import { BaseContext } from 'clipanion';
2
+ import { InternalTest, LocationsMapping, PollResult, Reporter, Vitals } from '../interfaces';
3
+ interface Stats {
4
+ allowfailures: number;
5
+ errors: number;
6
+ failures: number;
7
+ skipped: number;
8
+ tests: number;
9
+ warnings: number;
10
+ }
11
+ interface XMLTestCaseProperties extends Stats {
12
+ name: string;
13
+ time: number | undefined;
14
+ timestamp: string;
15
+ }
16
+ export interface XMLTestCase {
17
+ $: XMLTestCaseProperties;
18
+ allowed_error: XMLError[];
19
+ browser_error: XMLError[];
20
+ error: XMLError[];
21
+ properties: {
22
+ property: {
23
+ $: {
24
+ name: string;
25
+ value: any;
26
+ };
27
+ }[];
28
+ };
29
+ testcase: XMLStep[];
30
+ warning: XMLError[];
31
+ }
32
+ interface XMLStepProperties extends Stats {
33
+ allow_failure: boolean;
34
+ is_skipped: boolean;
35
+ name: string;
36
+ substep_public_id?: string;
37
+ time: number;
38
+ type: string;
39
+ url?: string;
40
+ }
41
+ interface XMLStep {
42
+ $: XMLStepProperties;
43
+ browser_error?: {
44
+ $: {
45
+ name: string;
46
+ type: string;
47
+ };
48
+ _: string;
49
+ }[];
50
+ error: {
51
+ $: {
52
+ type: 'assertion';
53
+ };
54
+ _: string;
55
+ }[];
56
+ vitals?: {
57
+ $: Vitals;
58
+ }[];
59
+ warning?: {
60
+ $: {
61
+ type: string;
62
+ };
63
+ _: string;
64
+ }[];
65
+ }
66
+ interface XMLError {
67
+ $: {
68
+ type: string;
69
+ [key: string]: string;
70
+ };
71
+ _: string;
72
+ }
73
+ interface Args {
74
+ context: BaseContext;
75
+ jUnitReport?: string;
76
+ runName?: string;
77
+ }
78
+ export declare const getDefaultStats: () => Stats;
79
+ export declare class JUnitReporter implements Reporter {
80
+ private builder;
81
+ private destination;
82
+ private json;
83
+ private write;
84
+ constructor({ context, jUnitReport, runName }: Args);
85
+ runEnd(): Promise<void>;
86
+ testEnd(test: InternalTest, results: PollResult[], baseUrl: string, locations: LocationsMapping, failOnCriticalErrors: boolean, failOnTimeout: boolean): void;
87
+ private getApiStepStats;
88
+ private getApiTestStep;
89
+ private getBrowserStepStats;
90
+ private getBrowserTestStep;
91
+ private getResultStats;
92
+ private getSuiteStats;
93
+ private getTestCase;
94
+ }
95
+ export {};
@@ -0,0 +1,74 @@
1
+ import { APIHelper, MainReporter, PollResult, Summary, SyntheticsCIConfig, Test, Trigger } from './interfaces';
2
+ export declare const executeTests: (reporter: MainReporter, config: SyntheticsCIConfig) => Promise<{
3
+ results: {
4
+ [key: string]: PollResult[];
5
+ };
6
+ summary: Summary;
7
+ tests: Test[];
8
+ triggers: Trigger;
9
+ }>;
10
+ export declare const getTestsList: (api: APIHelper, config: SyntheticsCIConfig, reporter: MainReporter) => Promise<{
11
+ config: {
12
+ allowInsecureCertificates?: boolean | undefined;
13
+ basicAuth?: import("./interfaces").BasicAuthCredentials | undefined;
14
+ body?: string | undefined;
15
+ bodyType?: string | undefined;
16
+ cookies?: string | {
17
+ append?: boolean | undefined;
18
+ value: string;
19
+ } | undefined;
20
+ defaultStepTimeout?: number | undefined;
21
+ deviceIds?: string[] | undefined;
22
+ executionRule?: import("./interfaces").ExecutionRule | undefined;
23
+ followRedirects?: boolean | undefined;
24
+ headers?: {
25
+ [key: string]: string;
26
+ } | undefined;
27
+ locations: string[];
28
+ pollingTimeout?: number | undefined;
29
+ retry?: import("./interfaces").RetryConfig | undefined;
30
+ startUrl?: string | undefined;
31
+ tunnel?: import("./tunnel").TunnelInfo | undefined;
32
+ variables?: {
33
+ [key: string]: string;
34
+ } | undefined;
35
+ } | {
36
+ allowInsecureCertificates?: boolean | undefined;
37
+ basicAuth?: import("./interfaces").BasicAuthCredentials | undefined;
38
+ body?: string | undefined;
39
+ bodyType?: string | undefined;
40
+ cookies?: string | {
41
+ append?: boolean | undefined;
42
+ value: string;
43
+ } | undefined;
44
+ defaultStepTimeout?: number | undefined;
45
+ deviceIds?: string[] | undefined;
46
+ executionRule?: import("./interfaces").ExecutionRule | undefined;
47
+ followRedirects?: boolean | undefined;
48
+ headers?: {
49
+ [key: string]: string;
50
+ } | undefined;
51
+ locations?: string[] | undefined;
52
+ pollingTimeout?: number | undefined;
53
+ retry?: import("./interfaces").RetryConfig | undefined;
54
+ startUrl?: string | undefined;
55
+ tunnel?: import("./tunnel").TunnelInfo | undefined;
56
+ variables?: {
57
+ [key: string]: string;
58
+ } | undefined;
59
+ };
60
+ id: string;
61
+ suite: string | undefined;
62
+ }[]>;
63
+ export declare const getApiHelper: (config: SyntheticsCIConfig) => {
64
+ getPresignedURL: (testIds: string[]) => Promise<{
65
+ url: string;
66
+ }>;
67
+ getTest: (testId: string) => Promise<Test>;
68
+ pollResults: (resultIds: string[]) => Promise<{
69
+ results: PollResult[];
70
+ }>;
71
+ searchTests: (query: string) => Promise<import("./interfaces").TestSearchResult>;
72
+ triggerTests: (data: import("./interfaces").Payload) => Promise<Trigger>;
73
+ };
74
+ export declare const getDatadogHost: (useIntake: boolean | undefined, config: SyntheticsCIConfig) => string;
@@ -8,336 +8,152 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.removeUndefinedValues = exports.RunTestCommand = exports.DEFAULT_COMMAND_CONFIG = void 0;
16
- const chalk_1 = __importDefault(require("chalk"));
17
- const clipanion_1 = require("clipanion");
18
- const deep_extend_1 = __importDefault(require("deep-extend"));
19
- const utils_1 = require("../../helpers/utils");
12
+ exports.getDatadogHost = exports.getApiHelper = exports.getTestsList = exports.executeTests = void 0;
20
13
  const api_1 = require("./api");
21
- const interfaces_1 = require("./interfaces");
22
- const default_1 = require("./reporters/default");
23
- const junit_1 = require("./reporters/junit");
14
+ const errors_1 = require("./errors");
24
15
  const tunnel_1 = require("./tunnel");
25
- const utils_2 = require("./utils");
26
- exports.DEFAULT_COMMAND_CONFIG = {
27
- apiKey: '',
28
- appKey: '',
29
- configPath: 'datadog-ci.json',
30
- datadogSite: 'datadoghq.com',
31
- failOnCriticalErrors: false,
32
- failOnTimeout: true,
33
- files: ['{,!(node_modules)/**/}*.synthetics.json'],
34
- global: {},
35
- locations: [],
36
- pollingTimeout: 2 * 60 * 1000,
37
- proxy: { protocol: 'http' },
38
- publicIds: [],
39
- subdomain: 'app',
40
- tunnel: false,
41
- };
42
- class RunTestCommand extends clipanion_1.Command {
43
- constructor() {
44
- super(...arguments);
45
- this.config = JSON.parse(JSON.stringify(exports.DEFAULT_COMMAND_CONFIG)); // Deep copy to avoid mutation during unit tests
46
- }
47
- execute() {
48
- var _a;
49
- return __awaiter(this, void 0, void 0, function* () {
50
- const reporters = [new default_1.DefaultReporter(this)];
51
- if (this.jUnitReport) {
52
- reporters.push(new junit_1.JUnitReporter(this));
53
- }
54
- this.reporter = utils_2.getReporter(reporters);
55
- yield this.resolveConfig();
56
- const startTime = Date.now();
57
- const api = this.getApiHelper();
58
- const publicIdsFromCli = this.config.publicIds.map((id) => ({ suite: 'CLI Suite', config: this.config.global, id }));
59
- let testsToTrigger;
60
- let tunnel;
61
- const safeExit = (exitCode) => __awaiter(this, void 0, void 0, function* () {
62
- if (tunnel) {
63
- yield tunnel.stop();
64
- }
65
- return exitCode;
66
- });
67
- if (publicIdsFromCli.length) {
68
- testsToTrigger = publicIdsFromCli;
69
- }
70
- else {
71
- try {
72
- testsToTrigger = yield this.getTestsList(api);
73
- }
74
- catch (error) {
75
- this.reporter.error(`\n${chalk_1.default.bgRed.bold(' ERROR: unable to obtain test configurations with search query ')}\n${error.message}\n\n`);
76
- if (api_1.is5xxError(error) && !this.config.failOnCriticalErrors) {
77
- return safeExit(0);
78
- }
79
- return safeExit(1);
80
- }
81
- }
82
- if (!testsToTrigger.length) {
83
- this.reporter.log('No test suites to run.\n');
84
- return safeExit(0);
85
- }
86
- let testsToTriggerResult;
87
- try {
88
- testsToTriggerResult = yield utils_2.getTestsToTrigger(api, testsToTrigger, this.reporter);
89
- }
90
- catch (error) {
91
- this.reporter.error(`\n${chalk_1.default.bgRed.bold(' ERROR: unable to obtain test configurations ')}\n${error.message}\n\n`);
92
- if (api_1.is5xxError(error) && !this.config.failOnCriticalErrors) {
93
- return safeExit(0);
94
- }
95
- return safeExit(1);
96
- }
97
- const { tests, overriddenTestsToTrigger, summary } = testsToTriggerResult;
98
- // All tests have been skipped or are missing.
99
- if (!tests.length) {
100
- this.reporter.log('No test to run.\n');
101
- return safeExit(0);
102
- }
103
- const publicIdsToTrigger = tests.map(({ public_id }) => public_id);
104
- if (this.config.tunnel) {
105
- this.reporter.log('You are using tunnel option, the chosen location(s) will be overridden by a location in your account region.\n');
106
- let presignedURL;
107
- try {
108
- // Get the pre-signed URL to connect to the tunnel service
109
- presignedURL = (yield api.getPresignedURL(publicIdsToTrigger)).url;
110
- }
111
- catch (e) {
112
- this.reporter.error(`\n${chalk_1.default.bgRed.bold(' ERROR: unable to get tunnel configuration')}\n${e.message}\n\n`);
113
- if (api_1.is5xxError(e) && !this.config.failOnCriticalErrors) {
114
- return safeExit(0);
115
- }
116
- return safeExit(1);
117
- }
118
- // Open a tunnel to Datadog
119
- try {
120
- tunnel = new tunnel_1.Tunnel(presignedURL, publicIdsToTrigger, this.config.proxy, this.reporter);
121
- const tunnelInfo = yield tunnel.start();
122
- overriddenTestsToTrigger.forEach((testToTrigger) => {
123
- testToTrigger.tunnel = tunnelInfo;
124
- });
125
- }
126
- catch (e) {
127
- this.reporter.error(`\n${chalk_1.default.bgRed.bold(' ERROR: unable to start tunnel ')}\n${e.message}\n\n`);
128
- if (api_1.is5xxError(e) && !this.config.failOnCriticalErrors) {
129
- return safeExit(0);
130
- }
131
- return safeExit(1);
132
- }
133
- }
134
- let triggers;
135
- try {
136
- triggers = yield utils_2.runTests(api, overriddenTestsToTrigger);
137
- }
138
- catch (e) {
139
- this.reporter.error(`\n${chalk_1.default.bgRed.bold(' ERROR: unable to trigger tests ')}\n${e.message}\n\n`);
140
- if (api_1.is5xxError(e) && !this.config.failOnCriticalErrors) {
141
- return safeExit(0);
142
- }
143
- return safeExit(1);
144
- }
145
- if (!triggers.results) {
146
- throw new Error('No result to poll.');
147
- }
148
- const results = {};
149
- try {
150
- // Poll the results.
151
- const resultPolled = yield utils_2.waitForResults(api, triggers.results, this.config.pollingTimeout, testsToTrigger, tunnel, this.config.failOnCriticalErrors);
152
- Object.assign(results, resultPolled);
153
- }
154
- catch (error) {
155
- this.reporter.error(`\n${chalk_1.default.bgRed.bold(' ERROR: unable to poll test results ')}\n${error.message}\n\n`);
156
- if (api_1.is5xxError(error) && !this.config.failOnCriticalErrors) {
157
- return safeExit(0);
158
- }
159
- return safeExit(1);
160
- }
161
- // Sort tests to show success first then non blocking failures and finally blocking failures.
162
- tests.sort(this.sortTestsByOutcome(results));
163
- // Rendering the results.
164
- this.reporter.reportStart({ startTime });
165
- const locationNames = triggers.locations.reduce((mapping, location) => {
166
- mapping[location.id] = location.display_name;
167
- return mapping;
168
- }, {});
169
- let hasSucceeded = true; // Determine if all the tests have succeeded
170
- for (const test of tests) {
171
- const testResults = results[test.public_id];
172
- if (!this.config.failOnTimeout) {
173
- if (!summary.timedOut) {
174
- summary.timedOut = 0;
175
- }
176
- const hasTimeout = testResults.some((pollResult) => pollResult.result.error === interfaces_1.ERRORS.TIMEOUT);
177
- if (hasTimeout) {
178
- summary.timedOut++;
179
- }
180
- }
181
- if (!this.config.failOnCriticalErrors) {
182
- if (!summary.criticalErrors) {
183
- summary.criticalErrors = 0;
184
- }
185
- const hasCriticalErrors = testResults.some((pollResult) => utils_2.isCriticalError(pollResult.result));
186
- if (hasCriticalErrors) {
187
- summary.criticalErrors++;
188
- }
189
- }
190
- const passed = utils_2.hasTestSucceeded(testResults, this.config.failOnCriticalErrors, this.config.failOnTimeout);
191
- if (passed) {
192
- summary.passed++;
193
- }
194
- else {
195
- summary.failed++;
196
- if (((_a = test.options.ci) === null || _a === void 0 ? void 0 : _a.executionRule) !== interfaces_1.ExecutionRule.NON_BLOCKING) {
197
- hasSucceeded = false;
198
- }
199
- }
200
- this.reporter.testEnd(test, testResults, this.getAppBaseURL(), locationNames, this.config.failOnCriticalErrors, this.config.failOnTimeout);
201
- }
202
- this.reporter.runEnd(summary);
203
- return safeExit(hasSucceeded ? 0 : 1);
204
- });
16
+ const utils_1 = require("./utils");
17
+ const executeTests = (reporter, config) => __awaiter(void 0, void 0, void 0, function* () {
18
+ const api = exports.getApiHelper(config);
19
+ const publicIdsFromCli = config.publicIds.map((id) => ({ config: config.global, id }));
20
+ let testsToTrigger;
21
+ let tunnel;
22
+ const stopTunnel = () => __awaiter(void 0, void 0, void 0, function* () {
23
+ if (tunnel) {
24
+ yield tunnel.stop();
25
+ }
26
+ });
27
+ if (publicIdsFromCli.length) {
28
+ testsToTrigger = publicIdsFromCli;
205
29
  }
206
- getApiHelper() {
207
- if (!this.config.appKey || !this.config.apiKey) {
208
- if (!this.config.appKey) {
209
- this.reporter.error(`Missing ${chalk_1.default.red.bold('DATADOG_APP_KEY')} in your environment.\n`);
210
- }
211
- if (!this.config.apiKey) {
212
- this.reporter.error(`Missing ${chalk_1.default.red.bold('DATADOG_API_KEY')} in your environment.\n`);
213
- }
214
- throw new Error('API and/or Application keys are missing');
30
+ else {
31
+ try {
32
+ testsToTrigger = yield exports.getTestsList(api, config, reporter);
215
33
  }
216
- return api_1.apiConstructor({
217
- apiKey: this.config.apiKey,
218
- appKey: this.config.appKey,
219
- baseIntakeUrl: this.getDatadogHost(true),
220
- baseUrl: this.getDatadogHost(),
221
- proxyOpts: this.config.proxy,
222
- });
34
+ catch (error) {
35
+ const isCriticalError = api_1.is5xxError(error);
36
+ throw new (isCriticalError ? errors_1.CriticalError : errors_1.CiError)('UNAVAILABLE_TEST_CONFIG');
37
+ }
38
+ }
39
+ if (!testsToTrigger.length) {
40
+ throw new errors_1.CiError('NO_TESTS_TO_RUN');
41
+ }
42
+ let testsToTriggerResult;
43
+ try {
44
+ testsToTriggerResult = yield utils_1.getTestsToTrigger(api, testsToTrigger, reporter);
223
45
  }
224
- getAppBaseURL() {
225
- return `https://${this.config.subdomain}.${this.config.datadogSite}/`;
46
+ catch (error) {
47
+ const isCriticalError = api_1.is5xxError(error);
48
+ throw new (isCriticalError ? errors_1.CriticalError : errors_1.CiError)('UNAVAILABLE_TEST_CONFIG');
226
49
  }
227
- getDatadogHost(useIntake = false) {
228
- const apiPath = 'api/v1';
229
- let host = `https://api.${this.config.datadogSite}`;
230
- const hostOverride = process.env.DD_API_HOST_OVERRIDE;
231
- if (hostOverride) {
232
- host = hostOverride;
50
+ const { tests, overriddenTestsToTrigger, summary } = testsToTriggerResult;
51
+ // All tests have been skipped or are missing.
52
+ if (!tests.length) {
53
+ throw new errors_1.CiError('NO_TESTS_TO_RUN');
54
+ }
55
+ const publicIdsToTrigger = tests.map(({ public_id }) => public_id);
56
+ if (config.tunnel) {
57
+ let presignedURL;
58
+ try {
59
+ // Get the pre-signed URL to connect to the tunnel service
60
+ presignedURL = (yield api.getPresignedURL(publicIdsToTrigger)).url;
61
+ }
62
+ catch (error) {
63
+ const isCriticalError = api_1.is5xxError(error);
64
+ throw new (isCriticalError ? errors_1.CriticalError : errors_1.CiError)('UNAVAILABLE_TUNNEL_CONFIG');
233
65
  }
234
- else if (useIntake &&
235
- (this.config.datadogSite === 'datadoghq.com' || this.config.datadogSite === 'datad0g.com')) {
236
- host = `https://intake.synthetics.${this.config.datadogSite}`;
66
+ // Open a tunnel to Datadog
67
+ try {
68
+ tunnel = new tunnel_1.Tunnel(presignedURL, publicIdsToTrigger, config.proxy, reporter);
69
+ const tunnelInfo = yield tunnel.start();
70
+ overriddenTestsToTrigger.forEach((testToTrigger) => {
71
+ testToTrigger.tunnel = tunnelInfo;
72
+ });
73
+ }
74
+ catch (error) {
75
+ const isCriticalError = api_1.is5xxError(error);
76
+ yield stopTunnel();
77
+ throw new (isCriticalError ? errors_1.CriticalError : errors_1.CiError)('TUNNEL_START_FAILED');
237
78
  }
238
- return `${host}/${apiPath}`;
239
79
  }
240
- getTestsList(api) {
241
- var _a;
242
- return __awaiter(this, void 0, void 0, function* () {
243
- if (this.config.testSearchQuery) {
244
- const testSearchResults = yield api.searchTests(this.config.testSearchQuery);
245
- return testSearchResults.tests.map((test) => ({
246
- config: this.config.global,
247
- id: test.public_id,
248
- suite: `Query: ${this.testSearchQuery}`,
249
- }));
250
- }
251
- const suites = (yield Promise.all(this.config.files.map((glob) => utils_2.getSuites(glob, this.reporter))))
252
- .reduce((acc, val) => acc.concat(val), [])
253
- .filter((suite) => !!suite.content.tests);
254
- const configFromEnvironment = ((_a = this.config.locations) === null || _a === void 0 ? void 0 : _a.length) ? { locations: this.config.locations } : {};
255
- const testsToTrigger = suites
256
- .map((suite) => suite.content.tests.map((test) => ({
257
- config: Object.assign(Object.assign(Object.assign({}, this.config.global), configFromEnvironment), test.config),
258
- id: test.id,
259
- suite: suite.name,
260
- })))
261
- .reduce((acc, suiteTests) => acc.concat(suiteTests), []);
262
- return testsToTrigger;
263
- });
80
+ let triggers;
81
+ try {
82
+ triggers = yield utils_1.runTests(api, overriddenTestsToTrigger);
83
+ }
84
+ catch (error) {
85
+ const isCriticalError = api_1.is5xxError(error);
86
+ yield stopTunnel();
87
+ throw new (isCriticalError ? errors_1.CriticalError : errors_1.CiError)('TRIGGER_TESTS_FAILED');
88
+ }
89
+ if (!triggers.results) {
90
+ yield stopTunnel();
91
+ throw new errors_1.CriticalError('NO_RESULTS_TO_POLL');
92
+ }
93
+ const results = {};
94
+ try {
95
+ // Poll the results.
96
+ const resultPolled = yield utils_1.waitForResults(api, triggers.results, config.pollingTimeout, testsToTrigger, tunnel, config.failOnCriticalErrors);
97
+ Object.assign(results, resultPolled);
98
+ }
99
+ catch (error) {
100
+ const isCriticalError = api_1.is5xxError(error);
101
+ yield stopTunnel();
102
+ throw new (isCriticalError ? errors_1.CriticalError : errors_1.CiError)('POLL_RESULTS_FAILED');
264
103
  }
265
- resolveConfig() {
266
- var _a, _b;
267
- return __awaiter(this, void 0, void 0, function* () {
268
- // Default < file < ENV < CLI
269
- // Override with file config variables
270
- try {
271
- this.config = yield utils_1.parseConfigFile(this.config, (_a = this.configPath) !== null && _a !== void 0 ? _a : this.config.configPath);
272
- }
273
- catch (error) {
274
- if (this.configPath) {
275
- throw error;
276
- }
277
- }
278
- // Override with ENV variables
279
- this.config = deep_extend_1.default(this.config, exports.removeUndefinedValues({
280
- apiKey: process.env.DATADOG_API_KEY,
281
- appKey: process.env.DATADOG_APP_KEY,
282
- datadogSite: process.env.DATADOG_SITE,
283
- locations: (_b = process.env.DATADOG_SYNTHETICS_LOCATIONS) === null || _b === void 0 ? void 0 : _b.split(';'),
284
- subdomain: process.env.DATADOG_SUBDOMAIN,
285
- }));
286
- // Override with CLI parameters
287
- this.config = deep_extend_1.default(this.config, exports.removeUndefinedValues({
288
- apiKey: this.apiKey,
289
- appKey: this.appKey,
290
- configPath: this.configPath,
291
- datadogSite: this.datadogSite,
292
- failOnCriticalErrors: this.failOnCriticalErrors,
293
- failOnTimeout: this.failOnTimeout,
294
- files: this.files,
295
- publicIds: this.publicIds,
296
- subdomain: this.subdomain,
297
- testSearchQuery: this.testSearchQuery,
298
- tunnel: this.tunnel,
299
- }));
300
- if (typeof this.config.files === 'string') {
301
- this.reporter.log('[DEPRECATED] "files" should be an array of string instead of a string.\n');
302
- this.config.files = [this.config.files];
303
- }
304
- });
104
+ return { results, summary, tests, triggers };
105
+ });
106
+ exports.executeTests = executeTests;
107
+ const getTestsList = (api, config, reporter) => __awaiter(void 0, void 0, void 0, function* () {
108
+ var _a;
109
+ if (config.testSearchQuery) {
110
+ const testSearchResults = yield api.searchTests(config.testSearchQuery);
111
+ return testSearchResults.tests.map((test) => ({
112
+ config: config.global,
113
+ id: test.public_id,
114
+ suite: `Query: ${config.testSearchQuery}`,
115
+ }));
116
+ }
117
+ const suites = (yield Promise.all(config.files.map((glob) => utils_1.getSuites(glob, reporter))))
118
+ .reduce((acc, val) => acc.concat(val), [])
119
+ .filter((suite) => !!suite.content.tests);
120
+ const configFromEnvironment = ((_a = config.locations) === null || _a === void 0 ? void 0 : _a.length) ? { locations: config.locations } : {};
121
+ const testsToTrigger = suites
122
+ .map((suite) => suite.content.tests.map((test) => ({
123
+ config: Object.assign(Object.assign(Object.assign({}, config.global), configFromEnvironment), test.config),
124
+ id: test.id,
125
+ suite: suite.name,
126
+ })))
127
+ .reduce((acc, suiteTests) => acc.concat(suiteTests), []);
128
+ return testsToTrigger;
129
+ });
130
+ exports.getTestsList = getTestsList;
131
+ const getApiHelper = (config) => {
132
+ if (!config.appKey) {
133
+ throw new errors_1.CiError('MISSING_APP_KEY');
134
+ }
135
+ if (!config.apiKey) {
136
+ throw new errors_1.CiError('MISSING_API_KEY');
137
+ }
138
+ return api_1.apiConstructor({
139
+ apiKey: config.apiKey,
140
+ appKey: config.appKey,
141
+ baseIntakeUrl: exports.getDatadogHost(true, config),
142
+ baseUrl: exports.getDatadogHost(false, config),
143
+ proxyOpts: config.proxy,
144
+ });
145
+ };
146
+ exports.getApiHelper = getApiHelper;
147
+ const getDatadogHost = (useIntake = false, config) => {
148
+ const apiPath = 'api/v1';
149
+ let host = `https://api.${config.datadogSite}`;
150
+ const hostOverride = process.env.DD_API_HOST_OVERRIDE;
151
+ if (hostOverride) {
152
+ host = hostOverride;
305
153
  }
306
- sortTestsByOutcome(results) {
307
- return (t1, t2) => {
308
- var _a, _b;
309
- const success1 = utils_2.hasTestSucceeded(results[t1.public_id], this.config.failOnCriticalErrors, this.config.failOnTimeout);
310
- const success2 = utils_2.hasTestSucceeded(results[t2.public_id], this.config.failOnCriticalErrors, this.config.failOnTimeout);
311
- const isNonBlockingTest1 = ((_a = t1.options.ci) === null || _a === void 0 ? void 0 : _a.executionRule) === interfaces_1.ExecutionRule.NON_BLOCKING;
312
- const isNonBlockingTest2 = ((_b = t2.options.ci) === null || _b === void 0 ? void 0 : _b.executionRule) === interfaces_1.ExecutionRule.NON_BLOCKING;
313
- if (success1 === success2) {
314
- if (isNonBlockingTest1 === isNonBlockingTest2) {
315
- return 0;
316
- }
317
- return isNonBlockingTest1 ? -1 : 1;
318
- }
319
- return success1 ? -1 : 1;
320
- };
154
+ else if (useIntake && (config.datadogSite === 'datadoghq.com' || config.datadogSite === 'datad0g.com')) {
155
+ host = `https://intake.synthetics.${config.datadogSite}`;
321
156
  }
322
- }
323
- exports.RunTestCommand = RunTestCommand;
324
- const removeUndefinedValues = (object) => {
325
- const newObject = Object.assign({}, object);
326
- Object.keys(newObject).forEach((k) => newObject[k] === undefined && delete newObject[k]);
327
- return newObject;
157
+ return `${host}/${apiPath}`;
328
158
  };
329
- exports.removeUndefinedValues = removeUndefinedValues;
330
- RunTestCommand.addPath('synthetics', 'run-tests');
331
- RunTestCommand.addOption('apiKey', clipanion_1.Command.String('--apiKey'));
332
- RunTestCommand.addOption('appKey', clipanion_1.Command.String('--appKey'));
333
- RunTestCommand.addOption('failOnCriticalErrors', clipanion_1.Command.Boolean('--failOnCriticalErrors'));
334
- RunTestCommand.addOption('configPath', clipanion_1.Command.String('--config'));
335
- RunTestCommand.addOption('datadogSite', clipanion_1.Command.String('--datadogSite'));
336
- RunTestCommand.addOption('files', clipanion_1.Command.Array('-f,--files'));
337
- RunTestCommand.addOption('failOnTimeout', clipanion_1.Command.Boolean('--failOnTimeout'));
338
- RunTestCommand.addOption('publicIds', clipanion_1.Command.Array('-p,--public-id'));
339
- RunTestCommand.addOption('testSearchQuery', clipanion_1.Command.String('-s,--search'));
340
- RunTestCommand.addOption('subdomain', clipanion_1.Command.Boolean('--subdomain'));
341
- RunTestCommand.addOption('tunnel', clipanion_1.Command.Boolean('-t,--tunnel'));
342
- RunTestCommand.addOption('jUnitReport', clipanion_1.Command.String('-j,--jUnitReport'));
343
- RunTestCommand.addOption('runName', clipanion_1.Command.String('-n,--runName'));
159
+ exports.getDatadogHost = getDatadogHost;