testbeats 2.2.4 → 2.2.6
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 +1 -1
- package/src/commands/publish.command.js +30 -11
- package/src/extensions/ai-failure-summary.extension.js +1 -1
- package/src/extensions/base.extension.js +17 -1
- package/src/extensions/error-clusters.extension.js +1 -1
- package/src/helpers/constants.js +1 -0
- package/src/helpers/extension.helper.js +10 -0
- package/src/index.d.ts +16 -2
- package/src/platforms/base.platform.js +38 -2
- package/src/platforms/chat.platform.js +11 -0
- package/src/platforms/github.platform.js +0 -11
- package/src/platforms/index.js +2 -1
- package/src/platforms/slack.platform.js +13 -2
- package/src/platforms/teams.platform.js +11 -6
- package/src/targets/base.target.js +45 -0
- package/src/targets/custom.target.js +31 -0
- package/src/targets/delay.target.js +24 -0
- package/src/targets/github.js +5 -5
- package/src/targets/http.target.js +36 -0
- package/src/targets/index.js +10 -6
- package/src/targets/slack.js +25 -4
- package/src/targets/custom.js +0 -28
- package/src/targets/delay.js +0 -19
package/package.json
CHANGED
|
@@ -173,21 +173,40 @@ class PublishCommand {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
if (target.inputs) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
176
|
+
this.#validateURL(target);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
logger.debug("Validating targets - Successful!")
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
#validateURL(target) {
|
|
183
|
+
const inputs = target.inputs;
|
|
184
|
+
if (target.name === 'slack' || target.name === 'teams' || target.name === 'chat') {
|
|
185
|
+
if (inputs.token) {
|
|
186
|
+
if (!Array.isArray(inputs.channels)) {
|
|
187
|
+
throw new Error(`channels in ${target.name} target inputs must be an array`);
|
|
188
|
+
}
|
|
189
|
+
if (!inputs.channels.length) {
|
|
190
|
+
throw new Error(`at least one channel must be defined in ${target.name} target inputs`);
|
|
191
|
+
}
|
|
192
|
+
for (const channel of inputs.channels) {
|
|
193
|
+
if (typeof channel !== 'string') {
|
|
194
|
+
throw new Error(`channel in ${target.name} target inputs must be a string`);
|
|
186
195
|
}
|
|
187
196
|
}
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!inputs.url) {
|
|
201
|
+
throw new Error(`missing url in ${target.name} target inputs`);
|
|
202
|
+
}
|
|
203
|
+
if (typeof inputs.url !== 'string') {
|
|
204
|
+
throw new Error(`url in ${target.name} target inputs must be a string`);
|
|
205
|
+
}
|
|
206
|
+
if (!inputs.url.startsWith('http')) {
|
|
207
|
+
throw new Error(`url in ${target.name} target inputs must start with 'http' or 'https'`);
|
|
188
208
|
}
|
|
189
209
|
}
|
|
190
|
-
logger.debug("Validating targets - Successful!")
|
|
191
210
|
}
|
|
192
211
|
|
|
193
212
|
#processResults() {
|
|
@@ -36,7 +36,7 @@ class AIFailureSummaryExtension extends BaseExtension {
|
|
|
36
36
|
* @type {import('../beats/beats.types').IBeatExecutionMetric}
|
|
37
37
|
*/
|
|
38
38
|
const execution_metrics = data.execution_metrics[0];
|
|
39
|
-
this.text = execution_metrics.failure_summary;
|
|
39
|
+
this.text = this.platform.code(execution_metrics.failure_summary);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const TestResult = require('test-results-parser/src/models/TestResult');
|
|
2
2
|
const logger = require('../utils/logger');
|
|
3
|
-
const { addChatExtension, addSlackExtension, addTeamsExtension } = require('../helpers/extension.helper');
|
|
3
|
+
const { addChatExtension, addSlackExtension, addTeamsExtension, addGithubExtension } = require('../helpers/extension.helper');
|
|
4
|
+
const { getPlatform } = require('../platforms');
|
|
4
5
|
|
|
5
6
|
class BaseExtension {
|
|
6
7
|
|
|
@@ -32,6 +33,11 @@ class BaseExtension {
|
|
|
32
33
|
* @type {import('..').IExtensionDefaultOptions}
|
|
33
34
|
*/
|
|
34
35
|
this.default_options = {};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @type {import('../platforms/base.platform').BasePlatform}
|
|
39
|
+
*/
|
|
40
|
+
this.platform = getPlatform(this.target.name);
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
updateExtensionInputs() {
|
|
@@ -46,6 +52,9 @@ class BaseExtension {
|
|
|
46
52
|
case 'chat':
|
|
47
53
|
this.extension.inputs = Object.assign({}, { separator: true }, this.extension.inputs);
|
|
48
54
|
break;
|
|
55
|
+
case 'github':
|
|
56
|
+
this.extension.inputs = Object.assign({}, { separator: true }, this.extension.inputs);
|
|
57
|
+
break;
|
|
49
58
|
default:
|
|
50
59
|
break;
|
|
51
60
|
}
|
|
@@ -67,6 +76,9 @@ class BaseExtension {
|
|
|
67
76
|
case 'chat':
|
|
68
77
|
addChatExtension({ payload: this.payload, extension: this.extension, text: this.text });
|
|
69
78
|
break;
|
|
79
|
+
case 'github':
|
|
80
|
+
addGithubExtension({ payload: this.payload, extension: this.extension, text: this.text });
|
|
81
|
+
break;
|
|
70
82
|
default:
|
|
71
83
|
break;
|
|
72
84
|
}
|
|
@@ -84,6 +96,8 @@ class BaseExtension {
|
|
|
84
96
|
return _texts.join('\n');
|
|
85
97
|
case 'chat':
|
|
86
98
|
return _texts.join('<br>');
|
|
99
|
+
case 'github':
|
|
100
|
+
return _texts.join('\n');
|
|
87
101
|
default:
|
|
88
102
|
break;
|
|
89
103
|
}
|
|
@@ -100,6 +114,8 @@ class BaseExtension {
|
|
|
100
114
|
return `*${text}*`;
|
|
101
115
|
case 'chat':
|
|
102
116
|
return `<b>${text}</b>`;
|
|
117
|
+
case 'github':
|
|
118
|
+
return `**${text}**`;
|
|
103
119
|
default:
|
|
104
120
|
break;
|
|
105
121
|
}
|
|
@@ -38,7 +38,7 @@ class ErrorClustersExtension extends BaseExtension {
|
|
|
38
38
|
for (const cluster of clusters) {
|
|
39
39
|
texts.push(`${truncate(cluster.failure, 150)} - ${this.bold(`(x${cluster.count})`)}`);
|
|
40
40
|
}
|
|
41
|
-
this.text = this.
|
|
41
|
+
this.text = this.platform.bullets(texts);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
package/src/helpers/constants.js
CHANGED
|
@@ -100,6 +100,15 @@ function addChatExtension({ payload, extension, text }) {
|
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
function addGithubExtension({ payload, extension, text }) {
|
|
104
|
+
if (extension.inputs.title) {
|
|
105
|
+
const title = extension.inputs.title_link ? `[${extension.inputs.title}](${extension.inputs.title_link})` : extension.inputs.title;
|
|
106
|
+
payload.content.push(`**${title}**\n${text}\n\n`);
|
|
107
|
+
} else {
|
|
108
|
+
payload.content.push(`${text}\n\n`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
103
112
|
/**
|
|
104
113
|
* Sort extensions by their order property.
|
|
105
114
|
* Extensions without order will appear last, maintaining their original relative order.
|
|
@@ -123,5 +132,6 @@ module.exports = {
|
|
|
123
132
|
addSlackExtension,
|
|
124
133
|
addTeamsExtension,
|
|
125
134
|
addChatExtension,
|
|
135
|
+
addGithubExtension,
|
|
126
136
|
sortExtensionsByOrder
|
|
127
137
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface ITarget {
|
|
|
10
10
|
name: TargetName;
|
|
11
11
|
enable?: string | boolean;
|
|
12
12
|
condition?: Condition;
|
|
13
|
-
inputs?: SlackInputs | TeamsInputs | ChatInputs | GitHubInputs |
|
|
13
|
+
inputs?: SlackInputs | TeamsInputs | ChatInputs | GitHubInputs | ICustomTargetInputs | InfluxDBTargetInputs;
|
|
14
14
|
extensions?: IExtension[];
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -234,6 +234,8 @@ export interface TargetInputs {
|
|
|
234
234
|
|
|
235
235
|
export interface SlackInputs extends TargetInputs {
|
|
236
236
|
message_format?: 'blocks' | 'attachments';
|
|
237
|
+
token?: string;
|
|
238
|
+
channels?: string[];
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
export interface TeamsInputs extends TargetInputs {
|
|
@@ -275,11 +277,19 @@ export interface CustomTargetFunctionContext {
|
|
|
275
277
|
|
|
276
278
|
export type CustomTargetFunction = (ctx: CustomTargetFunctionContext) => void | Promise<void>;
|
|
277
279
|
|
|
278
|
-
export interface
|
|
280
|
+
export interface ICustomTargetInputs {
|
|
279
281
|
load: string | CustomTargetFunction;
|
|
280
282
|
}
|
|
281
283
|
|
|
284
|
+
export interface IDelayTargetInputs {
|
|
285
|
+
seconds: number;
|
|
286
|
+
}
|
|
282
287
|
|
|
288
|
+
export interface IHttpTargetInputs {
|
|
289
|
+
url: string;
|
|
290
|
+
method: string;
|
|
291
|
+
headers: object;
|
|
292
|
+
}
|
|
283
293
|
|
|
284
294
|
export interface CustomResultOptions {
|
|
285
295
|
type: string;
|
|
@@ -337,5 +347,9 @@ export type IExtensionDefaultOptions = {
|
|
|
337
347
|
condition: Condition
|
|
338
348
|
}
|
|
339
349
|
|
|
350
|
+
export type ITargetDefaultOptions = {
|
|
351
|
+
condition: Condition
|
|
352
|
+
}
|
|
353
|
+
|
|
340
354
|
export function publish(options: PublishOptions): Promise<any>
|
|
341
355
|
export function defineConfig(config: PublishConfig): PublishConfig
|
|
@@ -6,13 +6,41 @@ class BasePlatform {
|
|
|
6
6
|
* @param {string|number} text
|
|
7
7
|
*/
|
|
8
8
|
bold(text) {
|
|
9
|
-
|
|
9
|
+
return `**${text}**`;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
break() {
|
|
13
|
-
|
|
13
|
+
return '\n';
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @param {string[]} values
|
|
18
|
+
*/
|
|
19
|
+
merge(values) {
|
|
20
|
+
return this.getValidTexts(values).join(this.break());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {string[]} items - Array of strings to convert to bullet points
|
|
25
|
+
* @returns {string} - Formatted bullet points as a string
|
|
26
|
+
*/
|
|
27
|
+
bullets(items) {
|
|
28
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
return this.merge(items.map(item => `- ${item}`));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} text
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
code(text) {
|
|
39
|
+
return text;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
16
44
|
/**
|
|
17
45
|
*
|
|
18
46
|
* @param {import('..').ITarget} target
|
|
@@ -123,6 +151,14 @@ class BasePlatform {
|
|
|
123
151
|
|
|
124
152
|
return texts.join(' • ');
|
|
125
153
|
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {string[]} texts
|
|
157
|
+
* @returns {string[]}
|
|
158
|
+
*/
|
|
159
|
+
getValidTexts(texts) {
|
|
160
|
+
return texts.filter(text => !!text);
|
|
161
|
+
}
|
|
126
162
|
}
|
|
127
163
|
|
|
128
164
|
module.exports = { BasePlatform }
|
|
@@ -13,6 +13,17 @@ class ChatPlatform extends BasePlatform {
|
|
|
13
13
|
return '<br>';
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @param {string[]} items - Array of strings to convert to bullet points
|
|
18
|
+
* @returns {string} - Formatted bullet points as a string
|
|
19
|
+
*/
|
|
20
|
+
bullets(items) {
|
|
21
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
return this.merge(items.map(item => `• ${item}`));
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
}
|
|
17
28
|
|
|
18
29
|
module.exports = { ChatPlatform }
|
|
@@ -2,17 +2,6 @@ const { BasePlatform } = require('./base.platform');
|
|
|
2
2
|
|
|
3
3
|
class GitHubPlatform extends BasePlatform {
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* @param {string|number} text
|
|
7
|
-
*/
|
|
8
|
-
bold(text) {
|
|
9
|
-
return `**${text}**`;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
break() {
|
|
13
|
-
return '\n';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
5
|
}
|
|
17
6
|
|
|
18
7
|
module.exports = { GitHubPlatform };
|
package/src/platforms/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const { SlackPlatform } = require('./slack.platform');
|
|
|
3
3
|
const { TeamsPlatform } = require('./teams.platform');
|
|
4
4
|
const { ChatPlatform } = require('./chat.platform');
|
|
5
5
|
const { GitHubPlatform } = require('./github.platform');
|
|
6
|
+
const { BasePlatform } = require('./base.platform');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
@@ -19,7 +20,7 @@ function getPlatform(name) {
|
|
|
19
20
|
case TARGET.GITHUB:
|
|
20
21
|
return new GitHubPlatform();
|
|
21
22
|
default:
|
|
22
|
-
|
|
23
|
+
return new BasePlatform();
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -9,8 +9,19 @@ class SlackPlatform extends BasePlatform {
|
|
|
9
9
|
return `*${text}*`;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @param {string[]} items - Array of strings to convert to bullet points
|
|
14
|
+
* @returns {string} - Formatted bullet points as a string
|
|
15
|
+
*/
|
|
16
|
+
bullets(items) {
|
|
17
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
return this.merge(items.map(item => `• ${item}`));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
code(text) {
|
|
24
|
+
return `\`\`\`${text}\`\`\``;
|
|
14
25
|
}
|
|
15
26
|
}
|
|
16
27
|
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
const { BasePlatform } = require("./base.platform");
|
|
2
2
|
|
|
3
3
|
class TeamsPlatform extends BasePlatform {
|
|
4
|
-
/**
|
|
5
|
-
* @param {string|number} text
|
|
6
|
-
*/
|
|
7
|
-
bold(text) {
|
|
8
|
-
return `**${text}**`;
|
|
9
|
-
}
|
|
10
4
|
|
|
11
5
|
break() {
|
|
12
6
|
return '\n\n';
|
|
13
7
|
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string[]} items - Array of strings to convert to bullet points
|
|
11
|
+
* @returns {string} - Formatted bullet points as a string
|
|
12
|
+
*/
|
|
13
|
+
bullets(items) {
|
|
14
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
return this.merge(items.map(item => `- ${item}`));
|
|
18
|
+
}
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
module.exports = { TeamsPlatform }
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { getPlatform } = require('../platforms');
|
|
2
|
+
const { STATUS } = require('../helpers/constants');
|
|
3
|
+
|
|
4
|
+
class BaseTarget {
|
|
5
|
+
|
|
6
|
+
constructor({ target }) {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @type {import('../index').ITarget}
|
|
10
|
+
*/
|
|
11
|
+
this.target = target;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @type {string}
|
|
15
|
+
*/
|
|
16
|
+
this.name = target.name;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {string | boolean}
|
|
20
|
+
*/
|
|
21
|
+
this.enable = target.enable;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @type {import('../index').Condition}
|
|
25
|
+
*/
|
|
26
|
+
this.condition = target.condition || STATUS.PASS_OR_FAIL;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @type {import('../index').IExtension[]}
|
|
30
|
+
*/
|
|
31
|
+
this.extensions = target.extensions || [];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @type {import('../platforms/base.platform').BasePlatform}
|
|
35
|
+
*/
|
|
36
|
+
this.platform = getPlatform(this.name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async run({ result }) {
|
|
40
|
+
// throw new Error('Not implemented');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { BaseTarget};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { BaseTarget } = require('./base.target');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_INPUTS = {};
|
|
5
|
+
|
|
6
|
+
class CustomTarget extends BaseTarget {
|
|
7
|
+
|
|
8
|
+
constructor({ target }) {
|
|
9
|
+
super({ target });
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @type {import('../index').ICustomTargetInputs}
|
|
13
|
+
*/
|
|
14
|
+
this.inputs = Object.assign({}, DEFAULT_INPUTS, target.inputs);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run({ result }) {
|
|
18
|
+
if (typeof this.inputs.load === 'string') {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const target_runner = require(path.join(cwd, this.inputs.load));
|
|
21
|
+
await target_runner.run({ target: this.target, result });
|
|
22
|
+
} else if (typeof this.inputs.load === 'function') {
|
|
23
|
+
await this.inputs.load({ target: this.target, result });
|
|
24
|
+
} else {
|
|
25
|
+
throw `Invalid 'load' input in custom target - ${this.inputs.load}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { CustomTarget };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { BaseTarget } = require('./base.target');
|
|
2
|
+
|
|
3
|
+
const DEFAULT_INPUTS = {
|
|
4
|
+
seconds: 5
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
class DelayTarget extends BaseTarget {
|
|
8
|
+
|
|
9
|
+
constructor({ target }) {
|
|
10
|
+
super({ target });
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @type {import('../index').IDelayTargetInputs}
|
|
14
|
+
*/
|
|
15
|
+
this.inputs = Object.assign({}, DEFAULT_INPUTS, target.inputs);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async run() {
|
|
19
|
+
await new Promise(resolve => setTimeout(resolve, this.inputs.seconds * 1000));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = { DelayTarget };
|
package/src/targets/github.js
CHANGED
|
@@ -136,7 +136,7 @@ async function publishToGitHub({ target, message }) {
|
|
|
136
136
|
const token = target.inputs.token || process.env.GITHUB_TOKEN;
|
|
137
137
|
|
|
138
138
|
if (!token) {
|
|
139
|
-
throw new Error('GitHub token is required. Set GITHUB_TOKEN environment variable or provide
|
|
139
|
+
throw new Error('GitHub token is required. Set GITHUB_TOKEN environment variable or provide token in target inputs.');
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
if (!pull_number) {
|
|
@@ -155,7 +155,7 @@ async function publishToGitHub({ target, message }) {
|
|
|
155
155
|
|
|
156
156
|
if (target.inputs.update_comment) {
|
|
157
157
|
// Try to find existing comment and update it
|
|
158
|
-
const existingComment = await findExistingComment({ owner, repo, pull_number,
|
|
158
|
+
const existingComment = await findExistingComment({ owner, repo, pull_number, token, comment_title: target.inputs.comment_title });
|
|
159
159
|
if (existingComment) {
|
|
160
160
|
return request.patch({
|
|
161
161
|
url: `${url}/repos/${owner}/${repo}/issues/comments/${existingComment.id}`,
|
|
@@ -173,13 +173,13 @@ async function publishToGitHub({ target, message }) {
|
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
async function findExistingComment({ owner, repo, pull_number,
|
|
176
|
+
async function findExistingComment({ owner, repo, pull_number, token, comment_title }) {
|
|
177
177
|
if (!comment_title) return null;
|
|
178
178
|
|
|
179
179
|
try {
|
|
180
180
|
const url = `https://api.github.com/repos/${owner}/${repo}/issues/${pull_number}/comments`;
|
|
181
181
|
const headers = {
|
|
182
|
-
'Authorization': `token ${
|
|
182
|
+
'Authorization': `token ${token}`,
|
|
183
183
|
'Accept': 'application/vnd.github.v3+json',
|
|
184
184
|
'User-Agent': 'testbeats'
|
|
185
185
|
};
|
|
@@ -280,7 +280,7 @@ async function handleErrors({ target, errors }) {
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
const default_inputs = {
|
|
283
|
-
|
|
283
|
+
token: undefined,
|
|
284
284
|
comment_title: undefined,
|
|
285
285
|
update_comment: false,
|
|
286
286
|
owner: undefined,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { BaseTarget } = require('./base.target');
|
|
2
|
+
const request = require('phin-retry');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_INPUTS = {
|
|
5
|
+
url: '',
|
|
6
|
+
method: 'POST',
|
|
7
|
+
headers: {}
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
class HttpTarget extends BaseTarget {
|
|
11
|
+
|
|
12
|
+
constructor({ target }) {
|
|
13
|
+
super({ target });
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type {import('../index').IHttpTargetInputs}
|
|
17
|
+
*/
|
|
18
|
+
this.inputs = Object.assign({}, DEFAULT_INPUTS, target.inputs);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async run({ result }) {
|
|
22
|
+
const { url, method, headers } = this.inputs;
|
|
23
|
+
await request.__fetch({
|
|
24
|
+
url,
|
|
25
|
+
method,
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'application/json',
|
|
28
|
+
...headers
|
|
29
|
+
},
|
|
30
|
+
body: { result }
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { HttpTarget };
|
package/src/targets/index.js
CHANGED
|
@@ -2,8 +2,9 @@ const teams = require('./teams');
|
|
|
2
2
|
const slack = require('./slack');
|
|
3
3
|
const chat = require('./chat');
|
|
4
4
|
const github = require('./github');
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const { CustomTarget } = require('./custom.target');
|
|
6
|
+
const { DelayTarget } = require('./delay.target');
|
|
7
|
+
const { HttpTarget } = require('./http.target');
|
|
7
8
|
const influx = require('./influx');
|
|
8
9
|
const { TARGET } = require('../helpers/constants');
|
|
9
10
|
const { checkCondition } = require('../helpers/helper');
|
|
@@ -19,11 +20,13 @@ function getTargetRunner(target) {
|
|
|
19
20
|
case TARGET.GITHUB:
|
|
20
21
|
return github;
|
|
21
22
|
case TARGET.CUSTOM:
|
|
22
|
-
return
|
|
23
|
+
return new CustomTarget({ target });
|
|
23
24
|
case TARGET.DELAY:
|
|
24
|
-
return
|
|
25
|
+
return new DelayTarget({ target });
|
|
25
26
|
case TARGET.INFLUX:
|
|
26
27
|
return influx;
|
|
28
|
+
case TARGET.HTTP:
|
|
29
|
+
return new HttpTarget({ target });
|
|
27
30
|
default:
|
|
28
31
|
return require(target.name);
|
|
29
32
|
}
|
|
@@ -31,8 +34,9 @@ function getTargetRunner(target) {
|
|
|
31
34
|
|
|
32
35
|
async function run(target, result) {
|
|
33
36
|
const target_runner = getTargetRunner(target);
|
|
34
|
-
const target_options = Object.assign({}, target_runner.default_options, target);
|
|
35
|
-
|
|
37
|
+
// const target_options = Object.assign({}, target_runner.default_options, target);
|
|
38
|
+
const condition = target.condition || target_runner.default_options?.condition || target_runner.condition;
|
|
39
|
+
if (await checkCondition({ condition, result, target })) {
|
|
36
40
|
await target_runner.run({result, target});
|
|
37
41
|
}
|
|
38
42
|
}
|
package/src/targets/slack.js
CHANGED
|
@@ -9,6 +9,8 @@ const { getValidMetrics, getMetricValuesText } = require('../helpers/performance
|
|
|
9
9
|
const TestResult = require('test-results-parser/src/models/TestResult');
|
|
10
10
|
const { getPlatform } = require('../platforms');
|
|
11
11
|
|
|
12
|
+
const SLACK_BASE_URL = 'https://slack.com';
|
|
13
|
+
|
|
12
14
|
const STATUSES = {
|
|
13
15
|
GOOD: ':white_check_mark:',
|
|
14
16
|
WARNING: ':warning:',
|
|
@@ -31,10 +33,7 @@ async function run({ result, target }) {
|
|
|
31
33
|
}
|
|
32
34
|
const message = getRootPayload({ result, target, payload });
|
|
33
35
|
logger.info(`🔔 Publishing results to Slack...`);
|
|
34
|
-
return
|
|
35
|
-
url: target.inputs.url,
|
|
36
|
-
body: message
|
|
37
|
-
});
|
|
36
|
+
return publish({ inputs: target.inputs, message });
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
async function setFunctionalPayload({ result, target, payload }) {
|
|
@@ -325,6 +324,28 @@ async function handleErrors({ target, errors }) {
|
|
|
325
324
|
});
|
|
326
325
|
}
|
|
327
326
|
|
|
327
|
+
async function publish({ inputs, message}) {
|
|
328
|
+
const { url, token, channels } = inputs;
|
|
329
|
+
if (token) {
|
|
330
|
+
for (let i = 0; i < channels.length; i++) {
|
|
331
|
+
message.channel = channels[i];
|
|
332
|
+
return request.post({
|
|
333
|
+
url: url ? url : `${SLACK_BASE_URL}/api/chat.postMessage`,
|
|
334
|
+
headers: {
|
|
335
|
+
'Authorization': `Bearer ${token}`
|
|
336
|
+
},
|
|
337
|
+
body: message
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
} else {
|
|
342
|
+
return request.post({
|
|
343
|
+
url,
|
|
344
|
+
body: message
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
328
349
|
module.exports = {
|
|
329
350
|
run,
|
|
330
351
|
handleErrors,
|
package/src/targets/custom.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const { STATUS } = require('../helpers/constants');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* @param {object} param0
|
|
7
|
-
* @param {import('../index').ITarget} param0.target
|
|
8
|
-
*/
|
|
9
|
-
async function run({result, target}) {
|
|
10
|
-
if (typeof target.inputs.load === 'string') {
|
|
11
|
-
const cwd = process.cwd();
|
|
12
|
-
const target_runner = require(path.join(cwd, target.inputs.load));
|
|
13
|
-
await target_runner.run({ target, result });
|
|
14
|
-
} else if (typeof target.inputs.load === 'function') {
|
|
15
|
-
await target.inputs.load({ target, result });
|
|
16
|
-
} else {
|
|
17
|
-
throw `Invalid 'load' input in custom target - ${target.inputs.load}`;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const default_options = {
|
|
22
|
-
condition: STATUS.PASS_OR_FAIL
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
module.exports = {
|
|
26
|
-
run,
|
|
27
|
-
default_options
|
|
28
|
-
}
|
package/src/targets/delay.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const { STATUS } = require("../helpers/constants");
|
|
2
|
-
|
|
3
|
-
async function run({ target }) {
|
|
4
|
-
target.inputs = Object.assign({}, default_inputs, target.inputs);
|
|
5
|
-
await new Promise(resolve => setTimeout(resolve, target.inputs.seconds * 1000));
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const default_options = {
|
|
9
|
-
condition: STATUS.PASS_OR_FAIL
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const default_inputs = {
|
|
13
|
-
seconds: 5
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = {
|
|
17
|
-
run,
|
|
18
|
-
default_options
|
|
19
|
-
}
|