@akshatmittal/invoker 0.3.0 → 0.3.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/README.md +8 -10
- package/dist/slack.mjs +56 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -196,16 +196,14 @@ retries.
|
|
|
196
196
|
## Notify Slack
|
|
197
197
|
|
|
198
198
|
Invoker's optional Slack reporter posts one `Invoker Report` parent message per
|
|
199
|
-
Vitest run
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
failures are
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
an explicit Slack rate-limit rejection is reattempted only after its required
|
|
208
|
-
delay.
|
|
199
|
+
Vitest run containing every Workflow card. Each card includes aggregate results,
|
|
200
|
+
Workflow metadata, and a table of Task counts and durations. A shared footer
|
|
201
|
+
contains the elapsed span from the first Case start to the final Case completion,
|
|
202
|
+
a localized timestamp, and the optional run link. Final failures, successful
|
|
203
|
+
retry details, skipped Case reasons, and unhandled run errors are posted in the
|
|
204
|
+
same thread. Delivery failures are isolated to the affected reply. Ambiguous
|
|
205
|
+
transport failures are not retried; an explicit Slack rate-limit rejection is
|
|
206
|
+
reattempted only after its required delay.
|
|
209
207
|
|
|
210
208
|
```ts
|
|
211
209
|
import { slackReporter } from "@akshatmittal/invoker/slack";
|
package/dist/slack.mjs
CHANGED
|
@@ -49,7 +49,8 @@ function collectWorkflowReports(modules) {
|
|
|
49
49
|
skipped: 0,
|
|
50
50
|
incomplete: 0,
|
|
51
51
|
failures: [],
|
|
52
|
-
retries: []
|
|
52
|
+
retries: [],
|
|
53
|
+
skips: []
|
|
53
54
|
};
|
|
54
55
|
workflow.tasks.set(taskSuite, task);
|
|
55
56
|
}
|
|
@@ -78,28 +79,37 @@ function collectWorkflowReports(modules) {
|
|
|
78
79
|
matrix: invoker.matrix,
|
|
79
80
|
messages: result.errors.map(errorMessage)
|
|
80
81
|
});
|
|
82
|
+
else if (result.state === "skipped") task.skips.push({
|
|
83
|
+
task: task.name,
|
|
84
|
+
caseName: testCase.name,
|
|
85
|
+
matrix: invoker.matrix,
|
|
86
|
+
reason: result.note || "No reason provided"
|
|
87
|
+
});
|
|
81
88
|
}
|
|
82
89
|
return [...workflows.values()].map((workflow) => {
|
|
83
90
|
const failures = [];
|
|
84
91
|
const retries = [];
|
|
92
|
+
const skips = [];
|
|
85
93
|
addErrors(failures, workflow.suite.errors());
|
|
86
94
|
addErrors(failures, workflow.module.errors());
|
|
87
95
|
const collectedTasks = [...workflow.tasks.values()];
|
|
88
96
|
for (const task of collectedTasks) {
|
|
89
97
|
failures.push(...task.failures);
|
|
90
98
|
retries.push(...task.retries);
|
|
99
|
+
skips.push(...task.skips);
|
|
91
100
|
addErrors(failures, task.suite.errors(), task.name);
|
|
92
101
|
}
|
|
93
102
|
const { startedAt, endedAt } = timeSpan(collectedTasks);
|
|
94
103
|
return {
|
|
95
104
|
name: workflow.name,
|
|
96
105
|
metadata: workflow.metadata,
|
|
97
|
-
tasks: collectedTasks.map(({ suite: _suite, failures: _failures, retries: _retries, startedAt, endedAt, ...task }) => ({
|
|
106
|
+
tasks: collectedTasks.map(({ suite: _suite, failures: _failures, retries: _retries, skips: _skips, startedAt, endedAt, ...task }) => ({
|
|
98
107
|
...task,
|
|
99
108
|
duration: startedAt === void 0 || endedAt === void 0 ? 0 : endedAt - startedAt
|
|
100
109
|
})),
|
|
101
110
|
failures: deduplicateFailures(failures),
|
|
102
111
|
retries,
|
|
112
|
+
skips,
|
|
103
113
|
startedAt,
|
|
104
114
|
endedAt
|
|
105
115
|
};
|
|
@@ -252,6 +262,49 @@ function retryMessages(report) {
|
|
|
252
262
|
});
|
|
253
263
|
});
|
|
254
264
|
}
|
|
265
|
+
function skipMessages(report) {
|
|
266
|
+
return [...Map.groupBy(report.skips, (skip) => skip.task)].flatMap(([task, skips]) => {
|
|
267
|
+
const title = escapeSlack(truncate(task, NAME_CHARACTER_LIMIT));
|
|
268
|
+
const workflow = `*Workflow:* ${escapeSlack(truncate(report.name, NAME_CHARACTER_LIMIT))}`;
|
|
269
|
+
const metadata = metadataText(report.metadata);
|
|
270
|
+
const context = metadata ? `${workflow} • ${metadata}` : workflow;
|
|
271
|
+
return chunk(skips.map((skip) => {
|
|
272
|
+
const matrix = `\nMatrix: ${escapeSlack(JSON.stringify(skip.matrix))}`;
|
|
273
|
+
return `*${escapeSlack(skip.caseName)}*${matrix}\nReason: ${escapeSlack(skip.reason)}`;
|
|
274
|
+
}), SECTION_CHARACTER_LIMIT).map((details, index, messages) => {
|
|
275
|
+
const part = messages.length > 1 ? ` (${index + 1}/${messages.length})` : "";
|
|
276
|
+
return {
|
|
277
|
+
text: `${truncate(report.name, NAME_CHARACTER_LIMIT)} › ${truncate(task, NAME_CHARACTER_LIMIT)} — ${skips.length} skipped${part}`,
|
|
278
|
+
attachments: [{
|
|
279
|
+
color: "warning",
|
|
280
|
+
blocks: [
|
|
281
|
+
{
|
|
282
|
+
type: "section",
|
|
283
|
+
text: {
|
|
284
|
+
type: "mrkdwn",
|
|
285
|
+
text: `🟡 *${title} — ${skips.length} skipped${part}*`
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
type: "context",
|
|
290
|
+
elements: [{
|
|
291
|
+
type: "mrkdwn",
|
|
292
|
+
text: context
|
|
293
|
+
}]
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
type: "section",
|
|
297
|
+
text: {
|
|
298
|
+
type: "mrkdwn",
|
|
299
|
+
text: details
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
}]
|
|
304
|
+
};
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
255
308
|
function unhandledErrorMessages(errors) {
|
|
256
309
|
const messages = [...new Set(errors.map(errorMessage))];
|
|
257
310
|
return chunk(messages.map((message) => `• ${escapeSlack(message)}`), SECTION_CHARACTER_LIMIT).map((details, index, chunks) => {
|
|
@@ -457,6 +510,7 @@ function slackReporter(options) {
|
|
|
457
510
|
const replies = [
|
|
458
511
|
...reports.flatMap(failureMessages),
|
|
459
512
|
...reports.flatMap(retryMessages),
|
|
513
|
+
...reports.flatMap(skipMessages),
|
|
460
514
|
...unhandledErrorMessages(unhandledErrors)
|
|
461
515
|
];
|
|
462
516
|
if (replies.length > 0 && !parentTimestamp) {
|