@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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Command } from 'clipanion';
|
|
2
|
+
import { Provider } from './interfaces';
|
|
3
|
+
export declare class TraceCommand extends Command {
|
|
4
|
+
static usage: import("clipanion/lib/advanced").Usage;
|
|
5
|
+
private command?;
|
|
6
|
+
private config;
|
|
7
|
+
private name?;
|
|
8
|
+
private noFail?;
|
|
9
|
+
private tags?;
|
|
10
|
+
execute(): Promise<number>;
|
|
11
|
+
getCIEnvVars(): [Record<string, string>, Provider?];
|
|
12
|
+
private getApiHelper;
|
|
13
|
+
private getBaseIntakeUrl;
|
|
14
|
+
private getEnvironmentVars;
|
|
15
|
+
private reportCustomSpan;
|
|
16
|
+
private signalToNumber;
|
|
17
|
+
}
|
|
@@ -18,6 +18,7 @@ const child_process_1 = require("child_process");
|
|
|
18
18
|
const clipanion_1 = require("clipanion");
|
|
19
19
|
const crypto_1 = __importDefault(require("crypto"));
|
|
20
20
|
const os_1 = __importDefault(require("os"));
|
|
21
|
+
const retry_1 = require("../../helpers/retry");
|
|
21
22
|
const tags_1 = require("../../helpers/tags");
|
|
22
23
|
const api_1 = require("./api");
|
|
23
24
|
const interfaces_1 = require("./interfaces");
|
|
@@ -41,7 +42,17 @@ class TraceCommand extends clipanion_1.Command {
|
|
|
41
42
|
const [command, ...args] = this.command;
|
|
42
43
|
const id = crypto_1.default.randomBytes(5).toString('hex');
|
|
43
44
|
const startTime = new Date().toISOString();
|
|
44
|
-
const childProcess = child_process_1.spawn(command, args, {
|
|
45
|
+
const childProcess = child_process_1.spawn(command, args, {
|
|
46
|
+
env: Object.assign(Object.assign({}, process.env), { DD_CUSTOM_PARENT_ID: id }),
|
|
47
|
+
stdio: ['inherit', 'inherit', 'pipe'],
|
|
48
|
+
});
|
|
49
|
+
const chunks = [];
|
|
50
|
+
childProcess.stderr.pipe(this.context.stderr);
|
|
51
|
+
const stderrCatcher = new Promise((resolve, reject) => {
|
|
52
|
+
childProcess.stderr.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
53
|
+
childProcess.stderr.on('error', (err) => reject(err));
|
|
54
|
+
childProcess.stderr.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
55
|
+
});
|
|
45
56
|
const [status, signal] = yield new Promise((resolve, reject) => {
|
|
46
57
|
childProcess.on('error', (error) => {
|
|
47
58
|
reject(error);
|
|
@@ -50,15 +61,15 @@ class TraceCommand extends clipanion_1.Command {
|
|
|
50
61
|
resolve([exitStatus, exitSignal]);
|
|
51
62
|
});
|
|
52
63
|
});
|
|
64
|
+
const stderr = yield stderrCatcher;
|
|
53
65
|
const endTime = new Date().toISOString();
|
|
54
66
|
const exitCode = (_a = status !== null && status !== void 0 ? status : this.signalToNumber(signal)) !== null && _a !== void 0 ? _a : BAD_COMMAND_EXIT_CODE;
|
|
55
67
|
const [ciEnvVars, provider] = this.getCIEnvVars();
|
|
56
68
|
if (provider) {
|
|
57
|
-
const api = this.getApiHelper();
|
|
58
69
|
const commandStr = this.command.join(' ');
|
|
59
70
|
const envVarTags = this.config.envVarTags ? tags_1.parseTags(this.config.envVarTags.split(',')) : {};
|
|
60
71
|
const cliTags = this.tags ? tags_1.parseTags(this.tags) : {};
|
|
61
|
-
yield
|
|
72
|
+
yield this.reportCustomSpan({
|
|
62
73
|
command: commandStr,
|
|
63
74
|
custom: {
|
|
64
75
|
id,
|
|
@@ -66,6 +77,8 @@ class TraceCommand extends clipanion_1.Command {
|
|
|
66
77
|
},
|
|
67
78
|
data: ciEnvVars,
|
|
68
79
|
end_time: endTime,
|
|
80
|
+
error_message: stderr,
|
|
81
|
+
exit_code: exitCode,
|
|
69
82
|
is_error: exitCode !== 0,
|
|
70
83
|
name: (_b = this.name) !== null && _b !== void 0 ? _b : commandStr,
|
|
71
84
|
start_time: startTime,
|
|
@@ -151,6 +164,22 @@ class TraceCommand extends clipanion_1.Command {
|
|
|
151
164
|
getEnvironmentVars(keys) {
|
|
152
165
|
return keys.filter((key) => key in process.env).reduce((accum, key) => (Object.assign(Object.assign({}, accum), { [key]: process.env[key] })), {});
|
|
153
166
|
}
|
|
167
|
+
reportCustomSpan(payload, provider) {
|
|
168
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
169
|
+
const api = this.getApiHelper();
|
|
170
|
+
try {
|
|
171
|
+
yield retry_1.retryRequest(() => api.reportCustomSpan(payload, provider), {
|
|
172
|
+
onRetry: (e, attempt) => {
|
|
173
|
+
this.context.stderr.write(chalk_1.default.yellow(`[attempt ${attempt}] Could not report custom span. Retrying...: ${e.message}\n`));
|
|
174
|
+
},
|
|
175
|
+
retries: 5,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
this.context.stderr.write(chalk_1.default.red(`Failed to report custom span: ${error.message}\n`));
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
154
183
|
signalToNumber(signal) {
|
|
155
184
|
if (!signal) {
|
|
156
185
|
return undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const retry_1 = require("../retry");
|
|
13
|
+
describe('retry', () => {
|
|
14
|
+
const retryCallback = jest.fn();
|
|
15
|
+
const createResultWithErrors = (errors) => {
|
|
16
|
+
let i = -1;
|
|
17
|
+
return () => {
|
|
18
|
+
i = i + 1;
|
|
19
|
+
if (errors[i] === undefined) {
|
|
20
|
+
return Promise.resolve({
|
|
21
|
+
config: {},
|
|
22
|
+
data: {},
|
|
23
|
+
headers: undefined,
|
|
24
|
+
status: 200,
|
|
25
|
+
statusText: '',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return Promise.reject(errors[i]);
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
jest.restoreAllMocks();
|
|
33
|
+
});
|
|
34
|
+
const buildHttpError = (statusCode) => ({
|
|
35
|
+
response: {
|
|
36
|
+
status: statusCode,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
test('should retry retriable failed requests', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
yield retry_1.retryRequest(createResultWithErrors([buildHttpError(500), undefined]), {
|
|
41
|
+
maxTimeout: 50,
|
|
42
|
+
minTimeout: 10,
|
|
43
|
+
onRetry: retryCallback,
|
|
44
|
+
retries: 5,
|
|
45
|
+
});
|
|
46
|
+
expect(retryCallback).toBeCalledTimes(1);
|
|
47
|
+
}));
|
|
48
|
+
test('should retry non-http errors', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
yield retry_1.retryRequest(createResultWithErrors([{ message: 'Connection timeout' }, undefined]), {
|
|
50
|
+
maxTimeout: 50,
|
|
51
|
+
minTimeout: 10,
|
|
52
|
+
onRetry: retryCallback,
|
|
53
|
+
retries: 5,
|
|
54
|
+
});
|
|
55
|
+
expect(retryCallback).toBeCalledTimes(1);
|
|
56
|
+
}));
|
|
57
|
+
test('should not retry some clients failures', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
let threwError = false;
|
|
59
|
+
try {
|
|
60
|
+
yield retry_1.retryRequest(createResultWithErrors([buildHttpError(413)]), {
|
|
61
|
+
maxTimeout: 50,
|
|
62
|
+
minTimeout: 10,
|
|
63
|
+
onRetry: retryCallback,
|
|
64
|
+
retries: 5,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
threwError = true;
|
|
69
|
+
}
|
|
70
|
+
expect(threwError).toBeTruthy();
|
|
71
|
+
expect(retryCallback).toBeCalledTimes(0);
|
|
72
|
+
}));
|
|
73
|
+
test('should retry only a given amount of times', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
+
let threwError = false;
|
|
75
|
+
try {
|
|
76
|
+
yield retry_1.retryRequest(createResultWithErrors([buildHttpError(500), buildHttpError(500), buildHttpError(500), buildHttpError(500)]), {
|
|
77
|
+
maxTimeout: 20,
|
|
78
|
+
minTimeout: 10,
|
|
79
|
+
onRetry: retryCallback,
|
|
80
|
+
retries: 3,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
threwError = true;
|
|
85
|
+
}
|
|
86
|
+
expect(threwError).toBeTruthy();
|
|
87
|
+
expect(retryCallback).toBeCalledTimes(3);
|
|
88
|
+
}));
|
|
89
|
+
test('should not retry if the call was successful', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
|
+
yield retry_1.retryRequest(createResultWithErrors([undefined]), {
|
|
91
|
+
maxTimeout: 50,
|
|
92
|
+
minTimeout: 10,
|
|
93
|
+
onRetry: retryCallback,
|
|
94
|
+
retries: 5,
|
|
95
|
+
});
|
|
96
|
+
expect(retryCallback).toBeCalledTimes(0);
|
|
97
|
+
}));
|
|
98
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AxiosError } from 'axios';
|
|
2
|
+
import { BufferedMetricsLogger } from 'datadog-metrics';
|
|
3
|
+
/** ApiKeyValidator is an helper interface to interpret Datadog error responses and possibly check the
|
|
4
|
+
* validity of the api key.
|
|
5
|
+
*/
|
|
6
|
+
export interface ApiKeyValidator {
|
|
7
|
+
verifyApiKey(error: AxiosError): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface ApiKeyValidatorParams {
|
|
10
|
+
apiKey: string | undefined;
|
|
11
|
+
datadogSite: string;
|
|
12
|
+
metricsLogger?: BufferedMetricsLogger;
|
|
13
|
+
}
|
|
14
|
+
export declare const newApiKeyValidator: (params: ApiKeyValidatorParams) => ApiKeyValidator;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Metadata, SpanTags } from './interfaces';
|
|
2
|
+
export declare const CI_ENGINES: {
|
|
3
|
+
APPVEYOR: string;
|
|
4
|
+
AZURE: string;
|
|
5
|
+
BITBUCKET: string;
|
|
6
|
+
BITRISE: string;
|
|
7
|
+
BUILDKITE: string;
|
|
8
|
+
CIRCLECI: string;
|
|
9
|
+
GITHUB: string;
|
|
10
|
+
GITLAB: string;
|
|
11
|
+
JENKINS: string;
|
|
12
|
+
TRAVIS: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const getCISpanTags: () => SpanTags | undefined;
|
|
15
|
+
export declare const getCIMetadata: () => Metadata | undefined;
|
package/dist/helpers/ci.js
CHANGED
|
@@ -102,7 +102,7 @@ const getCISpanTags = () => {
|
|
|
102
102
|
tags[refKey] = ref;
|
|
103
103
|
}
|
|
104
104
|
if (env.GITLAB_CI) {
|
|
105
|
-
const { CI_PIPELINE_ID: GITLAB_CI_PIPELINE_ID, CI_PROJECT_PATH, CI_PIPELINE_IID, CI_PIPELINE_URL: GITLAB_CI_PIPELINE_URL, CI_PROJECT_DIR,
|
|
105
|
+
const { CI_PIPELINE_ID: GITLAB_CI_PIPELINE_ID, CI_PROJECT_PATH, CI_PIPELINE_IID, CI_PIPELINE_URL: GITLAB_CI_PIPELINE_URL, CI_PROJECT_DIR, CI_COMMIT_REF_NAME, CI_COMMIT_TAG, CI_COMMIT_SHA, CI_REPOSITORY_URL, CI_JOB_URL: GITLAB_CI_JOB_URL, CI_JOB_STAGE, CI_JOB_NAME: GITLAB_CI_JOB_NAME, CI_COMMIT_MESSAGE, CI_COMMIT_TIMESTAMP, CI_COMMIT_AUTHOR, } = env;
|
|
106
106
|
const { name, email } = parseEmailAndName(CI_COMMIT_AUTHOR);
|
|
107
107
|
tags = {
|
|
108
108
|
[tags_1.CI_JOB_NAME]: GITLAB_CI_JOB_NAME,
|
|
@@ -114,7 +114,7 @@ const getCISpanTags = () => {
|
|
|
114
114
|
[tags_1.CI_PROVIDER_NAME]: exports.CI_ENGINES.GITLAB,
|
|
115
115
|
[tags_1.CI_WORKSPACE_PATH]: CI_PROJECT_DIR,
|
|
116
116
|
[tags_1.CI_STAGE_NAME]: CI_JOB_STAGE,
|
|
117
|
-
[tags_1.GIT_BRANCH]:
|
|
117
|
+
[tags_1.GIT_BRANCH]: CI_COMMIT_REF_NAME,
|
|
118
118
|
[tags_1.GIT_SHA]: CI_COMMIT_SHA,
|
|
119
119
|
[tags_1.GIT_REPOSITORY_URL]: CI_REPOSITORY_URL,
|
|
120
120
|
[tags_1.GIT_TAG]: CI_COMMIT_TAG,
|
|
@@ -333,7 +333,7 @@ const getCIMetadata = () => {
|
|
|
333
333
|
},
|
|
334
334
|
},
|
|
335
335
|
git: {
|
|
336
|
-
branch: env.
|
|
336
|
+
branch: env.CI_COMMIT_REF_NAME,
|
|
337
337
|
commitSha: env.CI_COMMIT_SHA,
|
|
338
338
|
},
|
|
339
339
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AxiosPromise, AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
import { CI_JOB_NAME, CI_JOB_URL, CI_PIPELINE_ID, CI_PIPELINE_NAME, CI_PIPELINE_NUMBER, CI_PIPELINE_URL, CI_PROVIDER_NAME, CI_STAGE_NAME, CI_WORKSPACE_PATH, GIT_BRANCH, GIT_COMMIT_AUTHOR_DATE, GIT_COMMIT_AUTHOR_EMAIL, GIT_COMMIT_AUTHOR_NAME, GIT_COMMIT_COMMITTER_DATE, GIT_COMMIT_COMMITTER_EMAIL, GIT_COMMIT_COMMITTER_NAME, GIT_COMMIT_MESSAGE, GIT_REPOSITORY_URL, GIT_SHA, GIT_TAG } from './tags';
|
|
3
|
+
export interface Metadata {
|
|
4
|
+
ci: {
|
|
5
|
+
pipeline: {
|
|
6
|
+
url?: string;
|
|
7
|
+
};
|
|
8
|
+
provider: {
|
|
9
|
+
name: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
git: {
|
|
13
|
+
branch?: string;
|
|
14
|
+
commitSha?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare type SpanTag = typeof CI_JOB_NAME | typeof CI_JOB_URL | typeof CI_PIPELINE_ID | typeof CI_PIPELINE_NAME | typeof CI_PIPELINE_NUMBER | typeof CI_PIPELINE_URL | typeof CI_PROVIDER_NAME | typeof CI_STAGE_NAME | typeof CI_WORKSPACE_PATH | typeof GIT_BRANCH | typeof GIT_REPOSITORY_URL | typeof GIT_SHA | typeof GIT_TAG | typeof GIT_COMMIT_AUTHOR_EMAIL | typeof GIT_COMMIT_AUTHOR_NAME | typeof GIT_COMMIT_AUTHOR_DATE | typeof GIT_COMMIT_MESSAGE | typeof GIT_COMMIT_COMMITTER_DATE | typeof GIT_COMMIT_COMMITTER_EMAIL | typeof GIT_COMMIT_COMMITTER_NAME;
|
|
18
|
+
export declare type SpanTags = Partial<Record<SpanTag, string>>;
|
|
19
|
+
export declare type RequestBuilder = (args: AxiosRequestConfig) => AxiosPromise<AxiosResponse>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import metrics from 'datadog-metrics';
|
|
2
|
+
export interface MetricsLogger {
|
|
3
|
+
logger: metrics.BufferedMetricsLogger;
|
|
4
|
+
flush(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export interface MetricsLoggerOptions {
|
|
7
|
+
datadogSite?: string;
|
|
8
|
+
defaultTags?: string[];
|
|
9
|
+
prefix: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const getMetricsLogger: (opts: MetricsLoggerOptions) => MetricsLogger;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.retryRequest = void 0;
|
|
16
|
+
const async_retry_1 = __importDefault(require("async-retry"));
|
|
17
|
+
const errorCodesNoRetry = [400, 403, 413];
|
|
18
|
+
const retryRequest = (requestPerformer, retryOpts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
// Request function, passed to async-retry
|
|
20
|
+
const doRequest = (bail) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
try {
|
|
22
|
+
yield requestPerformer();
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.response && errorCodesNoRetry.includes(error.response.status)) {
|
|
26
|
+
// If it's an axios error with a status code that is excluded from retries, we bail to avoid retrying
|
|
27
|
+
bail(error);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Other cases are retried: other axios HTTP errors as well as
|
|
31
|
+
// non-axios errors such as DNS resolution errors and connection timeouts
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
// Do the actual call
|
|
36
|
+
return async_retry_1.default(doRequest, retryOpts);
|
|
37
|
+
});
|
|
38
|
+
exports.retryRequest = retryRequest;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const CI_PIPELINE_URL = "ci.pipeline.url";
|
|
2
|
+
export declare const CI_PROVIDER_NAME = "ci.provider.name";
|
|
3
|
+
export declare const CI_PIPELINE_ID = "ci.pipeline.id";
|
|
4
|
+
export declare const CI_PIPELINE_NAME = "ci.pipeline.name";
|
|
5
|
+
export declare const CI_PIPELINE_NUMBER = "ci.pipeline.number";
|
|
6
|
+
export declare const CI_WORKSPACE_PATH = "ci.workspace_path";
|
|
7
|
+
export declare const GIT_REPOSITORY_URL = "git.repository_url";
|
|
8
|
+
export declare const CI_JOB_URL = "ci.job.url";
|
|
9
|
+
export declare const CI_JOB_NAME = "ci.job.name";
|
|
10
|
+
export declare const CI_STAGE_NAME = "ci.stage.name";
|
|
11
|
+
export declare const CI_LEVEL = "_dd.ci.level";
|
|
12
|
+
export declare const CI_BUILD_LEVEL = "_dd.ci.build_level";
|
|
13
|
+
export declare const GIT_BRANCH = "git.branch";
|
|
14
|
+
export declare const GIT_COMMIT_AUTHOR_DATE = "git.commit.author.date";
|
|
15
|
+
export declare const GIT_COMMIT_AUTHOR_EMAIL = "git.commit.author.email";
|
|
16
|
+
export declare const GIT_COMMIT_AUTHOR_NAME = "git.commit.author.name";
|
|
17
|
+
export declare const GIT_COMMIT_COMMITTER_DATE = "git.commit.committer.date";
|
|
18
|
+
export declare const GIT_COMMIT_COMMITTER_EMAIL = "git.commit.committer.email";
|
|
19
|
+
export declare const GIT_COMMIT_COMMITTER_NAME = "git.commit.committer.name";
|
|
20
|
+
export declare const GIT_COMMIT_MESSAGE = "git.commit.message";
|
|
21
|
+
export declare const GIT_SHA = "git.commit.sha";
|
|
22
|
+
export declare const GIT_TAG = "git.tag";
|
|
23
|
+
export declare const SPAN_TYPE = "span.type";
|
|
24
|
+
/**
|
|
25
|
+
* Receives an array of the form ['key:value', 'key2:value2']
|
|
26
|
+
* and returns an object of the form {key: 'value', key2: 'value2'}
|
|
27
|
+
*/
|
|
28
|
+
export declare const parseTags: (tags: string[]) => {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import FormData from 'form-data';
|
|
3
|
+
import { ReadStream } from 'fs';
|
|
4
|
+
import { ApiKeyValidator } from './apikey';
|
|
5
|
+
import { RequestBuilder } from './interfaces';
|
|
6
|
+
/** Multipart payload destined to be sent to Datadog's API
|
|
7
|
+
*/
|
|
8
|
+
export interface MultipartPayload {
|
|
9
|
+
content: Map<string, MultipartValue>;
|
|
10
|
+
}
|
|
11
|
+
export interface MultipartValue {
|
|
12
|
+
options?: FormData.AppendOptions | string;
|
|
13
|
+
value: string | ReadStream;
|
|
14
|
+
}
|
|
15
|
+
export interface UploadOptions {
|
|
16
|
+
/** ApiKeyValidator (optional) throws an InvalidConfigurationException when upload fails because
|
|
17
|
+
* of an invalid API key. Callers should most likely catch this exception and display it as a
|
|
18
|
+
* nice error message.
|
|
19
|
+
*/
|
|
20
|
+
apiKeyValidator?: ApiKeyValidator;
|
|
21
|
+
/** Retries is the amount of upload retries before giving up. Some requests are never retried
|
|
22
|
+
* (400, 413).
|
|
23
|
+
*/
|
|
24
|
+
retries: number;
|
|
25
|
+
/** Callback when upload fails (retries are not considered as failure)
|
|
26
|
+
*/
|
|
27
|
+
onError(error: Error): void;
|
|
28
|
+
/** Callback to execute before retries
|
|
29
|
+
*/
|
|
30
|
+
onRetry(error: Error, attempts: number): void;
|
|
31
|
+
/** Callback to execute before upload.
|
|
32
|
+
*/
|
|
33
|
+
onUpload(): void;
|
|
34
|
+
}
|
|
35
|
+
export declare enum UploadStatus {
|
|
36
|
+
Success = 0,
|
|
37
|
+
Failure = 1,
|
|
38
|
+
Skipped = 2
|
|
39
|
+
}
|
|
40
|
+
/** Upload a MultipartPayload to Datadog's API using the provided RequestBuilder.
|
|
41
|
+
* This handles retries as well as logging information about upload if a logger is provided in
|
|
42
|
+
* the options
|
|
43
|
+
*/
|
|
44
|
+
export declare const upload: (requestBuilder: RequestBuilder) => (payload: MultipartPayload, opts: UploadOptions) => Promise<UploadStatus>;
|
package/dist/helpers/upload.js
CHANGED
|
@@ -13,9 +13,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.upload = exports.UploadStatus = void 0;
|
|
16
|
-
const async_retry_1 = __importDefault(require("async-retry"));
|
|
17
16
|
const form_data_1 = __importDefault(require("form-data"));
|
|
18
|
-
const
|
|
17
|
+
const retry_1 = require("./retry");
|
|
19
18
|
var UploadStatus;
|
|
20
19
|
(function (UploadStatus) {
|
|
21
20
|
UploadStatus[UploadStatus["Success"] = 0] = "Success";
|
|
@@ -29,10 +28,10 @@ var UploadStatus;
|
|
|
29
28
|
const upload = (requestBuilder) => (payload, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
29
|
opts.onUpload();
|
|
31
30
|
try {
|
|
32
|
-
yield
|
|
31
|
+
yield retry_1.retryRequest(() => uploadMultipart(requestBuilder, payload), {
|
|
33
32
|
onRetry: opts.onRetry,
|
|
34
33
|
retries: opts.retries,
|
|
35
|
-
})
|
|
34
|
+
});
|
|
36
35
|
return UploadStatus.Success;
|
|
37
36
|
}
|
|
38
37
|
catch (error) {
|
|
@@ -52,31 +51,10 @@ const upload = (requestBuilder) => (payload, opts) => __awaiter(void 0, void 0,
|
|
|
52
51
|
}
|
|
53
52
|
});
|
|
54
53
|
exports.upload = upload;
|
|
55
|
-
const uploadWithRetry = (requestBuilder, retryOpts) => (payload) => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
-
// Upload function, passed to async-retry
|
|
57
|
-
const doUpload = (bail) => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
-
try {
|
|
59
|
-
yield uploadMultipart(requestBuilder)(payload);
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
if (error.response) {
|
|
63
|
-
// If it's an axios error
|
|
64
|
-
if (!errorCodesNoRetry.includes(error.response.status)) {
|
|
65
|
-
// And a status code that is not excluded from retries, throw the error so that upload is retried
|
|
66
|
-
throw error;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
// If it's another error or an axios error we don't want to retry, bail
|
|
70
|
-
bail(error);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
// Do the actual call
|
|
74
|
-
return async_retry_1.default(doUpload, retryOpts);
|
|
75
|
-
});
|
|
76
54
|
// Dependency follows-redirects sets a default maxBodyLength of 10 MB https://github.com/follow-redirects/follow-redirects/blob/b774a77e582b97174813b3eaeb86931becba69db/index.js#L391
|
|
77
55
|
// We don't want any hard limit enforced by the CLI, the backend will enforce a max size by returning 413 errors.
|
|
78
56
|
const maxBodyLength = Infinity;
|
|
79
|
-
const uploadMultipart = (request
|
|
57
|
+
const uploadMultipart = (request, payload) => __awaiter(void 0, void 0, void 0, function* () {
|
|
80
58
|
const form = new form_data_1.default();
|
|
81
59
|
payload.content.forEach((value, key) => {
|
|
82
60
|
form.append(key, value.value, value.options);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getUserGitMetadata: () => {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AxiosRequestConfig } from 'axios';
|
|
2
|
+
import ProxyAgent from 'proxy-agent';
|
|
3
|
+
import type { SpanTags } from './interfaces';
|
|
4
|
+
export declare const pick: <T extends object, K extends keyof T>(base: T, keys: K[]) => Partial<T>;
|
|
5
|
+
export declare const getConfig: (configPath: string) => Promise<any>;
|
|
6
|
+
export declare const parseConfigFile: <T>(baseConfig: T, configPath?: string | undefined) => Promise<T>;
|
|
7
|
+
declare type ProxyType = 'http' | 'https' | 'socks' | 'socks4' | 'socks4a' | 'socks5' | 'socks5h' | 'pac+data' | 'pac+file' | 'pac+ftp' | 'pac+http' | 'pac+https';
|
|
8
|
+
export interface ProxyConfiguration {
|
|
9
|
+
auth?: {
|
|
10
|
+
password: string;
|
|
11
|
+
username: string;
|
|
12
|
+
};
|
|
13
|
+
host?: string;
|
|
14
|
+
port?: number;
|
|
15
|
+
protocol: ProxyType;
|
|
16
|
+
}
|
|
17
|
+
export declare const getProxyUrl: (options?: ProxyConfiguration | undefined) => string;
|
|
18
|
+
export interface RequestOptions {
|
|
19
|
+
apiKey: string;
|
|
20
|
+
appKey?: string;
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
headers?: Map<string, string>;
|
|
23
|
+
overrideUrl?: string;
|
|
24
|
+
proxyOpts?: ProxyConfiguration;
|
|
25
|
+
}
|
|
26
|
+
export declare const getRequestBuilder: (options: RequestOptions) => (args: AxiosRequestConfig) => import("axios").AxiosPromise<any>;
|
|
27
|
+
export declare const getProxyAgent: (proxyOpts?: ProxyConfiguration | undefined) => ReturnType<typeof ProxyAgent>;
|
|
28
|
+
export declare const getApiHostForSite: (site: string) => string;
|
|
29
|
+
export declare const buildPath: (...args: string[]) => string;
|
|
30
|
+
export declare const removeEmptyValues: (tags: SpanTags) => {};
|
|
31
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datadog/datadog-ci",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.7",
|
|
4
4
|
"description": "Run datadog actions from the CI.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"repository": "https://github.com/DataDog/datadog-ci",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"datadog-metrics": "0.9.3",
|
|
49
49
|
"dd-trace": "0.35.1-beta.1",
|
|
50
50
|
"deep-extend": "0.6.0",
|
|
51
|
-
"fast-xml-parser": "
|
|
51
|
+
"fast-xml-parser": "3.19.0",
|
|
52
52
|
"form-data": "3.0.0",
|
|
53
53
|
"glob": "7.1.4",
|
|
54
|
-
"proxy-agent": "
|
|
54
|
+
"proxy-agent": "5.0.0",
|
|
55
55
|
"simple-git": "2.31.0",
|
|
56
56
|
"ssh2": "1.4.0",
|
|
57
57
|
"ssh2-streams": "0.4.10",
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
"@types/xml2js": "0.4.9",
|
|
80
80
|
"jest": "27.0.5",
|
|
81
81
|
"jest-environment-node": "27.0.5",
|
|
82
|
+
"jest-matcher-specific-error": "1.0.0",
|
|
82
83
|
"prettier": "2.0.5",
|
|
83
84
|
"proxy": "1.0.2",
|
|
84
85
|
"ts-jest": "27.0.3",
|