@datadog/datadog-ci 0.18.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +1 -0
- package/README.md +28 -2
- package/dist/commands/git-metadata/__tests__/git.test.js +44 -2
- package/dist/commands/{dependencies/__tests__/upload.test.d.ts → git-metadata/__tests__/library.test.d.ts} +0 -0
- package/dist/commands/git-metadata/__tests__/library.test.js +82 -0
- package/dist/commands/git-metadata/git.d.ts +1 -2
- package/dist/commands/git-metadata/git.js +13 -25
- package/dist/commands/git-metadata/index.d.ts +1 -0
- package/dist/commands/git-metadata/index.js +13 -0
- package/dist/commands/git-metadata/library.d.ts +6 -0
- package/dist/commands/git-metadata/library.js +68 -0
- package/dist/commands/git-metadata/upload.d.ts +1 -2
- package/dist/commands/git-metadata/upload.js +31 -27
- package/dist/commands/lambda/__tests__/functions/instrument.test.js +2 -2
- package/dist/commands/lambda/__tests__/functions/uninstrument.test.js +2 -2
- package/dist/commands/lambda/__tests__/instrument.test.js +14 -9
- package/dist/commands/lambda/__tests__/prompt.test.js +0 -4
- package/dist/commands/lambda/__tests__/uninstrument.test.js +12 -7
- package/dist/commands/lambda/constants.d.ts +0 -1
- package/dist/commands/lambda/constants.js +2 -27
- package/dist/commands/lambda/functions/commons.js +1 -1
- package/dist/commands/lambda/instrument.js +5 -2
- package/dist/commands/lambda/prompt.d.ts +1 -0
- package/dist/commands/lambda/prompt.js +19 -10
- package/dist/commands/lambda/tags.js +1 -5
- package/dist/commands/lambda/uninstrument.js +1 -1
- package/dist/commands/synthetics/__tests__/cli.test.js +107 -4
- package/dist/commands/synthetics/__tests__/fixtures.d.ts +2 -1
- package/dist/commands/synthetics/__tests__/fixtures.js +4 -1
- package/dist/commands/synthetics/__tests__/reporters/default.test.js +2 -1
- package/dist/commands/synthetics/__tests__/run-test.test.js +4 -4
- package/dist/commands/synthetics/__tests__/utils.test.js +31 -1
- package/dist/commands/synthetics/api.d.ts +1 -0
- package/dist/commands/synthetics/api.js +5 -3
- package/dist/commands/synthetics/command.js +13 -5
- package/dist/commands/synthetics/crypto.d.ts +2 -1
- package/dist/commands/synthetics/errors.d.ts +7 -2
- package/dist/commands/synthetics/errors.js +6 -3
- package/dist/commands/synthetics/index.d.ts +1 -1
- package/dist/commands/synthetics/index.js +2 -1
- package/dist/commands/synthetics/interfaces.d.ts +5 -1
- package/dist/commands/synthetics/reporters/default.d.ts +1 -0
- package/dist/commands/synthetics/reporters/default.js +16 -8
- package/dist/commands/synthetics/run-test.js +9 -15
- package/dist/commands/synthetics/utils.d.ts +1 -0
- package/dist/commands/synthetics/utils.js +29 -13
- package/dist/commands/{dependencies → version}/cli.d.ts +0 -0
- package/dist/commands/version/cli.js +27 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/package.json +14 -2
- package/dist/commands/dependencies/__tests__/helpers/context.d.ts +0 -12
- package/dist/commands/dependencies/__tests__/helpers/context.js +0 -31
- package/dist/commands/dependencies/__tests__/helpers/stream.d.ts +0 -2
- package/dist/commands/dependencies/__tests__/helpers/stream.js +0 -24
- package/dist/commands/dependencies/__tests__/helpers/upload.run.d.ts +0 -13
- package/dist/commands/dependencies/__tests__/helpers/upload.run.js +0 -40
- package/dist/commands/dependencies/__tests__/upload.test.js +0 -264
- package/dist/commands/dependencies/api.d.ts +0 -2
- package/dist/commands/dependencies/api.js +0 -27
- package/dist/commands/dependencies/cli.js +0 -4
- package/dist/commands/dependencies/interfaces.d.ts +0 -10
- package/dist/commands/dependencies/interfaces.js +0 -2
- package/dist/commands/dependencies/renderer.d.ts +0 -13
- package/dist/commands/dependencies/renderer.js +0 -57
- package/dist/commands/dependencies/upload.d.ts +0 -16
- package/dist/commands/dependencies/upload.js +0 -171
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -30,6 +30,7 @@ inquirer,import,MIT,Copyright (c) 2012 Simon Boudrias
|
|
|
30
30
|
jest,dev,MIT,Copyright (c) Facebook, Inc. and its affiliates.
|
|
31
31
|
jest-environment-node,dev,MIT,Copyright (c) Facebook, Inc. and its affiliates.
|
|
32
32
|
jest-matcher-specific-error,dev,MIT,Copyright (c) 2020 Daniel Hreben
|
|
33
|
+
pkg,dev,MIT,Copyright (c) 2021 Vercel, Inc.
|
|
33
34
|
prettier,dev,MIT,Copyright © James Long and contributors
|
|
34
35
|
proxy,dev,MIT,Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
|
|
35
36
|
proxy-agent,import,MIT,Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
|
package/README.md
CHANGED
|
@@ -29,13 +29,40 @@ npm install -g @datadog/datadog-ci
|
|
|
29
29
|
yarn global add @datadog/datadog-ci
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
### Standalone binary (**beta**)
|
|
33
|
+
|
|
34
|
+
If installing nodejs in the CI is an issue, standalone binaries are provided with [releases](https://github.com/DataDog/datadog-ci/releases). Only _linux-x64_, _darwin-x64_ (macOS) and _win-x64_ (Windows) are supported at the time. **These standalone binaries are in _beta_ and their stability is not guaranteed**. To install:
|
|
35
|
+
|
|
36
|
+
#### Linux
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" && chmod +x /usr/local/bin/datadog-ci
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### MacOS
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_darwin-x64" --output "/usr/local/bin/datadog-ci" && chmod +x /usr/local/bin/datadog-ci
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### Windows
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
Invoke-WebRequest -Uri "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_win-x64.exe" -OutFile "datadog-ci.exe"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then you can run `datadog-ci` commands normally:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
datadog-ci version
|
|
58
|
+
```
|
|
59
|
+
|
|
32
60
|
## Usage
|
|
33
61
|
|
|
34
62
|
```bash
|
|
35
63
|
Usage: datadog-ci <command> <subcommand> [options]
|
|
36
64
|
|
|
37
65
|
Available commands:
|
|
38
|
-
- dependencies
|
|
39
66
|
- lambda
|
|
40
67
|
- sourcemaps
|
|
41
68
|
- synthetics
|
|
@@ -49,7 +76,6 @@ Each command allows interacting with a product of the Datadog platform. The comm
|
|
|
49
76
|
|
|
50
77
|
Further documentation for each command can be found in its folder, ie:
|
|
51
78
|
|
|
52
|
-
- [Dependencies](src/commands/dependencies)
|
|
53
79
|
- [Lambda](src/commands/lambda)
|
|
54
80
|
- [Sourcemaps](src/commands/sourcemaps/)
|
|
55
81
|
- [Synthetics CI/CD Testing](src/commands/synthetics/)
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
2
21
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
22
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
23
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -9,6 +28,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
28
|
});
|
|
10
29
|
};
|
|
11
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
const simpleGit = __importStar(require("simple-git"));
|
|
12
32
|
const git_1 = require("../git");
|
|
13
33
|
const createMockSimpleGit = (conf) => ({
|
|
14
34
|
getRemotes: (_) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -84,7 +104,7 @@ describe('git', () => {
|
|
|
84
104
|
remotes: [{ name: 'first', refs: { push: 'https://git-repo' } }],
|
|
85
105
|
trackedFiles: ['myfile.js'],
|
|
86
106
|
});
|
|
87
|
-
const commitInfo = yield git_1.getCommitInfo(mock
|
|
107
|
+
const commitInfo = yield git_1.getCommitInfo(mock);
|
|
88
108
|
expect(commitInfo).toBeDefined();
|
|
89
109
|
expect(commitInfo.hash).toBe('abcd');
|
|
90
110
|
expect(commitInfo.trackedFiles).toStrictEqual(['myfile.js']);
|
|
@@ -95,11 +115,33 @@ describe('git', () => {
|
|
|
95
115
|
hash: 'abcd',
|
|
96
116
|
trackedFiles: ['myfile.js'],
|
|
97
117
|
});
|
|
98
|
-
const commitInfo = yield git_1.getCommitInfo(mock,
|
|
118
|
+
const commitInfo = yield git_1.getCommitInfo(mock, 'https://overridden');
|
|
99
119
|
expect(commitInfo).toBeDefined();
|
|
100
120
|
expect(commitInfo.hash).toBe('abcd');
|
|
101
121
|
expect(commitInfo.trackedFiles).toStrictEqual(['myfile.js']);
|
|
102
122
|
expect(commitInfo.remote).toBe('https://overridden');
|
|
103
123
|
}));
|
|
104
124
|
});
|
|
125
|
+
describe('newSimpleGit', () => {
|
|
126
|
+
test('should throw an error if git is not installed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
127
|
+
jest.spyOn(simpleGit, 'gitP').mockImplementation(() => {
|
|
128
|
+
throw Error('gitp error');
|
|
129
|
+
});
|
|
130
|
+
yield expect(git_1.newSimpleGit()).rejects.toThrow('gitp error');
|
|
131
|
+
}));
|
|
132
|
+
test('should throw an error if revparse throws an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
133
|
+
const mock = createMockSimpleGit({});
|
|
134
|
+
jest.spyOn(simpleGit, 'gitP').mockReturnValue(mock);
|
|
135
|
+
jest.spyOn(mock, 'revparse').mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
throw Error('revparse error');
|
|
137
|
+
}));
|
|
138
|
+
yield expect(git_1.newSimpleGit()).rejects.toThrow('revparse error');
|
|
139
|
+
}));
|
|
140
|
+
test('should not throw any errors', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
+
const mock = createMockSimpleGit({});
|
|
142
|
+
jest.spyOn(simpleGit, 'gitP').mockReturnValue(mock);
|
|
143
|
+
jest.spyOn(mock, 'revparse').mockResolvedValue('1234');
|
|
144
|
+
yield expect(git_1.newSimpleGit()).resolves.not.toThrow();
|
|
145
|
+
}));
|
|
146
|
+
});
|
|
105
147
|
});
|
|
File without changes
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
const apikey = __importStar(require("../../../helpers/apikey"));
|
|
32
|
+
const upload = __importStar(require("../../../helpers/upload"));
|
|
33
|
+
const git = __importStar(require("../git"));
|
|
34
|
+
const interfaces_1 = require("../interfaces");
|
|
35
|
+
const library_1 = require("../library");
|
|
36
|
+
describe('library', () => {
|
|
37
|
+
describe('isGitRepo', () => {
|
|
38
|
+
test('should return false if checkIsRepo fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const simpleGitClient = {
|
|
40
|
+
checkIsRepo: () => {
|
|
41
|
+
throw Error();
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
jest.spyOn(git, 'newSimpleGit').mockResolvedValue(simpleGitClient);
|
|
45
|
+
yield expect(library_1.isGitRepo()).resolves.toEqual(false);
|
|
46
|
+
}));
|
|
47
|
+
test('should return false git is not installed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
jest.spyOn(git, 'newSimpleGit').mockImplementation(() => {
|
|
49
|
+
throw new Error('git is not installed');
|
|
50
|
+
});
|
|
51
|
+
yield expect(library_1.isGitRepo()).resolves.toEqual(false);
|
|
52
|
+
}));
|
|
53
|
+
test('should return true if datadog API key is set, git is installed, and we are in a repo', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
const simpleGitClient = { checkIsRepo: () => true };
|
|
55
|
+
jest.spyOn(git, 'newSimpleGit').mockResolvedValue(simpleGitClient);
|
|
56
|
+
yield expect(library_1.isGitRepo()).resolves.toEqual(true);
|
|
57
|
+
}));
|
|
58
|
+
});
|
|
59
|
+
describe('addSourceCodeIntegration', () => {
|
|
60
|
+
test('source code integration fails if simpleGitOrFail throws an exception', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
+
jest.spyOn(git, 'newSimpleGit').mockImplementation(() => {
|
|
62
|
+
throw new Error('git is not installed');
|
|
63
|
+
});
|
|
64
|
+
jest.spyOn(apikey, 'newApiKeyValidator').mockReturnValue({});
|
|
65
|
+
yield expect(library_1.uploadGitCommitHash('dummy', 'fake.site')).rejects.toThrowError('git is not installed');
|
|
66
|
+
}));
|
|
67
|
+
test('source code integration returns the correct hash', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
|
+
const simpleGitClient = { checkIsRepo: () => true };
|
|
69
|
+
jest.spyOn(git, 'newSimpleGit').mockResolvedValue(simpleGitClient);
|
|
70
|
+
jest.spyOn(git, 'getCommitInfo').mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () { return new interfaces_1.CommitInfo('hash', 'url', ['file1', 'file2']); }));
|
|
71
|
+
jest.spyOn(upload, 'upload').mockReturnValue((a, b) => {
|
|
72
|
+
{
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
resolve(upload.UploadStatus.Success);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
jest.spyOn(apikey, 'newApiKeyValidator').mockReturnValue({});
|
|
79
|
+
expect(yield library_1.uploadGitCommitHash('dummy', 'fake.site')).toBe('hash');
|
|
80
|
+
}));
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as simpleGit from 'simple-git';
|
|
2
|
-
import { Writable } from 'stream';
|
|
3
2
|
import { CommitInfo } from './interfaces';
|
|
4
3
|
export declare const newSimpleGit: () => Promise<simpleGit.SimpleGit>;
|
|
5
4
|
export declare const gitRemote: (git: simpleGit.SimpleGit) => Promise<string>;
|
|
6
5
|
export declare const stripCredentials: (remote: string) => string;
|
|
7
6
|
export declare const gitTrackedFiles: (git: simpleGit.SimpleGit) => Promise<string[]>;
|
|
8
|
-
export declare const getCommitInfo: (git: simpleGit.SimpleGit,
|
|
7
|
+
export declare const getCommitInfo: (git: simpleGit.SimpleGit, repositoryURL?: string | undefined) => Promise<CommitInfo>;
|
|
@@ -31,7 +31,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
31
31
|
exports.getCommitInfo = exports.gitTrackedFiles = exports.stripCredentials = exports.gitRemote = exports.newSimpleGit = void 0;
|
|
32
32
|
const simpleGit = __importStar(require("simple-git"));
|
|
33
33
|
const url_1 = require("url");
|
|
34
|
-
const renderer_1 = require("./renderer");
|
|
35
34
|
const interfaces_1 = require("./interfaces");
|
|
36
35
|
// Returns a configured SimpleGit.
|
|
37
36
|
const newSimpleGit = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -40,16 +39,11 @@ const newSimpleGit = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
40
39
|
binary: 'git',
|
|
41
40
|
maxConcurrentProcesses: 1,
|
|
42
41
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
options.baseDir = root;
|
|
49
|
-
}
|
|
50
|
-
catch (_a) {
|
|
51
|
-
// Ignore exception as it will fail if we are not inside a git repository.
|
|
52
|
-
}
|
|
42
|
+
// Attempt to set the baseDir to the root of the repository so the 'git ls-files' command
|
|
43
|
+
// returns the tracked files paths relative to the root of the repository.
|
|
44
|
+
const git = simpleGit.gitP(options);
|
|
45
|
+
const root = yield git.revparse('--show-toplevel');
|
|
46
|
+
options.baseDir = root;
|
|
53
47
|
return simpleGit.gitP(options);
|
|
54
48
|
});
|
|
55
49
|
exports.newSimpleGit = newSimpleGit;
|
|
@@ -91,27 +85,21 @@ const gitTrackedFiles = (git) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
91
85
|
});
|
|
92
86
|
exports.gitTrackedFiles = gitTrackedFiles;
|
|
93
87
|
// Returns the current hash, remote URL and tracked files paths.
|
|
94
|
-
const getCommitInfo = (git,
|
|
88
|
+
const getCommitInfo = (git, repositoryURL) => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
89
|
// Invoke git commands to retrieve the remote, hash and tracked files.
|
|
96
90
|
// We're using Promise.all instead of Promive.allSettled since we want to fail early if
|
|
97
91
|
// any of the promises fails.
|
|
98
92
|
let remote;
|
|
99
93
|
let hash;
|
|
100
94
|
let trackedFiles;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
remote = repositoryURL;
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
;
|
|
109
|
-
[remote, hash, trackedFiles] = yield Promise.all([exports.gitRemote(git), gitHash(git), exports.gitTrackedFiles(git)]);
|
|
110
|
-
}
|
|
95
|
+
if (repositoryURL) {
|
|
96
|
+
;
|
|
97
|
+
[hash, trackedFiles] = yield Promise.all([gitHash(git), exports.gitTrackedFiles(git)]);
|
|
98
|
+
remote = repositoryURL;
|
|
111
99
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
100
|
+
else {
|
|
101
|
+
;
|
|
102
|
+
[remote, hash, trackedFiles] = yield Promise.all([exports.gitRemote(git), gitHash(git), exports.gitTrackedFiles(git)]);
|
|
115
103
|
}
|
|
116
104
|
return new interfaces_1.CommitInfo(hash, remote, trackedFiles);
|
|
117
105
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './library';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
__exportStar(require("./library"), exports);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { RequestBuilder } from '../../helpers/interfaces';
|
|
2
|
+
import { UploadOptions, UploadStatus } from '../../helpers/upload';
|
|
3
|
+
import { CommitInfo } from './interfaces';
|
|
4
|
+
export declare const isGitRepo: () => Promise<boolean>;
|
|
5
|
+
export declare const uploadGitCommitHash: (apiKey: string, datadogSite: string) => Promise<string>;
|
|
6
|
+
export declare const uploadRepository: (requestBuilder: RequestBuilder, libraryVersion: string) => (commitInfo: CommitInfo, opts: UploadOptions) => Promise<UploadStatus>;
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
exports.uploadRepository = exports.uploadGitCommitHash = exports.isGitRepo = void 0;
|
|
13
|
+
const apikey_1 = require("../../helpers/apikey");
|
|
14
|
+
const upload_1 = require("../../helpers/upload");
|
|
15
|
+
const utils_1 = require("../../helpers/utils");
|
|
16
|
+
const git_1 = require("./git");
|
|
17
|
+
const isGitRepo = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
|
+
try {
|
|
19
|
+
const simpleGit = yield git_1.newSimpleGit();
|
|
20
|
+
const isRepo = simpleGit.checkIsRepo();
|
|
21
|
+
return isRepo;
|
|
22
|
+
}
|
|
23
|
+
catch (_a) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
exports.isGitRepo = isGitRepo;
|
|
28
|
+
const uploadGitCommitHash = (apiKey, datadogSite) => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
const apiKeyValidator = apikey_1.newApiKeyValidator({
|
|
30
|
+
apiKey,
|
|
31
|
+
datadogSite,
|
|
32
|
+
});
|
|
33
|
+
const simpleGit = yield git_1.newSimpleGit();
|
|
34
|
+
const payload = yield git_1.getCommitInfo(simpleGit);
|
|
35
|
+
const version = require('../../../package.json').version;
|
|
36
|
+
const requestBuilder = utils_1.getRequestBuilder({
|
|
37
|
+
apiKey,
|
|
38
|
+
baseUrl: 'https://sourcemap-intake.' + datadogSite,
|
|
39
|
+
headers: new Map([
|
|
40
|
+
['DD-EVP-ORIGIN', 'datadog-ci sci'],
|
|
41
|
+
['DD-EVP-ORIGIN-VERSION', version],
|
|
42
|
+
]),
|
|
43
|
+
overrideUrl: 'api/v2/srcmap',
|
|
44
|
+
});
|
|
45
|
+
const status = yield exports.uploadRepository(requestBuilder, version)(payload, {
|
|
46
|
+
apiKeyValidator,
|
|
47
|
+
onError: (e) => {
|
|
48
|
+
throw e;
|
|
49
|
+
},
|
|
50
|
+
onRetry: () => {
|
|
51
|
+
// Do nothing
|
|
52
|
+
},
|
|
53
|
+
onUpload: () => {
|
|
54
|
+
return;
|
|
55
|
+
},
|
|
56
|
+
retries: 5,
|
|
57
|
+
});
|
|
58
|
+
if (status !== upload_1.UploadStatus.Success) {
|
|
59
|
+
throw new Error('Error uploading commit information.');
|
|
60
|
+
}
|
|
61
|
+
return payload.hash;
|
|
62
|
+
});
|
|
63
|
+
exports.uploadGitCommitHash = uploadGitCommitHash;
|
|
64
|
+
const uploadRepository = (requestBuilder, libraryVersion) => (commitInfo, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
+
const payload = commitInfo.asMultipartPayload(libraryVersion);
|
|
66
|
+
return upload_1.upload(requestBuilder)(payload, opts);
|
|
67
|
+
});
|
|
68
|
+
exports.uploadRepository = uploadRepository;
|
|
@@ -23,6 +23,7 @@ const upload_1 = require("../../helpers/upload");
|
|
|
23
23
|
const utils_1 = require("../../helpers/utils");
|
|
24
24
|
const api_1 = require("./api");
|
|
25
25
|
const git_1 = require("./git");
|
|
26
|
+
const library_1 = require("./library");
|
|
26
27
|
const renderer_1 = require("./renderer");
|
|
27
28
|
class UploadCommand extends clipanion_1.Command {
|
|
28
29
|
constructor() {
|
|
@@ -49,28 +50,40 @@ class UploadCommand extends clipanion_1.Command {
|
|
|
49
50
|
datadogSite: api_1.datadogSite,
|
|
50
51
|
metricsLogger: metricsLogger.logger,
|
|
51
52
|
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
let payload;
|
|
54
|
+
try {
|
|
55
|
+
payload = yield git_1.getCommitInfo(yield git_1.newSimpleGit(), this.repositoryURL);
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
if (e instanceof Error) {
|
|
59
|
+
this.context.stdout.write(renderer_1.renderFailedUpload(e.message));
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
55
62
|
}
|
|
56
63
|
this.context.stdout.write(renderer_1.renderCommandInfo(payload));
|
|
64
|
+
let status;
|
|
57
65
|
try {
|
|
58
66
|
const requestBuilder = this.getRequestBuilder();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
if (this.dryRun) {
|
|
68
|
+
status = upload_1.UploadStatus.Success;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
status = yield library_1.uploadRepository(requestBuilder, this.cliVersion)(payload, {
|
|
72
|
+
apiKeyValidator,
|
|
73
|
+
onError: (e) => {
|
|
74
|
+
this.context.stdout.write(renderer_1.renderFailedUpload(e.message));
|
|
75
|
+
metricsLogger.logger.increment('failed', 1);
|
|
76
|
+
},
|
|
77
|
+
onRetry: (e, attempt) => {
|
|
78
|
+
this.context.stdout.write(renderer_1.renderRetriedUpload(e.message, attempt));
|
|
79
|
+
metricsLogger.logger.increment('retries', 1);
|
|
80
|
+
},
|
|
81
|
+
onUpload: () => {
|
|
82
|
+
return;
|
|
83
|
+
},
|
|
84
|
+
retries: 5,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
74
87
|
metricsLogger.logger.increment('success', 1);
|
|
75
88
|
const totalTime = (Date.now() - initialTime) / 1000;
|
|
76
89
|
if (status !== upload_1.UploadStatus.Success) {
|
|
@@ -113,15 +126,6 @@ class UploadCommand extends clipanion_1.Command {
|
|
|
113
126
|
overrideUrl: 'api/v2/srcmap',
|
|
114
127
|
});
|
|
115
128
|
}
|
|
116
|
-
uploadRepository(requestBuilder) {
|
|
117
|
-
return (commitInfo, opts) => __awaiter(this, void 0, void 0, function* () {
|
|
118
|
-
const payload = commitInfo.asMultipartPayload(this.cliVersion);
|
|
119
|
-
if (this.dryRun) {
|
|
120
|
-
return upload_1.UploadStatus.Success;
|
|
121
|
-
}
|
|
122
|
-
return upload_1.upload(requestBuilder)(payload, opts);
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
129
|
}
|
|
126
130
|
exports.UploadCommand = UploadCommand;
|
|
127
131
|
UploadCommand.usage = clipanion_1.Command.Usage({
|
|
@@ -741,7 +741,7 @@ describe('instrument', () => {
|
|
|
741
741
|
test('fails when retry count is exceeded', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
742
742
|
const makeMockLambdaListFunctionsError = () => ({
|
|
743
743
|
listFunctions: jest.fn().mockImplementation((args) => ({
|
|
744
|
-
promise: () => Promise.reject(),
|
|
744
|
+
promise: () => Promise.reject('ListFunctionsError'),
|
|
745
745
|
})),
|
|
746
746
|
});
|
|
747
747
|
const lambda = makeMockLambdaListFunctionsError();
|
|
@@ -753,7 +753,7 @@ describe('instrument', () => {
|
|
|
753
753
|
mergeXrayTraces: false,
|
|
754
754
|
tracingEnabled: false,
|
|
755
755
|
};
|
|
756
|
-
yield expect(instrument_1.getInstrumentedFunctionConfigsFromRegEx(lambda, cloudWatch, 'us-east-1', 'fake-pattern', settings)).rejects.toStrictEqual(new Error('Max retry count exceeded.'));
|
|
756
|
+
yield expect(instrument_1.getInstrumentedFunctionConfigsFromRegEx(lambda, cloudWatch, 'us-east-1', 'fake-pattern', settings)).rejects.toStrictEqual(new Error('Max retry count exceeded. ListFunctionsError'));
|
|
757
757
|
}));
|
|
758
758
|
});
|
|
759
759
|
});
|
|
@@ -394,12 +394,12 @@ describe('uninstrument', () => {
|
|
|
394
394
|
test('fails when retry count is exceeded', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
395
395
|
const makeMockLambdaListFunctionsError = () => ({
|
|
396
396
|
listFunctions: jest.fn().mockImplementation((args) => ({
|
|
397
|
-
promise: () => Promise.reject(),
|
|
397
|
+
promise: () => Promise.reject('ListFunctionsError'),
|
|
398
398
|
})),
|
|
399
399
|
});
|
|
400
400
|
const lambda = makeMockLambdaListFunctionsError();
|
|
401
401
|
const cloudWatch = fixtures_1.makeMockCloudWatchLogs({});
|
|
402
|
-
yield expect(uninstrument_1.getUninstrumentedFunctionConfigsFromRegEx(lambda, cloudWatch, 'fake-pattern', undefined)).rejects.toStrictEqual(new Error('Max retry count exceeded.'));
|
|
402
|
+
yield expect(uninstrument_1.getUninstrumentedFunctionConfigsFromRegEx(lambda, cloudWatch, 'fake-pattern', undefined)).rejects.toStrictEqual(new Error('Max retry count exceeded. ListFunctionsError'));
|
|
403
403
|
}));
|
|
404
404
|
});
|
|
405
405
|
});
|
|
@@ -369,7 +369,7 @@ TagResource -> arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world
|
|
|
369
369
|
'0.1',
|
|
370
370
|
], context);
|
|
371
371
|
const output = context.stdout.toString();
|
|
372
|
-
expect(output).toMatch(/.*
|
|
372
|
+
expect(output.replace('\n', '')).toMatch(/.*Error: Couldn't get local git status.*/);
|
|
373
373
|
}));
|
|
374
374
|
test('instrumenting with source code integrations fails if DATADOG_API_KEY is not provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
375
375
|
;
|
|
@@ -853,7 +853,8 @@ TagResource -> arn:aws:lambda:us-east-1:123456789012:function:lambda-hello-world
|
|
|
853
853
|
const output = context.stdout.toString();
|
|
854
854
|
expect(code).toBe(0);
|
|
855
855
|
expect(output).toMatchInlineSnapshot(`
|
|
856
|
-
"${chalk_1.bold(chalk_1.yellow('[!]'))} No
|
|
856
|
+
"${chalk_1.bold(chalk_1.yellow('[!]'))} No AWS credentials found, let's set them up! Or you can re-run the command and supply the AWS credentials in the same way when you invoke the AWS CLI.
|
|
857
|
+
${chalk_1.bold(chalk_1.yellow('[!]'))} Configure AWS region.
|
|
857
858
|
${chalk_1.bold(chalk_1.yellow('[!]'))} Configure Datadog settings.
|
|
858
859
|
Fetching Lambda functions, this might take a while.
|
|
859
860
|
${chalk_1.bold(chalk_1.yellow('[Warning]'))} The environment, service and version tags have not been configured. Learn more about Datadog unified service tagging: ${chalk_1.underline(chalk_1.blueBright('https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging/#serverless-environment.'))}
|
|
@@ -974,7 +975,8 @@ ${chalk_1.yellow('[!]')} Instrumenting functions.
|
|
|
974
975
|
const output = context.stdout.toString();
|
|
975
976
|
expect(code).toBe(0);
|
|
976
977
|
expect(output).toMatchInlineSnapshot(`
|
|
977
|
-
"${chalk_1.bold(chalk_1.yellow('[!]'))} No
|
|
978
|
+
"${chalk_1.bold(chalk_1.yellow('[!]'))} No AWS credentials found, let's set them up! Or you can re-run the command and supply the AWS credentials in the same way when you invoke the AWS CLI.
|
|
979
|
+
${chalk_1.bold(chalk_1.yellow('[!]'))} Configure AWS region.
|
|
978
980
|
${chalk_1.bold(chalk_1.yellow('[!]'))} Configure Datadog settings.
|
|
979
981
|
${chalk_1.bold(chalk_1.yellow('[Warning]'))} The environment, service and version tags have not been configured. Learn more about Datadog unified service tagging: ${chalk_1.underline(chalk_1.blueBright('https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging/#serverless-environment.'))}
|
|
980
982
|
${chalk_1.bold(chalk_1.yellow('[Warning]'))} Instrument your ${chalk_1.hex('#FF9900').bold('Lambda')} functions in a dev or staging environment first. Should the instrumentation result be unsatisfactory, run \`${chalk_1.bold('uninstrument')}\` with the same arguments to revert the changes.\n
|
|
@@ -1047,7 +1049,7 @@ ${chalk_1.yellow('[!]')} Instrumenting functions.
|
|
|
1047
1049
|
const output = context.stdout.toString();
|
|
1048
1050
|
expect(code).toBe(1);
|
|
1049
1051
|
expect(output).toMatchInlineSnapshot(`
|
|
1050
|
-
"${chalk_1.bold(chalk_1.yellow('[!]'))} No
|
|
1052
|
+
"${chalk_1.bold(chalk_1.yellow('[!]'))} No AWS credentials found, let's set them up! Or you can re-run the command and supply the AWS credentials in the same way when you invoke the AWS CLI.
|
|
1051
1053
|
${chalk_1.red('[Error]')} Unexpected error
|
|
1052
1054
|
"
|
|
1053
1055
|
`);
|
|
@@ -1066,7 +1068,8 @@ ${chalk_1.red('[Error]')} Unexpected error
|
|
|
1066
1068
|
const output = context.stdout.toString();
|
|
1067
1069
|
expect(code).toBe(1);
|
|
1068
1070
|
expect(output).toMatchInlineSnapshot(`
|
|
1069
|
-
"${chalk_1.bold(chalk_1.yellow('[!]'))} Configure
|
|
1071
|
+
"${chalk_1.bold(chalk_1.yellow('[!]'))} Configure AWS region.
|
|
1072
|
+
${chalk_1.bold(chalk_1.yellow('[!]'))} Configure Datadog settings.
|
|
1070
1073
|
${chalk_1.red('[Error]')} Unexpected error
|
|
1071
1074
|
"
|
|
1072
1075
|
`);
|
|
@@ -1087,7 +1090,8 @@ ${chalk_1.red('[Error]')} Unexpected error
|
|
|
1087
1090
|
const output = context.stdout.toString();
|
|
1088
1091
|
expect(code).toBe(1);
|
|
1089
1092
|
expect(output).toMatchInlineSnapshot(`
|
|
1090
|
-
"
|
|
1093
|
+
"${chalk_1.bold(chalk_1.yellow('[!]'))} Configure AWS region.
|
|
1094
|
+
Fetching Lambda functions, this might take a while.
|
|
1091
1095
|
${chalk_1.red('[Error]')} Couldn't find any Lambda functions in the specified region.
|
|
1092
1096
|
"
|
|
1093
1097
|
`);
|
|
@@ -1102,7 +1106,7 @@ ${chalk_1.red('[Error]')} Couldn't find any Lambda functions in the specified re
|
|
|
1102
1106
|
};
|
|
1103
1107
|
fs.readFile.mockImplementation((a, b, callback) => callback({ code: 'ENOENT' }));
|
|
1104
1108
|
aws_sdk_1.Lambda.mockImplementation(() => ({
|
|
1105
|
-
listFunctions: jest.fn().mockImplementation(() => ({ promise: () => Promise.reject('
|
|
1109
|
+
listFunctions: jest.fn().mockImplementation(() => ({ promise: () => Promise.reject('ListFunctionsError') })),
|
|
1106
1110
|
}));
|
|
1107
1111
|
const cli = fixtures_1.makeCli();
|
|
1108
1112
|
const context = fixtures_1.createMockContext();
|
|
@@ -1110,8 +1114,9 @@ ${chalk_1.red('[Error]')} Couldn't find any Lambda functions in the specified re
|
|
|
1110
1114
|
const output = context.stdout.toString();
|
|
1111
1115
|
expect(code).toBe(1);
|
|
1112
1116
|
expect(output).toMatchInlineSnapshot(`
|
|
1113
|
-
"
|
|
1114
|
-
|
|
1117
|
+
"${chalk_1.bold(chalk_1.yellow('[!]'))} Configure AWS region.
|
|
1118
|
+
Fetching Lambda functions, this might take a while.
|
|
1119
|
+
${chalk_1.red('[Error]')} Couldn't fetch Lambda functions. Error: Max retry count exceeded. ListFunctionsError
|
|
1115
1120
|
"
|
|
1116
1121
|
`);
|
|
1117
1122
|
}));
|
|
@@ -80,25 +80,21 @@ describe('prompt', () => {
|
|
|
80
80
|
inquirer_1.prompt.mockImplementation(() => Promise.resolve({
|
|
81
81
|
[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]: fixtures_1.mockAwsAccessKeyId,
|
|
82
82
|
[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]: fixtures_1.mockAwsSecretAccessKey,
|
|
83
|
-
[constants_1.AWS_DEFAULT_REGION_ENV_VAR]: 'sa-east-1',
|
|
84
83
|
}));
|
|
85
84
|
yield prompt_1.requestAWSCredentials();
|
|
86
85
|
expect(process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]).toBe(fixtures_1.mockAwsAccessKeyId);
|
|
87
86
|
expect(process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]).toBe(fixtures_1.mockAwsSecretAccessKey);
|
|
88
|
-
expect(process.env[constants_1.AWS_DEFAULT_REGION_ENV_VAR]).toBe('sa-east-1');
|
|
89
87
|
}));
|
|
90
88
|
test('sets the AWS credentials with session token as environment variables', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
91
89
|
;
|
|
92
90
|
inquirer_1.prompt.mockImplementation(() => Promise.resolve({
|
|
93
91
|
[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]: fixtures_1.mockAwsAccessKeyId,
|
|
94
92
|
[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]: fixtures_1.mockAwsSecretAccessKey,
|
|
95
|
-
[constants_1.AWS_DEFAULT_REGION_ENV_VAR]: 'sa-east-1',
|
|
96
93
|
[constants_1.AWS_SESSION_TOKEN_ENV_VAR]: 'some-session-token',
|
|
97
94
|
}));
|
|
98
95
|
yield prompt_1.requestAWSCredentials();
|
|
99
96
|
expect(process.env[constants_1.AWS_ACCESS_KEY_ID_ENV_VAR]).toBe(fixtures_1.mockAwsAccessKeyId);
|
|
100
97
|
expect(process.env[constants_1.AWS_SECRET_ACCESS_KEY_ENV_VAR]).toBe(fixtures_1.mockAwsSecretAccessKey);
|
|
101
|
-
expect(process.env[constants_1.AWS_DEFAULT_REGION_ENV_VAR]).toBe('sa-east-1');
|
|
102
98
|
expect(process.env[constants_1.AWS_SESSION_TOKEN_ENV_VAR]).toBe('some-session-token');
|
|
103
99
|
}));
|
|
104
100
|
test('throws error when something unexpected happens while prompting', () => __awaiter(void 0, void 0, void 0, function* () {
|