artillery-plugin-slack 1.11.0 → 1.12.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.
Files changed (2) hide show
  1. package/index.js +100 -67
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -52,20 +52,29 @@ class SlackPlugin {
52
52
  this.exitCode = 1;
53
53
  }
54
54
  this.ensureChecks.failed += 1;
55
- this.ensureChecks.checkList.push(
56
- `:x: \`${check.original}\`${check.strict ? '' : ' (optional) '}`
57
- );
55
+ this.ensureChecks.checkList.push({
56
+ text: check.original,
57
+ passed: false,
58
+ optional: !check.strict
59
+ });
58
60
  } else {
59
61
  this.ensureChecks.passed += 1;
60
- this.ensureChecks.checkList.push(
61
- `:white_check_mark: \`${check.original}\``
62
- );
62
+ this.ensureChecks.checkList.push({
63
+ text: check.original,
64
+ passed: true,
65
+ optional: false
66
+ });
63
67
  }
64
68
  });
65
69
 
66
70
  // When ensure is enabled, whether the beforeExit or the checks event will be triggered first will depend on the order of plugins in the test script
67
71
  // Since we need data from both events, first event triggered will store the data and the second event will send the report
68
- if (this.exitCode !== undefined && this.report && !this.reportSent) {
72
+ if (
73
+ this.exitCode !== undefined &&
74
+ this.exitCode !== null &&
75
+ this.report &&
76
+ !this.reportSent
77
+ ) {
69
78
  debug('Sending report from checks event');
70
79
  await this.sendReport(this.report, this.ensureChecks);
71
80
  this.reportSent = true;
@@ -92,10 +101,10 @@ class SlackPlugin {
92
101
 
93
102
  getErrors(report) {
94
103
  const errorList = [];
95
- for (const [key, value] of Object.entries(report.counters).filter(
96
- ([key, value]) => key.startsWith('errors.')
104
+ for (const [key, value] of Object.entries(report.counters).filter(([key]) =>
105
+ key.startsWith('errors.')
97
106
  )) {
98
- errorList.push(` ${key.replace('errors.', '')}: ${value}`);
107
+ errorList.push(`❌ ${key.replace('errors.', '')} (${value})`);
99
108
  }
100
109
  return errorList;
101
110
  }
@@ -103,98 +112,122 @@ class SlackPlugin {
103
112
  assembleSlackPayload(report, ensureChecks) {
104
113
  const errorList = this.getErrors(report);
105
114
  const duration = report.lastMetricAt - report.firstMetricAt;
106
- const introText =
115
+ const headerText =
107
116
  this.exitCode === 0
108
117
  ? '🟢 Artillery test run finished'
109
118
  : '🔴 Artillery test run failed';
110
119
 
111
120
  const payloadTemplate = {
112
- text: introText,
121
+ text: headerText,
113
122
  blocks: [
114
123
  {
115
- type: 'rich_text',
116
- elements: [
117
- {
118
- type: 'rich_text_section',
119
- elements: [
120
- {
121
- type: 'text',
122
- text: introText,
123
- style: {
124
- bold: true
125
- }
126
- }
127
- ]
128
- }
129
- ]
130
- },
131
- {
132
- type: 'section',
124
+ type: 'header',
133
125
  text: {
134
- type: 'mrkdwn',
135
- text: `Duration: ${this.formatDuration(duration)}`
126
+ type: 'plain_text',
127
+ text: headerText,
128
+ emoji: true
136
129
  }
137
130
  }
138
131
  ]
139
132
  };
140
133
 
141
- if (this.cloudEnabled) {
142
- payloadTemplate.blocks.push({
143
- type: 'section',
144
- text: {
145
- type: 'mrkdwn',
146
- text: `<${this.cloudTestRunUrl}>`
147
- }
148
- });
134
+ let errorsText = '*Errors*\nNone';
135
+
136
+ if (errorList.length > 0) {
137
+ // Only show first 10 errors to avoid Slack message length limit
138
+ const maxErrors = 10;
139
+ const trimmedList = errorList.slice(0, maxErrors);
140
+
141
+ if (errorList.length > maxErrors) {
142
+ trimmedList.push(`➕ ${errorList.length - maxErrors} more…`);
143
+ }
144
+
145
+ errorsText = `*Errors (${errorList.length})*\n\`\`\`\n${trimmedList.join(
146
+ '\n'
147
+ )}\n\`\`\``;
149
148
  }
150
149
 
151
150
  const metricBlocks = [
152
- {
153
- type: 'divider'
154
- },
155
151
  {
156
152
  type: 'section',
157
153
  fields: [
158
154
  {
159
155
  type: 'mrkdwn',
160
- text: `*${report.counters['vusers.completed']} / ${report.counters['vusers.created']}*\nVUs completed / created`
156
+ text: `*VUs*\n${report.counters['vusers.completed']} completed / ${report.counters['vusers.created']} created`
161
157
  },
162
158
  {
163
159
  type: 'mrkdwn',
164
- text: `*Errors*\n${
165
- errorList.length !== 0 ? errorList.join('\n') : '0'
166
- }`
160
+ text: `*Duration*\n${this.formatDuration(duration)}`
167
161
  }
168
162
  ]
169
- },
170
- {
171
- type: 'divider'
172
163
  }
173
164
  ];
174
165
 
166
+ let checksText = '*Checks*\nNone defined';
167
+
175
168
  if (this.ensureChecks) {
176
- metricBlocks.push(
177
- ...[
178
- {
179
- type: 'section',
180
- fields: [
181
- {
182
- type: 'mrkdwn',
183
- text: `*Checks (${ensureChecks.passed} / ${
184
- ensureChecks.total
185
- })*\n${this.ensureChecks.checkList.join('\n')}`
186
- }
187
- ]
188
- },
169
+ // Show summary if more than 10 checks to avoid Slack message length limit
170
+ if (this.ensureChecks.total > 10) {
171
+ let summaryText = '';
172
+
173
+ if (ensureChecks.passed > 0) {
174
+ summaryText += `🟢 ${ensureChecks.passed} checks passed\n`;
175
+ }
176
+
177
+ if (ensureChecks.failed > 0) {
178
+ summaryText += `🔴 ${ensureChecks.failed} checks failed`;
179
+ }
180
+
181
+ summaryText = summaryText.trim();
182
+ checksText = `*Checks (${ensureChecks.passed}/${ensureChecks.total})*\n\`\`\`\n${summaryText}\n\`\`\``;
183
+ } else {
184
+ const formattedChecks = this.ensureChecks.checkList.map(
185
+ (check) =>
186
+ `${check.passed ? '🟢' : '🔴'} ${check.text}${
187
+ check.optional ? ' (optional)' : ''
188
+ }`
189
+ );
190
+
191
+ checksText = `*Checks (${ensureChecks.passed} / ${
192
+ ensureChecks.total
193
+ })*\n\`\`\`\n${formattedChecks.join('\n')}\n\`\`\``;
194
+ }
195
+ }
196
+
197
+ metricBlocks.push({
198
+ type: 'section',
199
+ fields: [
200
+ {
201
+ type: 'mrkdwn',
202
+ text: checksText
203
+ },
204
+ {
205
+ type: 'mrkdwn',
206
+ text: errorsText
207
+ }
208
+ ]
209
+ });
210
+
211
+ payloadTemplate.blocks = payloadTemplate.blocks.concat(metricBlocks);
212
+
213
+ if (this.cloudEnabled) {
214
+ payloadTemplate.blocks.push({
215
+ type: 'actions',
216
+ elements: [
189
217
  {
190
- type: 'divider'
218
+ type: 'button',
219
+ text: {
220
+ type: 'plain_text',
221
+ text: 'See report on Artillery Cloud',
222
+ emoji: true
223
+ },
224
+ url: this.cloudTestRunUrl,
225
+ style: 'primary'
191
226
  }
192
227
  ]
193
- );
228
+ });
194
229
  }
195
230
 
196
- payloadTemplate.blocks = payloadTemplate.blocks.concat(metricBlocks);
197
-
198
231
  return JSON.stringify(payloadTemplate);
199
232
  }
200
233
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artillery-plugin-slack",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Send Artillery.io test notifications to Slack",
5
5
  "main": "index.js",
6
6
  "publishConfig": {