testbeats 2.1.6 → 2.2.1
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/package.json +2 -1
- package/src/beats/beats.attachments.js +0 -1
- package/src/cli.js +25 -4
- package/src/commands/generate-config.command.js +440 -0
- package/src/commands/publish.command.js +15 -0
- package/src/extensions/base.extension.js +4 -1
- package/src/extensions/browserstack.extension.js +30 -0
- package/src/extensions/ci-info.extension.js +5 -10
- package/src/extensions/extensions.d.ts +4 -0
- package/src/extensions/index.js +3 -0
- package/src/helpers/browserstack.helper.js +45 -0
- package/src/helpers/ci/azure-devops.js +37 -0
- package/src/helpers/ci/base.ci.js +134 -0
- package/src/helpers/ci/circle-ci.js +32 -0
- package/src/helpers/ci/github.js +36 -0
- package/src/helpers/ci/gitlab.js +37 -0
- package/src/helpers/ci/index.js +45 -0
- package/src/helpers/ci/jenkins.js +36 -0
- package/src/helpers/constants.js +3 -1
- package/src/helpers/helper.js +2 -9
- package/src/index.d.ts +46 -2
- package/src/index.js +8 -1
- package/src/setups/extensions.setup.js +62 -0
- package/src/helpers/ci.js +0 -140
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const request = require('phin-retry');
|
|
2
|
+
const { URLS } = require('./constants');
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {import('../index').BrowserstackInputs} inputs
|
|
8
|
+
*/
|
|
9
|
+
function getBaseUrl(inputs) {
|
|
10
|
+
return inputs.url || URLS.BROWSERSTACK;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param {import('../index').BrowserstackInputs} inputs
|
|
16
|
+
*/
|
|
17
|
+
async function getAutomationBuilds(inputs) {
|
|
18
|
+
return request.get({
|
|
19
|
+
url: `${getBaseUrl(inputs)}/automate/builds.json?limit=100`,
|
|
20
|
+
auth: {
|
|
21
|
+
username: inputs.username,
|
|
22
|
+
password: inputs.password
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {import('../index').BrowserstackInputs} inputs
|
|
30
|
+
* @param {string} build_id
|
|
31
|
+
*/
|
|
32
|
+
async function getAutomationBuildSessions(inputs, build_id) {
|
|
33
|
+
return request.get({
|
|
34
|
+
url: `${getBaseUrl(inputs)}/automate/builds/${build_id}/sessions.json`,
|
|
35
|
+
auth: {
|
|
36
|
+
username: inputs.username,
|
|
37
|
+
password: inputs.password
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
getAutomationBuilds,
|
|
44
|
+
getAutomationBuildSessions
|
|
45
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const { BaseCI } = require('./base.ci');
|
|
2
|
+
|
|
3
|
+
const ENV = process.env;
|
|
4
|
+
|
|
5
|
+
class AzureDevOpsCI extends BaseCI {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.init();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
init() {
|
|
12
|
+
this.setInfo(this.targets.ci, 'AZURE_DEVOPS_PIPELINES');
|
|
13
|
+
this.setInfo(this.targets.git, 'AZURE_DEVOPS_REPOS');
|
|
14
|
+
this.setInfo(this.targets.repository_url, ENV.BUILD_REPOSITORY_URI);
|
|
15
|
+
this.setInfo(this.targets.repository_name, ENV.BUILD_REPOSITORY_NAME);
|
|
16
|
+
this.setInfo(this.targets.repository_ref, ENV.BUILD_SOURCEBRANCH);
|
|
17
|
+
this.setInfo(this.targets.repository_commit_sha, ENV.BUILD_SOURCEVERSION);
|
|
18
|
+
this.setInfo(this.targets.build_url, ENV.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI + ENV.SYSTEM_TEAMPROJECT + '/_build/results?buildId=' + ENV.BUILD_BUILDID);
|
|
19
|
+
this.setInfo(this.targets.build_number, ENV.BUILD_BUILDNUMBER);
|
|
20
|
+
this.setInfo(this.targets.build_name, ENV.BUILD_DEFINITIONNAME);
|
|
21
|
+
this.setInfo(this.targets.build_reason, ENV.BUILD_REASON);
|
|
22
|
+
|
|
23
|
+
this.setInfo(this.targets.branch_url, this.repository_url + this.repository_ref.replace('refs/heads/', '/tree/'));
|
|
24
|
+
this.setInfo(this.targets.branch_name, this.repository_ref.replace('refs/heads/', ''));
|
|
25
|
+
|
|
26
|
+
if (this.repository_ref.includes('refs/pull')) {
|
|
27
|
+
this.setInfo(this.targets.pull_request_url, this.repository_url + this.repository_ref.replace('refs/pull/', '/pull/'));
|
|
28
|
+
this.setInfo(this.targets.pull_request_name, this.repository_ref.replace('refs/pull/', '').replace('/merge', ''));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.setInfo(this.targets.user, ENV.BUILD_REQUESTEDFOR, true);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
AzureDevOpsCI
|
|
37
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const pkg = require('../../../package.json');
|
|
3
|
+
|
|
4
|
+
const ENV = process.env;
|
|
5
|
+
|
|
6
|
+
class BaseCI {
|
|
7
|
+
ci = '';
|
|
8
|
+
git = '';
|
|
9
|
+
repository_url = '';
|
|
10
|
+
repository_name = '';
|
|
11
|
+
repository_ref = '';
|
|
12
|
+
repository_commit_sha = '';
|
|
13
|
+
branch_url = '';
|
|
14
|
+
branch_name = '';
|
|
15
|
+
pull_request_url = '';
|
|
16
|
+
pull_request_name = '';
|
|
17
|
+
build_url = '';
|
|
18
|
+
build_number = '';
|
|
19
|
+
build_name = '';
|
|
20
|
+
build_reason = '';
|
|
21
|
+
user = '';
|
|
22
|
+
runtime = '';
|
|
23
|
+
runtime_version = '';
|
|
24
|
+
os = '';
|
|
25
|
+
os_version = '';
|
|
26
|
+
testbeats_version = '';
|
|
27
|
+
|
|
28
|
+
targets = {
|
|
29
|
+
ci: 'ci',
|
|
30
|
+
git: 'git',
|
|
31
|
+
repository_url: 'repository_url',
|
|
32
|
+
repository_name: 'repository_name',
|
|
33
|
+
repository_ref: 'repository_ref',
|
|
34
|
+
repository_commit_sha: 'repository_commit_sha',
|
|
35
|
+
branch_url: 'branch_url',
|
|
36
|
+
branch_name: 'branch_name',
|
|
37
|
+
pull_request_url: 'pull_request_url',
|
|
38
|
+
pull_request_name: 'pull_request_name',
|
|
39
|
+
build_url: 'build_url',
|
|
40
|
+
build_number: 'build_number',
|
|
41
|
+
build_name: 'build_name',
|
|
42
|
+
build_reason: 'build_reason',
|
|
43
|
+
user: 'user',
|
|
44
|
+
runtime: 'runtime',
|
|
45
|
+
runtime_version: 'runtime_version',
|
|
46
|
+
os: 'os',
|
|
47
|
+
os_version: 'os_version',
|
|
48
|
+
testbeats_version: 'testbeats_version'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
constructor() {
|
|
52
|
+
this.setDefaultInformation();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setDefaultInformation() {
|
|
56
|
+
this.ci = ENV.TEST_BEATS_CI_NAME;
|
|
57
|
+
this.git = ENV.TEST_BEATS_CI_GIT;
|
|
58
|
+
this.repository_url = ENV.TEST_BEATS_CI_REPOSITORY_URL;
|
|
59
|
+
this.repository_name = ENV.TEST_BEATS_CI_REPOSITORY_NAME;
|
|
60
|
+
this.repository_ref = ENV.TEST_BEATS_CI_REPOSITORY_REF;
|
|
61
|
+
this.repository_commit_sha = ENV.TEST_BEATS_CI_REPOSITORY_COMMIT_SHA;
|
|
62
|
+
this.branch_url = ENV.TEST_BEATS_BRANCH_URL;
|
|
63
|
+
this.branch_name = ENV.TEST_BEATS_BRANCH_NAME;
|
|
64
|
+
this.pull_request_url = ENV.TEST_BEATS_PULL_REQUEST_URL;
|
|
65
|
+
this.pull_request_name = ENV.TEST_BEATS_PULL_REQUEST_NAME;
|
|
66
|
+
this.build_url = ENV.TEST_BEATS_CI_BUILD_URL;
|
|
67
|
+
this.build_number = ENV.TEST_BEATS_CI_BUILD_NUMBER;
|
|
68
|
+
this.build_name = ENV.TEST_BEATS_CI_BUILD_NAME;
|
|
69
|
+
this.build_reason = ENV.TEST_BEATS_CI_BUILD_REASON;
|
|
70
|
+
this.user = ENV.TEST_BEATS_CI_USER || os.userInfo().username;
|
|
71
|
+
|
|
72
|
+
const runtime = this.#getRuntimeInfo();
|
|
73
|
+
this.runtime = runtime.name;
|
|
74
|
+
this.runtime_version = runtime.version;
|
|
75
|
+
this.os = os.platform();
|
|
76
|
+
this.os_version = os.release();
|
|
77
|
+
this.testbeats_version = pkg.version;
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#getRuntimeInfo() {
|
|
82
|
+
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
|
|
83
|
+
return { name: 'node', version: process.versions.node };
|
|
84
|
+
} else if (typeof Deno !== 'undefined') {
|
|
85
|
+
return { name: 'deno', version: Deno.version.deno };
|
|
86
|
+
} else if (typeof Bun !== 'undefined') {
|
|
87
|
+
return { name: 'bun', version: Bun.version };
|
|
88
|
+
} else {
|
|
89
|
+
return { name: 'unknown', version: 'unknown' };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
setInfo(target, value, force = false) {
|
|
94
|
+
if (force && value) {
|
|
95
|
+
this[target] = value;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!this[target]) {
|
|
99
|
+
this[target] = value;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @returns {import('../../extensions/extensions').ICIInfo}
|
|
106
|
+
*/
|
|
107
|
+
info() {
|
|
108
|
+
return {
|
|
109
|
+
ci: this.ci,
|
|
110
|
+
git: this.git,
|
|
111
|
+
repository_url: this.repository_url,
|
|
112
|
+
repository_name: this.repository_name,
|
|
113
|
+
repository_ref: this.repository_ref,
|
|
114
|
+
repository_commit_sha: this.repository_commit_sha,
|
|
115
|
+
branch_url: this.branch_url,
|
|
116
|
+
branch_name: this.branch_name,
|
|
117
|
+
pull_request_url: this.pull_request_url,
|
|
118
|
+
pull_request_name: this.pull_request_name,
|
|
119
|
+
build_url: this.build_url,
|
|
120
|
+
build_number: this.build_number,
|
|
121
|
+
build_name: this.build_name,
|
|
122
|
+
build_reason: this.build_reason,
|
|
123
|
+
user: this.user,
|
|
124
|
+
runtime: this.runtime,
|
|
125
|
+
runtime_version: this.runtime_version,
|
|
126
|
+
os: this.os,
|
|
127
|
+
os_version: this.os_version,
|
|
128
|
+
testbeats_version: this.testbeats_version
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
module.exports = { BaseCI };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const { BaseCI } = require('./base.ci');
|
|
2
|
+
|
|
3
|
+
const ENV = process.env;
|
|
4
|
+
|
|
5
|
+
class CircleCI extends BaseCI {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.init();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
init() {
|
|
12
|
+
this.setInfo(this.targets.ci, 'CIRCLE_CI');
|
|
13
|
+
this.setInfo(this.targets.git, '');
|
|
14
|
+
this.setInfo(this.targets.repository_url, ENV.CIRCLE_REPOSITORY_URL);
|
|
15
|
+
this.setInfo(this.targets.repository_name, ENV.CIRCLE_PROJECT_REPONAME);
|
|
16
|
+
this.setInfo(this.targets.repository_ref, ENV.CIRCLE_BRANCH);
|
|
17
|
+
this.setInfo(this.targets.repository_commit_sha, ENV.CIRCLE_SHA1);
|
|
18
|
+
this.setInfo(this.targets.branch_url, '');
|
|
19
|
+
this.setInfo(this.targets.branch_name, ENV.CIRCLE_BRANCH);
|
|
20
|
+
this.setInfo(this.targets.pull_request_url,'');
|
|
21
|
+
this.setInfo(this.targets.pull_request_name, '');
|
|
22
|
+
this.setInfo(this.targets.build_url, ENV.CIRCLE_BUILD_URL);
|
|
23
|
+
this.setInfo(this.targets.build_number, ENV.CIRCLE_BUILD_NUM);
|
|
24
|
+
this.setInfo(this.targets.build_name, ENV.CIRCLE_JOB);
|
|
25
|
+
this.setInfo(this.targets.build_reason, 'Push');
|
|
26
|
+
this.setInfo(this.targets.user, ENV.CIRCLE_USERNAME, true);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
CircleCI
|
|
32
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { BaseCI } = require('./base.ci');
|
|
2
|
+
|
|
3
|
+
const ENV = process.env;
|
|
4
|
+
|
|
5
|
+
class GitHubCI extends BaseCI {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.init();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
init() {
|
|
12
|
+
this.setInfo(this.targets.ci, 'GITHUB_ACTIONS');
|
|
13
|
+
this.setInfo(this.targets.git, 'GITHUB');
|
|
14
|
+
this.setInfo(this.targets.repository_url, ENV.GITHUB_SERVER_URL + '/' + ENV.GITHUB_REPOSITORY);
|
|
15
|
+
this.setInfo(this.targets.repository_name, ENV.GITHUB_REPOSITORY);
|
|
16
|
+
this.setInfo(this.targets.repository_ref, ENV.GITHUB_REF);
|
|
17
|
+
this.setInfo(this.targets.repository_commit_sha, ENV.GITHUB_SHA);
|
|
18
|
+
this.setInfo(this.targets.build_url, ENV.GITHUB_SERVER_URL + '/' + ENV.GITHUB_REPOSITORY + '/actions/runs/' + ENV.GITHUB_RUN_ID);
|
|
19
|
+
this.setInfo(this.targets.build_number, ENV.GITHUB_RUN_NUMBER);
|
|
20
|
+
this.setInfo(this.targets.build_name, ENV.GITHUB_WORKFLOW);
|
|
21
|
+
this.setInfo(this.targets.build_reason, ENV.GITHUB_EVENT_NAME);
|
|
22
|
+
this.setInfo(this.targets.user, ENV.GITHUB_ACTOR, true);
|
|
23
|
+
|
|
24
|
+
this.setInfo(this.targets.branch_url, this.repository_url + this.repository_ref.replace('refs/heads/', '/tree/'));
|
|
25
|
+
this.setInfo(this.targets.branch_name, this.repository_ref.replace('refs/heads/', ''));
|
|
26
|
+
|
|
27
|
+
if (this.repository_ref.includes('refs/pull')) {
|
|
28
|
+
this.setInfo(this.targets.pull_request_url, this.repository_url + this.repository_ref.replace('refs/pull/', '/pull/'));
|
|
29
|
+
this.setInfo(this.targets.pull_request_name, this.repository_ref.replace('refs/pull/', '').replace('/merge', ''));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
GitHubCI
|
|
36
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const { BaseCI } = require('./base.ci');
|
|
2
|
+
|
|
3
|
+
const ENV = process.env;
|
|
4
|
+
|
|
5
|
+
class GitLabCI extends BaseCI {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.init();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
init() {
|
|
12
|
+
this.setInfo(this.targets.ci, 'GITLAB');
|
|
13
|
+
this.setInfo(this.targets.git, 'GITLAB');
|
|
14
|
+
this.setInfo(this.targets.repository_url, ENV.CI_PROJECT_URL);
|
|
15
|
+
this.setInfo(this.targets.repository_name, ENV.CI_PROJECT_NAME);
|
|
16
|
+
this.setInfo(this.targets.repository_ref, '/-/tree/' + (ENV.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME || ENV.CI_COMMIT_REF_NAME));
|
|
17
|
+
this.setInfo(this.targets.repository_commit_sha, ENV.CI_MERGE_REQUEST_SOURCE_BRANCH_SHA || ENV.CI_COMMIT_SHA);
|
|
18
|
+
this.setInfo(this.targets.branch_url, ENV.CI_PROJECT_URL + '/-/tree/' + (ENV.CI_COMMIT_REF_NAME || ENV.CI_COMMIT_BRANCH));
|
|
19
|
+
this.setInfo(this.targets.branch_name, ENV.CI_COMMIT_REF_NAME || ENV.CI_COMMIT_BRANCH);
|
|
20
|
+
this.setInfo(this.targets.pull_request_url,'');
|
|
21
|
+
this.setInfo(this.targets.pull_request_name, '');
|
|
22
|
+
this.setInfo(this.targets.build_url, ENV.CI_JOB_URL);
|
|
23
|
+
this.setInfo(this.targets.build_number, ENV.CI_JOB_ID);
|
|
24
|
+
this.setInfo(this.targets.build_name, ENV.CI_JOB_NAME);
|
|
25
|
+
this.setInfo(this.targets.build_reason, ENV.CI_PIPELINE_SOURCE);
|
|
26
|
+
|
|
27
|
+
if (ENV.CI_OPEN_MERGE_REQUESTS) {
|
|
28
|
+
const pr_number = ENV.CI_OPEN_MERGE_REQUESTS.split("!")[1];
|
|
29
|
+
this.setInfo(this.targets.pull_request_name, "#" + pr_number);
|
|
30
|
+
this.setInfo(this.targets.pull_request_url, ENV.CI_PROJECT_URL + "/-/merge_requests/" + pr_number);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
GitLabCI
|
|
37
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { GitHubCI } = require('./github');
|
|
2
|
+
const { GitLabCI } = require('./gitlab');
|
|
3
|
+
const { JenkinsCI } = require('./jenkins');
|
|
4
|
+
const { AzureDevOpsCI } = require('./azure-devops');
|
|
5
|
+
const { CircleCI } = require('./circle-ci');
|
|
6
|
+
const { BaseCI } = require('./base.ci');
|
|
7
|
+
|
|
8
|
+
const ENV = process.env;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @returns {import('../../extensions/extensions').ICIInfo}
|
|
12
|
+
*/
|
|
13
|
+
function getCIInformation() {
|
|
14
|
+
if (ENV.GITHUB_ACTIONS) {
|
|
15
|
+
const ci = new GitHubCI();
|
|
16
|
+
return ci.info();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (ENV.GITLAB_CI) {
|
|
20
|
+
const ci = new GitLabCI();
|
|
21
|
+
return ci.info();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (ENV.JENKINS_URL) {
|
|
25
|
+
const ci = new JenkinsCI();
|
|
26
|
+
return ci.info();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (ENV.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI) {
|
|
30
|
+
const ci = new AzureDevOpsCI();
|
|
31
|
+
return ci.info();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (ENV.CIRCLECI) {
|
|
35
|
+
const ci = new CircleCI();
|
|
36
|
+
return ci.info();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const ci = new BaseCI();
|
|
40
|
+
return ci.info();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = {
|
|
44
|
+
getCIInformation
|
|
45
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { BaseCI } = require('./base.ci');
|
|
2
|
+
|
|
3
|
+
const ENV = process.env;
|
|
4
|
+
|
|
5
|
+
class JenkinsCI extends BaseCI {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.init();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
init() {
|
|
12
|
+
this.setInfo(this.targets.ci, 'JENKINS');
|
|
13
|
+
this.setInfo(this.targets.git, '');
|
|
14
|
+
this.setInfo(this.targets.repository_url, ENV.GIT_URL || ENV.GITHUB_URL || ENV.BITBUCKET_URL);
|
|
15
|
+
this.setInfo(this.targets.repository_name, ENV.JOB_NAME);
|
|
16
|
+
this.setInfo(this.targets.repository_ref, ENV.BRANCH || ENV.BRANCH_NAME);
|
|
17
|
+
this.setInfo(this.targets.repository_commit_sha, ENV.GIT_COMMIT || ENV.GIT_COMMIT_SHA || ENV.GITHUB_SHA || ENV.BITBUCKET_COMMIT);
|
|
18
|
+
this.setInfo(this.targets.branch_url, this.repository_url + this.repository_ref.replace('refs/heads/', '/tree/'));
|
|
19
|
+
this.setInfo(this.targets.branch_name, this.repository_ref.replace('refs/heads/', ''));
|
|
20
|
+
|
|
21
|
+
if (this.repository_ref.includes('refs/pull')) {
|
|
22
|
+
this.setInfo(this.targets.pull_request_url, this.repository_url + this.repository_ref.replace('refs/pull/', '/pull/'));
|
|
23
|
+
this.setInfo(this.targets.pull_request_name, this.repository_ref.replace('refs/pull/', '').replace('/merge', ''));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.setInfo(this.targets.build_url, ENV.BUILD_URL);
|
|
27
|
+
this.setInfo(this.targets.build_number, ENV.BUILD_NUMBER);
|
|
28
|
+
this.setInfo(this.targets.build_name, ENV.JOB_NAME);
|
|
29
|
+
this.setInfo(this.targets.build_reason, ENV.BUILD_CAUSE);
|
|
30
|
+
this.setInfo(this.targets.user, ENV.USER || ENV.USERNAME, true);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
JenkinsCI
|
|
36
|
+
}
|
package/src/helpers/constants.js
CHANGED
|
@@ -24,6 +24,7 @@ const EXTENSION = Object.freeze({
|
|
|
24
24
|
FAILURE_ANALYSIS: 'failure-analysis',
|
|
25
25
|
SMART_ANALYSIS: 'smart-analysis',
|
|
26
26
|
ERROR_CLUSTERS: 'error-clusters',
|
|
27
|
+
BROWSERSTACK: 'browserstack',
|
|
27
28
|
HYPERLINKS: 'hyperlinks',
|
|
28
29
|
MENTIONS: 'mentions',
|
|
29
30
|
REPORT_PORTAL_ANALYSIS: 'report-portal-analysis',
|
|
@@ -37,7 +38,8 @@ const EXTENSION = Object.freeze({
|
|
|
37
38
|
|
|
38
39
|
const URLS = Object.freeze({
|
|
39
40
|
PERCY: 'https://percy.io',
|
|
40
|
-
QUICK_CHART: 'https://quickchart.io'
|
|
41
|
+
QUICK_CHART: 'https://quickchart.io',
|
|
42
|
+
BROWSERSTACK: 'https://api.browserstack.com'
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
const PROCESS_STATUS = Object.freeze({
|
package/src/helpers/helper.js
CHANGED
|
@@ -14,18 +14,11 @@ function getPercentage(x, y) {
|
|
|
14
14
|
function processText(raw) {
|
|
15
15
|
const dataRefMatches = raw.match(DATA_REF_PATTERN);
|
|
16
16
|
if (dataRefMatches) {
|
|
17
|
-
const values = [];
|
|
18
17
|
for (let i = 0; i < dataRefMatches.length; i++) {
|
|
19
18
|
const dataRefMatch = dataRefMatches[i];
|
|
20
19
|
const content = dataRefMatch.slice(1, -1);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} else {
|
|
24
|
-
values.push(content);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
for (let i = 0; i < dataRefMatches.length; i++) {
|
|
28
|
-
raw = raw.replace(dataRefMatches[i], values[i]);
|
|
20
|
+
const envValue = process.env[content] || content;
|
|
21
|
+
raw = raw.replace(dataRefMatch, envValue);
|
|
29
22
|
}
|
|
30
23
|
}
|
|
31
24
|
return raw;
|
package/src/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { PerformanceParseOptions } from 'performance-results-parser';
|
|
|
2
2
|
import PerformanceTestResult from 'performance-results-parser/src/models/PerformanceTestResult';
|
|
3
3
|
import { Schedule, User } from 'rosters';
|
|
4
4
|
import { ParseOptions } from 'test-results-parser';
|
|
5
|
-
import TestResult from 'test-results-parser/src/models/TestResult';
|
|
5
|
+
export import TestResult from 'test-results-parser/src/models/TestResult';
|
|
6
6
|
|
|
7
7
|
export interface ITarget {
|
|
8
8
|
name: TargetName;
|
|
@@ -17,7 +17,7 @@ export interface IExtension {
|
|
|
17
17
|
enable?: string | boolean;
|
|
18
18
|
condition?: Condition;
|
|
19
19
|
hook?: Hook;
|
|
20
|
-
inputs?: ReportPortalAnalysisInputs | ReportPortalHistoryInputs | HyperlinkInputs | MentionInputs | QuickChartTestSummaryInputs | PercyAnalysisInputs | CustomExtensionInputs | MetadataInputs | CIInfoInputs | AIFailureSummaryInputs;
|
|
20
|
+
inputs?: ReportPortalAnalysisInputs | ReportPortalHistoryInputs | HyperlinkInputs | MentionInputs | QuickChartTestSummaryInputs | PercyAnalysisInputs | CustomExtensionInputs | MetadataInputs | CIInfoInputs | AIFailureSummaryInputs | BrowserstackInputs;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export type ExtensionName = 'report-portal-analysis' | 'hyperlinks' | 'mentions' | 'report-portal-history' | 'quick-chart-test-summary' | 'metadata' | 'ci-info' | 'custom' | 'ai-failure-summary';
|
|
@@ -83,7 +83,51 @@ export interface AIFailureSummaryInputs extends ExtensionInputs {
|
|
|
83
83
|
failure_summary: string;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
export interface BrowserStackAutomationBuild {
|
|
87
|
+
name: string;
|
|
88
|
+
hashed_id: string;
|
|
89
|
+
duration: number;
|
|
90
|
+
status: string;
|
|
91
|
+
build_tag: string;
|
|
92
|
+
public_url: string;
|
|
93
|
+
}
|
|
86
94
|
|
|
95
|
+
export interface BrowserStackAutomationSession {
|
|
96
|
+
name: string;
|
|
97
|
+
duration: number;
|
|
98
|
+
os: string;
|
|
99
|
+
os_version: string;
|
|
100
|
+
browser_version: string;
|
|
101
|
+
browser: string;
|
|
102
|
+
device: string;
|
|
103
|
+
status: string;
|
|
104
|
+
hashed_id: string;
|
|
105
|
+
reason: string;
|
|
106
|
+
build_name: string;
|
|
107
|
+
project_name: string;
|
|
108
|
+
build_hashed_id: string;
|
|
109
|
+
test_priority: string;
|
|
110
|
+
logs: string;
|
|
111
|
+
browserstack_status: string;
|
|
112
|
+
created_at: string;
|
|
113
|
+
browser_url: string;
|
|
114
|
+
public_url: string;
|
|
115
|
+
video_url: string;
|
|
116
|
+
browser_console_logs_url: string;
|
|
117
|
+
har_logs_url: string;
|
|
118
|
+
selenium_logs_url: string;
|
|
119
|
+
session_terminal_logs_url: string;
|
|
120
|
+
build_terminal_logs_url: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface BrowserstackInputs extends ExtensionInputs {
|
|
124
|
+
url?: string;
|
|
125
|
+
username?: string;
|
|
126
|
+
access_key?: string;
|
|
127
|
+
automation_build_name?: string;
|
|
128
|
+
automation_build?: BrowserStackAutomationBuild;
|
|
129
|
+
automation_sessions?: BrowserStackAutomationSession[];
|
|
130
|
+
}
|
|
87
131
|
|
|
88
132
|
export interface PercyAnalysisInputs extends ExtensionInputs {
|
|
89
133
|
url?: string;
|
package/src/index.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
const { PublishCommand } = require('./commands/publish.command');
|
|
2
|
+
const { GenerateConfigCommand } = require('./commands/generate-config.command');
|
|
2
3
|
|
|
3
4
|
function publish(options) {
|
|
4
5
|
const publish_command = new PublishCommand(options);
|
|
5
6
|
return publish_command.publish();
|
|
6
7
|
}
|
|
7
8
|
|
|
9
|
+
function generateConfig() {
|
|
10
|
+
const generate_command = new GenerateConfigCommand();
|
|
11
|
+
return generate_command.execute();
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
function defineConfig(config) {
|
|
9
|
-
return config
|
|
15
|
+
return config;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
module.exports = {
|
|
13
19
|
publish,
|
|
20
|
+
generateConfig,
|
|
14
21
|
defineConfig
|
|
15
22
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { getAutomationBuilds, getAutomationBuildSessions } = require('../helpers/browserstack.helper');
|
|
2
|
+
|
|
3
|
+
class ExtensionsSetup {
|
|
4
|
+
constructor(extensions, result) {
|
|
5
|
+
this.extensions = extensions;
|
|
6
|
+
this.result = result;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async run() {
|
|
10
|
+
for (const extension of this.extensions) {
|
|
11
|
+
if (extension.name === 'browserstack') {
|
|
12
|
+
const browserStackExtensionSetup = new BrowserStackExtensionSetup(extension.inputs, this.result);
|
|
13
|
+
await browserStackExtensionSetup.setup();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class BrowserStackExtensionSetup {
|
|
20
|
+
constructor(inputs, result) {
|
|
21
|
+
/** @type {import('../index').BrowserstackInputs} */
|
|
22
|
+
this.inputs = inputs;
|
|
23
|
+
this.result = result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async setup() {
|
|
27
|
+
const build_rows = await getAutomationBuilds(this.inputs);
|
|
28
|
+
if (!Array.isArray(build_rows) || build_rows.length === 0) {
|
|
29
|
+
throw new Error('No builds found');
|
|
30
|
+
}
|
|
31
|
+
const automation_build = build_rows.find(_ => _.automation_build.name === this.inputs.automation_build_name);
|
|
32
|
+
if (!automation_build) {
|
|
33
|
+
throw new Error(`Build ${this.inputs.automation_build_name} not found`);
|
|
34
|
+
}
|
|
35
|
+
this.inputs.automation_build = automation_build.automation_build;
|
|
36
|
+
if (this.result) {
|
|
37
|
+
this.result.metadata = this.result.metadata || {};
|
|
38
|
+
this.result.metadata.ext_browserstack_automation_build = automation_build.automation_build;
|
|
39
|
+
}
|
|
40
|
+
this.inputs.automation_sessions = [];
|
|
41
|
+
const session_rows = await getAutomationBuildSessions(this.inputs, automation_build.automation_build.hashed_id);
|
|
42
|
+
if (!Array.isArray(session_rows) || session_rows.length === 0) {
|
|
43
|
+
throw new Error('No sessions found');
|
|
44
|
+
}
|
|
45
|
+
for (const session_row of session_rows) {
|
|
46
|
+
this.inputs.automation_sessions.push(session_row.automation_session);
|
|
47
|
+
}
|
|
48
|
+
if (this.result && this.result.suites && this.result.suites.length > 0) {
|
|
49
|
+
for (const suite of this.result.suites) {
|
|
50
|
+
const automation_session = this.inputs.automation_sessions.filter(_ => { _.name === suite.name })[0];
|
|
51
|
+
if (automation_session) {
|
|
52
|
+
suite.metadata = suite.metadata || {};
|
|
53
|
+
suite.metadata.ext_browserstack_automation_session = automation_session;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
ExtensionsSetup
|
|
62
|
+
}
|