@datadog/datadog-ci 0.17.4 → 0.17.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +1 -0
- package/dist/commands/dependencies/__tests__/helpers/context.d.ts +12 -0
- package/dist/commands/dependencies/__tests__/helpers/stream.d.ts +2 -0
- package/dist/commands/dependencies/__tests__/helpers/upload.run.d.ts +13 -0
- package/dist/commands/dependencies/__tests__/upload.test.d.ts +1 -0
- package/dist/commands/dependencies/api.d.ts +2 -0
- package/dist/commands/dependencies/index.d.ts +1 -0
- package/dist/commands/dependencies/interfaces.d.ts +10 -0
- package/dist/commands/dependencies/renderer.d.ts +13 -0
- package/dist/commands/dependencies/upload.d.ts +16 -0
- package/dist/commands/dsyms/__tests__/upload.test.d.ts +1 -0
- package/dist/commands/dsyms/__tests__/utils.test.d.ts +1 -0
- package/dist/commands/dsyms/index.d.ts +1 -0
- package/dist/commands/dsyms/interfaces.d.ts +7 -0
- package/dist/commands/dsyms/renderer.d.ts +9 -0
- package/dist/commands/dsyms/upload.d.ts +11 -0
- package/dist/commands/dsyms/utils.d.ts +9 -0
- package/dist/commands/git-metadata/__tests__/git.test.d.ts +1 -0
- package/dist/commands/{commit → git-metadata}/__tests__/git.test.js +0 -0
- package/dist/commands/git-metadata/__tests__/upload.test.d.ts +1 -0
- package/dist/commands/{commit → git-metadata}/__tests__/upload.test.js +1 -1
- package/dist/commands/git-metadata/api.d.ts +3 -0
- package/dist/commands/{commit → git-metadata}/api.js +0 -0
- package/dist/commands/git-metadata/git.d.ts +8 -0
- package/dist/commands/{commit → git-metadata}/git.js +0 -0
- package/dist/commands/git-metadata/index.d.ts +1 -0
- package/dist/commands/{commit → git-metadata}/index.js +0 -0
- package/dist/commands/git-metadata/interfaces.d.ts +9 -0
- package/dist/commands/{commit → git-metadata}/interfaces.js +0 -0
- package/dist/commands/git-metadata/renderer.d.ts +8 -0
- package/dist/commands/{commit → git-metadata}/renderer.js +5 -8
- package/dist/commands/git-metadata/upload.d.ts +12 -0
- package/dist/commands/{commit → git-metadata}/upload.js +8 -3
- package/dist/commands/junit/__tests__/api.test.d.ts +1 -0
- package/dist/commands/junit/__tests__/upload.test.d.ts +1 -0
- package/dist/commands/junit/api.d.ts +8 -0
- package/dist/commands/junit/index.d.ts +1 -0
- package/dist/commands/junit/interfaces.d.ts +12 -0
- package/dist/commands/junit/renderer.d.ts +8 -0
- package/dist/commands/junit/upload.d.ts +15 -0
- package/dist/commands/junit/upload.js +8 -25
- package/dist/commands/junit/utils.d.ts +1 -0
- package/dist/commands/lambda/__tests__/function.test.d.ts +1 -0
- package/dist/commands/lambda/__tests__/instrument.test.d.ts +1 -0
- package/dist/commands/lambda/__tests__/loggroup.test.d.ts +1 -0
- package/dist/commands/lambda/__tests__/tags.test.d.ts +1 -0
- package/dist/commands/lambda/constants.d.ts +43 -0
- package/dist/commands/lambda/function.d.ts +43 -0
- package/dist/commands/lambda/index.d.ts +1 -0
- package/dist/commands/lambda/instrument.d.ts +28 -0
- package/dist/commands/lambda/interfaces.d.ts +16 -0
- package/dist/commands/lambda/loggroup.d.ts +17 -0
- package/dist/commands/lambda/tags.d.ts +7 -0
- package/dist/commands/sourcemaps/__tests__/git.test.d.ts +1 -0
- package/dist/commands/sourcemaps/__tests__/upload.test.d.ts +1 -0
- package/dist/commands/sourcemaps/__tests__/utils.test.d.ts +1 -0
- package/dist/commands/sourcemaps/git.d.ts +20 -0
- package/dist/commands/sourcemaps/index.d.ts +1 -0
- package/dist/commands/sourcemaps/interfaces.d.ts +15 -0
- package/dist/commands/sourcemaps/renderer.d.ts +12 -0
- package/dist/commands/sourcemaps/upload.d.ts +25 -0
- package/dist/commands/sourcemaps/utils.d.ts +3 -0
- package/dist/commands/sourcemaps/validation.d.ts +6 -0
- package/dist/commands/synthetics/__tests__/api.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/cli.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/cli.test.js +232 -0
- package/dist/commands/synthetics/__tests__/crypto.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/fixtures.d.ts +71 -0
- package/dist/commands/synthetics/__tests__/fixtures.js +17 -1
- package/dist/commands/synthetics/__tests__/reporters/default.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/reporters/default.test.js +2 -2
- package/dist/commands/synthetics/__tests__/reporters/junit.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/reporters/junit.test.js +16 -14
- package/dist/commands/synthetics/__tests__/run-test.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/run-test.test.js +42 -313
- package/dist/commands/synthetics/__tests__/tunnel.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/utils.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/utils.test.js +4 -0
- package/dist/commands/synthetics/__tests__/websocket.test.d.ts +1 -0
- package/dist/commands/synthetics/__tests__/websocket.test.js +6 -5
- package/dist/commands/synthetics/api.d.ts +24 -0
- package/dist/commands/synthetics/cli.d.ts +26 -0
- package/dist/commands/synthetics/cli.js +229 -0
- package/dist/commands/synthetics/crypto.d.ts +5 -0
- package/dist/commands/synthetics/errors.d.ts +9 -0
- package/dist/commands/synthetics/errors.js +25 -0
- package/dist/commands/synthetics/index.d.ts +1 -0
- package/dist/commands/synthetics/index.js +2 -2
- package/dist/commands/synthetics/interfaces.d.ts +342 -0
- package/dist/commands/synthetics/reporters/default.d.ts +18 -0
- package/dist/commands/synthetics/reporters/junit.d.ts +95 -0
- package/dist/commands/synthetics/reporters/junit.js +45 -19
- package/dist/commands/synthetics/run-test.d.ts +74 -0
- package/dist/commands/synthetics/run-test.js +135 -319
- package/dist/commands/synthetics/tunnel.d.ts +43 -0
- package/dist/commands/synthetics/utils.d.ts +26 -0
- package/dist/commands/synthetics/utils.js +11 -1
- package/dist/commands/synthetics/websocket.d.ts +38 -0
- package/dist/commands/trace/__tests__/trace.test.d.ts +1 -0
- package/dist/commands/trace/api.d.ts +6 -0
- package/dist/commands/trace/index.d.ts +1 -0
- package/dist/commands/trace/interfaces.d.ts +23 -0
- package/dist/commands/trace/trace.d.ts +17 -0
- package/dist/commands/trace/trace.js +32 -3
- package/dist/helpers/__tests__/ci.test.d.ts +1 -0
- package/dist/helpers/__tests__/ci.test.js +1 -1
- package/dist/helpers/__tests__/git.test.d.ts +1 -0
- package/dist/helpers/__tests__/retry.test.d.ts +1 -0
- package/dist/helpers/__tests__/retry.test.js +98 -0
- package/dist/helpers/__tests__/tags.test.d.ts +1 -0
- package/dist/helpers/__tests__/upload.test.d.ts +1 -0
- package/dist/helpers/__tests__/user-provided-git.test.d.ts +1 -0
- package/dist/helpers/__tests__/utils.test.d.ts +1 -0
- package/dist/helpers/apikey.d.ts +14 -0
- package/dist/helpers/ci.d.ts +15 -0
- package/dist/helpers/ci.js +3 -3
- package/dist/helpers/errors.d.ts +2 -0
- package/dist/helpers/formatting.d.ts +5 -0
- package/dist/helpers/git.d.ts +2 -0
- package/dist/helpers/interfaces.d.ts +19 -0
- package/dist/helpers/metrics.d.ts +11 -0
- package/dist/helpers/retry.d.ts +2 -0
- package/dist/helpers/retry.js +38 -0
- package/dist/helpers/tags.d.ts +28 -0
- package/dist/helpers/upload.d.ts +44 -0
- package/dist/helpers/upload.js +4 -26
- package/dist/helpers/user-provided-git.d.ts +1 -0
- package/dist/helpers/utils.d.ts +31 -0
- package/dist/index.d.ts +1 -0
- package/package.json +4 -3
|
@@ -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.
|
|
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
|
|
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
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
307
|
-
|
|
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.
|
|
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;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ProxyConfiguration } from '../../helpers/utils';
|
|
2
|
+
import { MainReporter } from './interfaces';
|
|
3
|
+
export interface TunnelInfo {
|
|
4
|
+
host: string;
|
|
5
|
+
id: string;
|
|
6
|
+
privateKey: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class Tunnel {
|
|
9
|
+
private url;
|
|
10
|
+
private testIDs;
|
|
11
|
+
private connected;
|
|
12
|
+
private forwardedSockets;
|
|
13
|
+
private FORWARDING_TIMEOUT;
|
|
14
|
+
private log;
|
|
15
|
+
private logError;
|
|
16
|
+
private logWarning;
|
|
17
|
+
private multiplexer?;
|
|
18
|
+
private privateKey;
|
|
19
|
+
private publicKey;
|
|
20
|
+
private sshConfig;
|
|
21
|
+
private ws;
|
|
22
|
+
constructor(url: string, testIDs: string[], proxy: ProxyConfiguration, reporter: MainReporter);
|
|
23
|
+
/**
|
|
24
|
+
* keepAlive will return a promise that tracks the state of the tunnel (and reject in case of error)
|
|
25
|
+
*/
|
|
26
|
+
keepAlive(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* start the tunnel:
|
|
29
|
+
* - get the pre-signed URL to connect to the tunnel service
|
|
30
|
+
* - Set up SSH
|
|
31
|
+
* - establish a WebSocket connection to the tunnel service
|
|
32
|
+
*/
|
|
33
|
+
start(): Promise<TunnelInfo>;
|
|
34
|
+
/**
|
|
35
|
+
* stop the tunnel
|
|
36
|
+
*/
|
|
37
|
+
stop(): Promise<void>;
|
|
38
|
+
private authenticateSSHConnection;
|
|
39
|
+
private forwardProxiedPacketsFromSSH;
|
|
40
|
+
private forwardWebSocketToSSH;
|
|
41
|
+
private getConnectionInfo;
|
|
42
|
+
private processSSHStream;
|
|
43
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { APIHelper, ConfigOverride, ExecutionRule, InternalTest, MainReporter, PollResult, Reporter, Result, Suite, Summary, TestPayload, Trigger, TriggerConfig, TriggerResponse, TriggerResult } from './interfaces';
|
|
2
|
+
import { Tunnel } from './tunnel';
|
|
3
|
+
export declare const handleConfig: (test: InternalTest, publicId: string, reporter: MainReporter, config?: ConfigOverride | undefined) => TestPayload;
|
|
4
|
+
export declare const getExecutionRule: (test: InternalTest, configOverride?: ConfigOverride | undefined) => ExecutionRule;
|
|
5
|
+
export declare const getStrictestExecutionRule: (configRule: ExecutionRule, testRule?: ExecutionRule | undefined) => ExecutionRule;
|
|
6
|
+
export declare const isCriticalError: (result: Result) => boolean;
|
|
7
|
+
export declare const hasResultPassed: (result: Result, failOnCriticalErrors: boolean, failOnTimeout: boolean) => boolean;
|
|
8
|
+
export declare const hasTestSucceeded: (results: PollResult[], failOnCriticalErrors: boolean, failOnTimeout: boolean) => boolean;
|
|
9
|
+
export declare const getSuites: (GLOB: string, reporter: MainReporter) => Promise<Suite[]>;
|
|
10
|
+
export declare const wait: (duration: number) => Promise<unknown>;
|
|
11
|
+
export declare const waitForResults: (api: APIHelper, triggerResponses: TriggerResponse[], defaultTimeout: number, triggerConfigs: TriggerConfig[], tunnel?: Tunnel | undefined, failOnCriticalErrors?: boolean | undefined) => Promise<{
|
|
12
|
+
[key: string]: PollResult[];
|
|
13
|
+
}>;
|
|
14
|
+
export declare const createTriggerResultMap: (triggerResponses: TriggerResponse[], defaultTimeout: number, triggerConfigs: TriggerConfig[]) => Map<string, TriggerResult>;
|
|
15
|
+
export declare const getResultDuration: (result: Result) => number;
|
|
16
|
+
export declare const getReporter: (reporters: Reporter[]) => MainReporter;
|
|
17
|
+
export declare const getTestsToTrigger: (api: APIHelper, triggerConfigs: TriggerConfig[], reporter: MainReporter) => Promise<{
|
|
18
|
+
tests: InternalTest[];
|
|
19
|
+
overriddenTestsToTrigger: TestPayload[];
|
|
20
|
+
summary: Summary;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const runTests: (api: APIHelper, testsToTrigger: TestPayload[]) => Promise<Trigger>;
|
|
23
|
+
export declare const retry: <T, E extends Error>(func: () => Promise<T>, shouldRetryAfterWait: (retries: number, error: E) => number | undefined) => Promise<T>;
|
|
24
|
+
export declare const removeUndefinedValues: <T extends {
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
}>(object: T) => T;
|
|
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
31
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
32
|
};
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
-
exports.retry = exports.runTests = exports.getTestsToTrigger = exports.getReporter = exports.getResultDuration = exports.createTriggerResultMap = exports.waitForResults = exports.wait = exports.getSuites = exports.hasTestSucceeded = exports.hasResultPassed = exports.isCriticalError = exports.getStrictestExecutionRule = exports.getExecutionRule = exports.handleConfig = void 0;
|
|
34
|
+
exports.removeUndefinedValues = exports.retry = exports.runTests = exports.getTestsToTrigger = exports.getReporter = exports.getResultDuration = exports.createTriggerResultMap = exports.waitForResults = exports.wait = exports.getSuites = exports.hasTestSucceeded = exports.hasResultPassed = exports.isCriticalError = exports.getStrictestExecutionRule = exports.getExecutionRule = exports.handleConfig = void 0;
|
|
35
35
|
const fs = __importStar(require("fs"));
|
|
36
36
|
const path = __importStar(require("path"));
|
|
37
37
|
const url_1 = require("url");
|
|
@@ -426,3 +426,13 @@ const retry = (func, shouldRetryAfterWait) => __awaiter(void 0, void 0, void 0,
|
|
|
426
426
|
return trier();
|
|
427
427
|
});
|
|
428
428
|
exports.retry = retry;
|
|
429
|
+
const removeUndefinedValues = (object) => {
|
|
430
|
+
const newObject = Object.assign({}, object);
|
|
431
|
+
for (const [key, value] of Object.entries(newObject)) {
|
|
432
|
+
if (value === undefined) {
|
|
433
|
+
delete newObject[key];
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return newObject;
|
|
437
|
+
};
|
|
438
|
+
exports.removeUndefinedValues = removeUndefinedValues;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import { default as WebSocketModule } from 'ws';
|
|
4
|
+
import { ProxyConfiguration } from '../../helpers/utils';
|
|
5
|
+
export declare class WebSocket extends EventEmitter {
|
|
6
|
+
private url;
|
|
7
|
+
private proxyOpts;
|
|
8
|
+
private firstMessage?;
|
|
9
|
+
private keepAliveWebsocket?;
|
|
10
|
+
private websocket?;
|
|
11
|
+
constructor(url: string, proxyOpts: ProxyConfiguration);
|
|
12
|
+
/**
|
|
13
|
+
* close will terminate the WebSocket connection
|
|
14
|
+
*/
|
|
15
|
+
close(gracefullyClose?: boolean): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* connect will start a WebSocket connection
|
|
18
|
+
*/
|
|
19
|
+
connect(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* duplex will create a duplex stream for the WS connection
|
|
22
|
+
*/
|
|
23
|
+
duplex(): import("stream").Duplex;
|
|
24
|
+
/**
|
|
25
|
+
* keepAlive will return a promise to keep track of the tunnel connection
|
|
26
|
+
*/
|
|
27
|
+
keepAlive(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* on allows to listen for WebSocket messages
|
|
30
|
+
*/
|
|
31
|
+
on(event: 'message', listener: (data: WebSocketModule.Data) => void): this;
|
|
32
|
+
/**
|
|
33
|
+
* once allows to listen for a WebSocket message
|
|
34
|
+
*/
|
|
35
|
+
once(event: 'message', listener: (data: WebSocketModule.Data) => void): this;
|
|
36
|
+
waitForFirstMessage(): Promise<WebSocketModule.Data>;
|
|
37
|
+
private establishWebsocketConnection;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
import { Payload } from './interfaces';
|
|
3
|
+
export declare const reportCustomSpan: (request: (args: AxiosRequestConfig) => AxiosPromise<AxiosResponse>) => (customSpan: Payload, provider: string) => Promise<AxiosResponse<AxiosResponse<any>>>;
|
|
4
|
+
export declare const apiConstructor: (baseUrl: string, apiKey: string) => {
|
|
5
|
+
reportCustomSpan: (customSpan: Payload, provider: string) => Promise<AxiosResponse<AxiosResponse<any>>>;
|
|
6
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AxiosPromise, AxiosResponse } from 'axios';
|
|
2
|
+
export declare const CIRCLECI = "circleci";
|
|
3
|
+
export declare const JENKINS = "jenkins";
|
|
4
|
+
export declare const SUPPORTED_PROVIDERS: readonly ["circleci", "jenkins"];
|
|
5
|
+
export declare type Provider = typeof SUPPORTED_PROVIDERS[number];
|
|
6
|
+
export interface Payload {
|
|
7
|
+
command: string;
|
|
8
|
+
custom: {
|
|
9
|
+
id: string;
|
|
10
|
+
parent_id?: string;
|
|
11
|
+
};
|
|
12
|
+
data: Record<string, string>;
|
|
13
|
+
end_time: string;
|
|
14
|
+
error_message: string;
|
|
15
|
+
exit_code: number;
|
|
16
|
+
is_error: boolean;
|
|
17
|
+
name: string;
|
|
18
|
+
start_time: string;
|
|
19
|
+
tags: Partial<Record<string, string>>;
|
|
20
|
+
}
|
|
21
|
+
export interface APIHelper {
|
|
22
|
+
reportCustomSpan(customSpan: Payload, provider: Provider): AxiosPromise<AxiosResponse>;
|
|
23
|
+
}
|