@fabasoad/sarif-to-slack 0.1.0 → 0.1.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/.pre-commit-config.yaml +1 -1
- package/api-extractor.json +1 -1
- package/dist/Logger.d.ts +2 -0
- package/dist/Logger.d.ts.map +1 -0
- package/dist/Logger.js +23 -0
- package/dist/Logger.js.map +1 -0
- package/dist/Processors.d.ts +2 -0
- package/dist/Processors.d.ts.map +1 -0
- package/dist/Processors.js +91 -0
- package/dist/Processors.js.map +1 -0
- package/dist/SarifToSlackService.d.ts +39 -0
- package/dist/SarifToSlackService.d.ts.map +1 -0
- package/dist/SarifToSlackService.js +95 -0
- package/dist/SarifToSlackService.js.map +1 -0
- package/dist/SlackMessageBuilder.d.ts +2 -0
- package/dist/SlackMessageBuilder.d.ts.map +1 -0
- package/dist/SlackMessageBuilder.js +143 -0
- package/dist/SlackMessageBuilder.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/sarif-to-slack.d.ts +1 -1
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +36 -0
- package/dist/types.js.map +1 -0
- package/package.json +4 -1
- package/src/SarifToSlackService.ts +4 -2
- package/tsconfig.json +27 -13
package/.pre-commit-config.yaml
CHANGED
package/api-extractor.json
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
*
|
|
46
46
|
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
|
|
47
47
|
*/
|
|
48
|
-
"mainEntryPointFilePath": "<projectFolder>/
|
|
48
|
+
"mainEntryPointFilePath": "<projectFolder>/dist/index.d.ts",
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* A list of NPM package names whose exports should be treated as part of this package.
|
package/dist/Logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":""}
|
package/dist/Logger.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Logger as TSLogger } from 'tslog';
|
|
2
|
+
import { LogLevel } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Logger class for managing logging operations.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export default class Logger {
|
|
8
|
+
static instance = new TSLogger();
|
|
9
|
+
static initialize({ logLevel = LogLevel.Info }) {
|
|
10
|
+
if (!Logger.instance) {
|
|
11
|
+
Logger.instance = new TSLogger({
|
|
12
|
+
minLevel: process.env.ACTIONS_STEP_DEBUG === 'true' ? 0 : logLevel,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
static info(...args) {
|
|
17
|
+
Logger.instance.info(args);
|
|
18
|
+
}
|
|
19
|
+
static debug(...args) {
|
|
20
|
+
Logger.instance.debug(args);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=Logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger.js","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAW,MAAM,OAAO,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAUlC;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IACjB,MAAM,CAAC,QAAQ,GAAsB,IAAI,QAAQ,EAAE,CAAC;IAErD,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAiB;QAClE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC;gBAC7B,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ;aACnE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAEM,MAAM,CAAC,IAAI,CAAC,GAAG,IAAc;QAClC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,GAAG,IAAc;QACnC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Processors.d.ts","sourceRoot":"","sources":["../src/Processors.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import Logger from './Logger';
|
|
4
|
+
/**
|
|
5
|
+
* Processes a color string and converts it to a specific hex code if it matches
|
|
6
|
+
* a CI status identifier.
|
|
7
|
+
* @param color - The color string to process, which can be a CI status identifier
|
|
8
|
+
* or a custom color.
|
|
9
|
+
* @returns The processed color as a hex string or undefined if the input is not
|
|
10
|
+
* a recognized CI status identifier.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export function processColor(color) {
|
|
14
|
+
switch (color) {
|
|
15
|
+
case 'success':
|
|
16
|
+
Logger.info(`Converting "${color}" to #008000`);
|
|
17
|
+
return '#008000';
|
|
18
|
+
case 'failure':
|
|
19
|
+
Logger.info(`Converting "${color}" to #ff0000`);
|
|
20
|
+
return '#ff0000';
|
|
21
|
+
case 'cancelled':
|
|
22
|
+
Logger.info(`Converting "${color}" to #0047ab`);
|
|
23
|
+
return '#0047ab';
|
|
24
|
+
case 'skipped':
|
|
25
|
+
Logger.info(`Converting "${color}" to #808080`);
|
|
26
|
+
return '#808080';
|
|
27
|
+
default:
|
|
28
|
+
Logger.debug(`"${color}" color is not a CI status identifier. Returning as is...`);
|
|
29
|
+
return color;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Processes a log level string or number and converts it to a numeric log level.
|
|
34
|
+
* @param logLevel
|
|
35
|
+
* @returns The numeric log level corresponding to the input string or number.
|
|
36
|
+
* @throws Error If the input string does not match any known log level.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export function processLogLevel(logLevel) {
|
|
40
|
+
if (typeof logLevel === 'string') {
|
|
41
|
+
switch (logLevel.toLowerCase()) {
|
|
42
|
+
case 'silly':
|
|
43
|
+
return 0;
|
|
44
|
+
case 'trace':
|
|
45
|
+
return 1;
|
|
46
|
+
case 'debug':
|
|
47
|
+
return 2;
|
|
48
|
+
case 'info':
|
|
49
|
+
return 3;
|
|
50
|
+
case 'warning':
|
|
51
|
+
return 4;
|
|
52
|
+
case 'error':
|
|
53
|
+
return 5;
|
|
54
|
+
case 'fatal':
|
|
55
|
+
return 6;
|
|
56
|
+
default:
|
|
57
|
+
throw new Error(`Unknown log level: ${logLevel}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return logLevel;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Processes the SARIF path, which can be a file or a directory. If it's a
|
|
64
|
+
* directory, it returns an array of paths to all `.sarif` files, otherwise it
|
|
65
|
+
* returns an array with a single path to the file.
|
|
66
|
+
* @param sarifPath - The path to the SARIF file or directory.
|
|
67
|
+
* @returns An array of strings representing the paths to the SARIF files.
|
|
68
|
+
* @throws Error If the path does not exist, or if it is neither a file nor a
|
|
69
|
+
* directory.
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
export function processSarifPath(sarifPath) {
|
|
73
|
+
if (!fs.existsSync(sarifPath)) {
|
|
74
|
+
throw new Error(`"sarif-path" does not exist: ${sarifPath}`);
|
|
75
|
+
}
|
|
76
|
+
const sarifStats = fs.statSync(sarifPath);
|
|
77
|
+
if (sarifStats.isDirectory()) {
|
|
78
|
+
Logger.info(`"sarif-path" is a directory: ${sarifPath}`);
|
|
79
|
+
const files = fs.readdirSync(sarifPath);
|
|
80
|
+
const filteredFiles = files.filter((file) => path.extname(file).toLowerCase() === '.sarif');
|
|
81
|
+
Logger.info(`Found ${filteredFiles.length} SARIF files in ${sarifPath} directory`);
|
|
82
|
+
Logger.debug(`Filtered SARIF files: ${filteredFiles.join(', ')}`);
|
|
83
|
+
return filteredFiles.map((file) => path.join(sarifPath, file));
|
|
84
|
+
}
|
|
85
|
+
if (sarifStats.isFile()) {
|
|
86
|
+
Logger.info(`"sarif-path" is a file: ${sarifPath}`);
|
|
87
|
+
return [sarifPath];
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`"sarif-path" is neither a file nor a directory: ${sarifPath}`);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=Processors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Processors.js","sourceRoot":"","sources":["../src/Processors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SarifToSlackServiceOptions, SlackMessage } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Service to convert SARIF files to Slack messages and send them.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare class SarifToSlackService {
|
|
7
|
+
private readonly _slackMessages;
|
|
8
|
+
private constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Gets the Slack messages prepared for each SARIF file.
|
|
11
|
+
* @returns A read-only map where keys are SARIF file paths and values are SlackMessage instances.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
get slackMessages(): ReadonlyMap<string, SlackMessage>;
|
|
15
|
+
/**
|
|
16
|
+
* Creates an instance of SarifToSlackService.
|
|
17
|
+
* @param opts - Options for the service, including webhook URL, SARIF path, and other configurations.
|
|
18
|
+
* @returns A promise that resolves to an instance of SarifToSlackService.
|
|
19
|
+
* @throws Error if no SARIF files are found at the provided path.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
static create(opts: SarifToSlackServiceOptions): Promise<SarifToSlackService>;
|
|
23
|
+
/**
|
|
24
|
+
* Sends all prepared Slack messages.
|
|
25
|
+
* @returns A promise that resolves when all messages have been sent.
|
|
26
|
+
* @throws Error if a Slack message was not prepared for a SARIF path.
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
sendAll(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Sends a Slack message for a specific SARIF path.
|
|
32
|
+
* @param sarifPath - The path of the SARIF file for which the message should be sent.
|
|
33
|
+
* @returns A promise that resolves when the message has been sent.
|
|
34
|
+
* @throws Error if a Slack message was not prepared for the given SARIF path.
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
send(sarifPath: string): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=SarifToSlackService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SarifToSlackService.d.ts","sourceRoot":"","sources":["../src/SarifToSlackService.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,0BAA0B,EAC1B,YAAY,EACb,MAAM,SAAS,CAAA;AAmChB;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4B;IAE3D,OAAO;IAIP;;;;OAIG;IACH,IAAW,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAE5D;IAED;;;;;;OAMG;WACiB,MAAM,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAU1F;;;;;OAKG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrC;;;;;;OAMG;IACU,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQpD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import Logger from './Logger';
|
|
3
|
+
import { processColor, processLogLevel, processSarifPath } from './Processors';
|
|
4
|
+
import { SlackMessageBuilder } from './SlackMessageBuilder';
|
|
5
|
+
async function initialize(opts) {
|
|
6
|
+
const slackMessages = new Map();
|
|
7
|
+
const sarifFiles = processSarifPath(opts.sarifPath);
|
|
8
|
+
if (sarifFiles.length === 0) {
|
|
9
|
+
throw new Error(`No SARIF files found at the provided path: ${opts.sarifPath}`);
|
|
10
|
+
}
|
|
11
|
+
for (const sarifFile of sarifFiles) {
|
|
12
|
+
const jsonString = await fs.readFile(sarifFile, 'utf8');
|
|
13
|
+
const messageBuilder = new SlackMessageBuilder(opts.webhookUrl, {
|
|
14
|
+
username: opts.username,
|
|
15
|
+
iconUrl: opts.iconUrl,
|
|
16
|
+
color: processColor(opts.color),
|
|
17
|
+
sarif: JSON.parse(jsonString)
|
|
18
|
+
});
|
|
19
|
+
if (opts.header?.include) {
|
|
20
|
+
messageBuilder.withHeader(opts.header?.value);
|
|
21
|
+
}
|
|
22
|
+
if (opts.footer?.include) {
|
|
23
|
+
messageBuilder.withFooter(opts.footer?.value);
|
|
24
|
+
}
|
|
25
|
+
if (opts.actor?.include) {
|
|
26
|
+
messageBuilder.withActor(opts.actor?.value);
|
|
27
|
+
}
|
|
28
|
+
if (opts.run?.include) {
|
|
29
|
+
messageBuilder.withRun();
|
|
30
|
+
}
|
|
31
|
+
slackMessages.set(sarifFile, messageBuilder);
|
|
32
|
+
}
|
|
33
|
+
return slackMessages;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Service to convert SARIF files to Slack messages and send them.
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export class SarifToSlackService {
|
|
40
|
+
_slackMessages;
|
|
41
|
+
constructor() {
|
|
42
|
+
this._slackMessages = new Map();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Gets the Slack messages prepared for each SARIF file.
|
|
46
|
+
* @returns A read-only map where keys are SARIF file paths and values are SlackMessage instances.
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
get slackMessages() {
|
|
50
|
+
return this._slackMessages;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates an instance of SarifToSlackService.
|
|
54
|
+
* @param opts - Options for the service, including webhook URL, SARIF path, and other configurations.
|
|
55
|
+
* @returns A promise that resolves to an instance of SarifToSlackService.
|
|
56
|
+
* @throws Error if no SARIF files are found at the provided path.
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
static async create(opts) {
|
|
60
|
+
Logger.initialize({
|
|
61
|
+
logLevel: processLogLevel(opts.logLevel)
|
|
62
|
+
});
|
|
63
|
+
const instance = new SarifToSlackService();
|
|
64
|
+
const map = await initialize(opts);
|
|
65
|
+
map.forEach((val, key) => instance._slackMessages.set(key, val));
|
|
66
|
+
return instance;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Sends all prepared Slack messages.
|
|
70
|
+
* @returns A promise that resolves when all messages have been sent.
|
|
71
|
+
* @throws Error if a Slack message was not prepared for a SARIF path.
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
async sendAll() {
|
|
75
|
+
for (const sarifPath of this._slackMessages.keys()) {
|
|
76
|
+
await this.send(sarifPath);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Sends a Slack message for a specific SARIF path.
|
|
81
|
+
* @param sarifPath - The path of the SARIF file for which the message should be sent.
|
|
82
|
+
* @returns A promise that resolves when the message has been sent.
|
|
83
|
+
* @throws Error if a Slack message was not prepared for the given SARIF path.
|
|
84
|
+
* @public
|
|
85
|
+
*/
|
|
86
|
+
async send(sarifPath) {
|
|
87
|
+
const message = this._slackMessages.get(sarifPath);
|
|
88
|
+
if (!message) {
|
|
89
|
+
throw new Error(`Slack message was not prepared for SARIF path: ${sarifPath}.`);
|
|
90
|
+
}
|
|
91
|
+
const text = await message.send();
|
|
92
|
+
Logger.info(`Message sent for ${sarifPath} file. Status:`, text);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=SarifToSlackService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SarifToSlackService.js","sourceRoot":"","sources":["../src/SarifToSlackService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlackMessageBuilder.d.ts","sourceRoot":"","sources":["../src/SlackMessageBuilder.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { IncomingWebhook } from '@slack/webhook';
|
|
2
|
+
/**
|
|
3
|
+
* Class for building and sending Slack messages based on SARIF logs.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export class SlackMessageBuilder {
|
|
7
|
+
webhook;
|
|
8
|
+
gitHubServerUrl;
|
|
9
|
+
color;
|
|
10
|
+
header;
|
|
11
|
+
footer;
|
|
12
|
+
actor;
|
|
13
|
+
runId;
|
|
14
|
+
sarif;
|
|
15
|
+
constructor(url, opts) {
|
|
16
|
+
this.webhook = new IncomingWebhook(url, {
|
|
17
|
+
username: opts.username || 'SARIF results',
|
|
18
|
+
icon_url: opts.iconUrl
|
|
19
|
+
});
|
|
20
|
+
this.color = opts.color;
|
|
21
|
+
this.sarif = opts.sarif;
|
|
22
|
+
this.gitHubServerUrl = process.env.GITHUB_SERVER_URL || 'https://github.com';
|
|
23
|
+
}
|
|
24
|
+
withHeader(header) {
|
|
25
|
+
this.header = {
|
|
26
|
+
type: 'header',
|
|
27
|
+
text: {
|
|
28
|
+
type: 'plain_text',
|
|
29
|
+
text: header || process.env.GITHUB_REPOSITORY || 'SARIF results'
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
withActor(actor) {
|
|
34
|
+
this.actor = actor || process.env.GITHUB_ACTOR;
|
|
35
|
+
}
|
|
36
|
+
withRun() {
|
|
37
|
+
this.runId = process.env.GITHUB_RUN_ID;
|
|
38
|
+
}
|
|
39
|
+
withFooter(footer) {
|
|
40
|
+
const repoName = 'fabasoad/sarif-to-slack-action';
|
|
41
|
+
this.footer = {
|
|
42
|
+
type: 'context',
|
|
43
|
+
elements: [{
|
|
44
|
+
type: footer ? 'plain_text' : 'mrkdwn',
|
|
45
|
+
text: footer || `Generated by <${this.gitHubServerUrl}/${repoName}|${repoName}>`
|
|
46
|
+
}],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async send() {
|
|
50
|
+
const blocks = [];
|
|
51
|
+
if (this.header) {
|
|
52
|
+
blocks.push(this.header);
|
|
53
|
+
}
|
|
54
|
+
blocks.push({
|
|
55
|
+
type: 'section',
|
|
56
|
+
text: {
|
|
57
|
+
type: 'mrkdwn',
|
|
58
|
+
text: this.buildText()
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (this.footer) {
|
|
62
|
+
blocks.push(this.footer);
|
|
63
|
+
}
|
|
64
|
+
const { text } = await this.webhook.send({
|
|
65
|
+
attachments: [{ color: this.color, blocks }]
|
|
66
|
+
});
|
|
67
|
+
return text;
|
|
68
|
+
}
|
|
69
|
+
buildText() {
|
|
70
|
+
const text = [];
|
|
71
|
+
if (this.actor) {
|
|
72
|
+
const actorUrl = `${this.gitHubServerUrl}/${this.actor}`;
|
|
73
|
+
text.push(`_Triggered by <${actorUrl}|${this.actor}>_`);
|
|
74
|
+
}
|
|
75
|
+
text.push(this.composeSummary());
|
|
76
|
+
if (this.runId) {
|
|
77
|
+
let runText = 'Job ';
|
|
78
|
+
if (process.env.GITHUB_REPOSITORY) {
|
|
79
|
+
runText += `<${this.gitHubServerUrl}/${process.env.GITHUB_REPOSITORY}/actions/runs/${this.runId}|#${this.runId}>`;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
runText += `#${this.runId}`;
|
|
83
|
+
}
|
|
84
|
+
text.push(runText);
|
|
85
|
+
}
|
|
86
|
+
return text.join('\n');
|
|
87
|
+
}
|
|
88
|
+
composeRunSummary(toolName, map) {
|
|
89
|
+
const levelsText = [];
|
|
90
|
+
for (const [level, count] of map.entries()) {
|
|
91
|
+
const levelCapitalized = level.charAt(0).toUpperCase() + level.slice(1);
|
|
92
|
+
levelsText.push(`*${levelCapitalized}*: ${count}`);
|
|
93
|
+
}
|
|
94
|
+
return `*${toolName}*\n${levelsText.join(', ')}`;
|
|
95
|
+
}
|
|
96
|
+
composeSummary() {
|
|
97
|
+
const data = new Map();
|
|
98
|
+
for (const run of this.sarif.runs) {
|
|
99
|
+
const toolName = run.tool.driver.name;
|
|
100
|
+
if (!data.has(toolName)) {
|
|
101
|
+
data.set(toolName, new Map());
|
|
102
|
+
}
|
|
103
|
+
const results = run.results ?? [];
|
|
104
|
+
for (const result of results) {
|
|
105
|
+
const level = this.tryGetLevel(run, result);
|
|
106
|
+
const count = data.get(toolName)?.get(level) || 0;
|
|
107
|
+
data.get(toolName)?.set(level, count + 1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const summaries = [];
|
|
111
|
+
for (const [toolName, map] of data.entries()) {
|
|
112
|
+
summaries.push(this.composeRunSummary(toolName, map));
|
|
113
|
+
}
|
|
114
|
+
return summaries.join('\n');
|
|
115
|
+
}
|
|
116
|
+
tryGetLevel(run, result) {
|
|
117
|
+
if (result.level) {
|
|
118
|
+
return result.level;
|
|
119
|
+
}
|
|
120
|
+
const ruleData = {};
|
|
121
|
+
if (result.rule) {
|
|
122
|
+
if (result.rule?.index) {
|
|
123
|
+
ruleData.index = result.rule.index;
|
|
124
|
+
}
|
|
125
|
+
if (result.rule?.id) {
|
|
126
|
+
ruleData.id = result.rule.id;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (!ruleData.index && result.ruleIndex) {
|
|
130
|
+
ruleData.index = result.ruleIndex;
|
|
131
|
+
}
|
|
132
|
+
if (ruleData.index
|
|
133
|
+
&& run.tool.driver?.rules
|
|
134
|
+
&& ruleData.index < run.tool.driver.rules.length) {
|
|
135
|
+
const rule = run.tool.driver.rules[ruleData.index];
|
|
136
|
+
if (rule.properties && 'problem.severity' in rule.properties) {
|
|
137
|
+
return rule.properties['problem.severity'];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return 'unknown';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=SlackMessageBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlackMessageBuilder.js","sourceRoot":"","sources":["../src/SlackMessageBuilder.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sarif to Slack message converter library.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* This library provides a service to send a Slack messages based on the provided
|
|
6
|
+
* SARIF (Static Analysis Results Interchange Format) files.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { SarifToSlackService } from 'sarif-to-slack';
|
|
11
|
+
*
|
|
12
|
+
* const service = new SarifToSlackService({
|
|
13
|
+
* webhookUrl: 'https://hooks.slack.com/services/your/webhook/url',
|
|
14
|
+
* sarifPath: 'path/to/your/sarif/file.sarif',
|
|
15
|
+
* logLevel: 'info',
|
|
16
|
+
* username: 'SARIF Bot',
|
|
17
|
+
* iconUrl: 'https://example.com/icon.png',
|
|
18
|
+
* color: '#36a64f',
|
|
19
|
+
* header: {
|
|
20
|
+
* include: true,
|
|
21
|
+
* value: 'SARIF Analysis Results'
|
|
22
|
+
* },
|
|
23
|
+
* footer: {
|
|
24
|
+
* include: true,
|
|
25
|
+
* value: 'Generated by @fabasoad/sarif-to-slack'
|
|
26
|
+
* },
|
|
27
|
+
* actor: {
|
|
28
|
+
* include: true,
|
|
29
|
+
* value: 'fabasoad'
|
|
30
|
+
* },
|
|
31
|
+
* run: {
|
|
32
|
+
* include: true
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* await service.sendAll();
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @see {@link SarifToSlackService}
|
|
39
|
+
*
|
|
40
|
+
* @packageDocumentation
|
|
41
|
+
*/
|
|
42
|
+
export { SarifToSlackService } from './SarifToSlackService';
|
|
43
|
+
export { IncludeAwareProps, IncludeAwareWithValueProps, LogLevel, Sarif, SarifToSlackServiceOptions, SlackMessage, } from './types';
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EACL,iBAAiB,EACjB,0BAA0B,EAC1B,QAAQ,EACR,KAAK,EACL,0BAA0B,EAC1B,YAAY,GACb,MAAM,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Copyright (c) Yevhen Fabizhevskyi. All rights reserved. Licensed under the MIT license.
|
|
2
|
+
/**
|
|
3
|
+
* Sarif to Slack message converter library.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* This library provides a service to send a Slack messages based on the provided
|
|
7
|
+
* SARIF (Static Analysis Results Interchange Format) files.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { SarifToSlackService } from 'sarif-to-slack';
|
|
12
|
+
*
|
|
13
|
+
* const service = new SarifToSlackService({
|
|
14
|
+
* webhookUrl: 'https://hooks.slack.com/services/your/webhook/url',
|
|
15
|
+
* sarifPath: 'path/to/your/sarif/file.sarif',
|
|
16
|
+
* logLevel: 'info',
|
|
17
|
+
* username: 'SARIF Bot',
|
|
18
|
+
* iconUrl: 'https://example.com/icon.png',
|
|
19
|
+
* color: '#36a64f',
|
|
20
|
+
* header: {
|
|
21
|
+
* include: true,
|
|
22
|
+
* value: 'SARIF Analysis Results'
|
|
23
|
+
* },
|
|
24
|
+
* footer: {
|
|
25
|
+
* include: true,
|
|
26
|
+
* value: 'Generated by @fabasoad/sarif-to-slack'
|
|
27
|
+
* },
|
|
28
|
+
* actor: {
|
|
29
|
+
* include: true,
|
|
30
|
+
* value: 'fabasoad'
|
|
31
|
+
* },
|
|
32
|
+
* run: {
|
|
33
|
+
* include: true
|
|
34
|
+
* },
|
|
35
|
+
* });
|
|
36
|
+
* await service.sendAll();
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @see {@link SarifToSlackService}
|
|
40
|
+
*
|
|
41
|
+
* @packageDocumentation
|
|
42
|
+
*/
|
|
43
|
+
export { SarifToSlackService } from './SarifToSlackService';
|
|
44
|
+
export { LogLevel, } from './types';
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAGL,QAAQ,GAIT,MAAM,SAAS,CAAA"}
|
package/dist/sarif-to-slack.d.ts
CHANGED
|
@@ -106,7 +106,7 @@ export declare type Sarif = Log;
|
|
|
106
106
|
* @public
|
|
107
107
|
*/
|
|
108
108
|
export declare class SarifToSlackService {
|
|
109
|
-
private _slackMessages;
|
|
109
|
+
private readonly _slackMessages;
|
|
110
110
|
private constructor();
|
|
111
111
|
/**
|
|
112
112
|
* Gets the Slack messages prepared for each SARIF file.
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Log } from 'sarif';
|
|
2
|
+
/**
|
|
3
|
+
* Type representing a SARIF log.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export type Sarif = Log;
|
|
7
|
+
/**
|
|
8
|
+
* Interface for a Slack message that can be sent.
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export interface SlackMessage {
|
|
12
|
+
/**
|
|
13
|
+
* Sends the Slack message.
|
|
14
|
+
* @returns A promise that resolves to the response from the Slack webhook.
|
|
15
|
+
*/
|
|
16
|
+
send: () => Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* The SARIF log associated with this Slack message.
|
|
19
|
+
*/
|
|
20
|
+
sarif: Sarif;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Enum representing log levels for the service.
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export declare enum LogLevel {
|
|
27
|
+
/**
|
|
28
|
+
* Represents the most verbose logging level, typically used for detailed debugging information.
|
|
29
|
+
*/
|
|
30
|
+
Silly = 0,
|
|
31
|
+
/**
|
|
32
|
+
* Represents a logging level for tracing the flow of the application.
|
|
33
|
+
*/
|
|
34
|
+
Trace = 1,
|
|
35
|
+
/**
|
|
36
|
+
* Represents a logging level for debugging information that is less verbose than silly.
|
|
37
|
+
*/
|
|
38
|
+
Debug = 2,
|
|
39
|
+
/**
|
|
40
|
+
* Represents a logging level for general informational messages that highlight the progress of the application.
|
|
41
|
+
*/
|
|
42
|
+
Info = 3,
|
|
43
|
+
/**
|
|
44
|
+
* Represents a logging level for potentially harmful situations that require attention.
|
|
45
|
+
*/
|
|
46
|
+
Warning = 4,
|
|
47
|
+
/**
|
|
48
|
+
* Represents a logging level for error conditions that do not require immediate action but should be noted.
|
|
49
|
+
*/
|
|
50
|
+
Error = 5,
|
|
51
|
+
/**
|
|
52
|
+
* Represents a logging level for critical errors that require immediate attention and may cause the application to terminate.
|
|
53
|
+
*/
|
|
54
|
+
Fatal = 6
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Type representing properties that indicate whether to include certain information
|
|
58
|
+
* in the Slack message.
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
export type IncludeAwareProps = {
|
|
62
|
+
include: boolean;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Type representing properties that indicate whether to include certain information
|
|
66
|
+
* in the Slack message, along with an optional value.
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export type IncludeAwareWithValueProps = IncludeAwareProps & {
|
|
70
|
+
value?: string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Options for the SarifToSlackService.
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export type SarifToSlackServiceOptions = {
|
|
77
|
+
webhookUrl: string;
|
|
78
|
+
sarifPath: string;
|
|
79
|
+
username?: string;
|
|
80
|
+
iconUrl?: string;
|
|
81
|
+
color?: string;
|
|
82
|
+
logLevel?: LogLevel | string;
|
|
83
|
+
header?: IncludeAwareWithValueProps;
|
|
84
|
+
footer?: IncludeAwareWithValueProps;
|
|
85
|
+
actor?: IncludeAwareWithValueProps;
|
|
86
|
+
run?: IncludeAwareProps;
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAEhC;;;GAGG;AACH,MAAM,MAAM,KAAK,GAAG,GAAG,CAAA;AAEvB;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3B;;OAEG;IACH,KAAK,EAAE,KAAK,CAAA;CACb;AAED;;;GAGG;AACH,oBAAY,QAAQ;IAClB;;OAEG;IACH,KAAK,IAAI;IACT;;OAEG;IACH,KAAK,IAAI;IACT;;OAEG;IACH,KAAK,IAAI;IACT;;OAEG;IACH,IAAI,IAAI;IACR;;OAEG;IACH,OAAO,IAAI;IACX;;OAEG;IACH,KAAK,IAAI;IACT;;OAEG;IACH,KAAK,IAAI;CACV;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,iBAAiB,GAAG;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,0BAA0B,GAAG;IAEvC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,KAAK,CAAC,EAAE,0BAA0B,CAAC;IACnC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB,CAAA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum representing log levels for the service.
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export var LogLevel;
|
|
6
|
+
(function (LogLevel) {
|
|
7
|
+
/**
|
|
8
|
+
* Represents the most verbose logging level, typically used for detailed debugging information.
|
|
9
|
+
*/
|
|
10
|
+
LogLevel[LogLevel["Silly"] = 0] = "Silly";
|
|
11
|
+
/**
|
|
12
|
+
* Represents a logging level for tracing the flow of the application.
|
|
13
|
+
*/
|
|
14
|
+
LogLevel[LogLevel["Trace"] = 1] = "Trace";
|
|
15
|
+
/**
|
|
16
|
+
* Represents a logging level for debugging information that is less verbose than silly.
|
|
17
|
+
*/
|
|
18
|
+
LogLevel[LogLevel["Debug"] = 2] = "Debug";
|
|
19
|
+
/**
|
|
20
|
+
* Represents a logging level for general informational messages that highlight the progress of the application.
|
|
21
|
+
*/
|
|
22
|
+
LogLevel[LogLevel["Info"] = 3] = "Info";
|
|
23
|
+
/**
|
|
24
|
+
* Represents a logging level for potentially harmful situations that require attention.
|
|
25
|
+
*/
|
|
26
|
+
LogLevel[LogLevel["Warning"] = 4] = "Warning";
|
|
27
|
+
/**
|
|
28
|
+
* Represents a logging level for error conditions that do not require immediate action but should be noted.
|
|
29
|
+
*/
|
|
30
|
+
LogLevel[LogLevel["Error"] = 5] = "Error";
|
|
31
|
+
/**
|
|
32
|
+
* Represents a logging level for critical errors that require immediate attention and may cause the application to terminate.
|
|
33
|
+
*/
|
|
34
|
+
LogLevel[LogLevel["Fatal"] = 6] = "Fatal";
|
|
35
|
+
})(LogLevel || (LogLevel = {}));
|
|
36
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwBA;;;GAGG;AACH,MAAM,CAAN,IAAY,QA6BX;AA7BD,WAAY,QAAQ;IAClB;;OAEG;IACH,yCAAS,CAAA;IACT;;OAEG;IACH,yCAAS,CAAA;IACT;;OAEG;IACH,yCAAS,CAAA;IACT;;OAEG;IACH,uCAAQ,CAAA;IACR;;OAEG;IACH,6CAAW,CAAA;IACX;;OAEG;IACH,yCAAS,CAAA;IACT;;OAEG;IACH,yCAAS,CAAA;AACX,CAAC,EA7BW,QAAQ,KAAR,QAAQ,QA6BnB"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fabasoad/sarif-to-slack",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "TypeScript library to send results of SARIF file to Slack webhook URL.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
6
7
|
"typings": "dist/index.d.ts",
|
|
8
|
+
"private": false,
|
|
7
9
|
"scripts": {
|
|
8
10
|
"lint": "biome lint --write src",
|
|
9
11
|
"test": "jest --config=jest.config.json --json --outputFile=jest-report.json --coverage",
|
|
10
12
|
"clean": "rm -rf coverage && rm -rf temp",
|
|
11
13
|
"clean:unsafe": "rm -f package-lock.json && rm -rf node_modules && rm -rf dist && rm -rf lib",
|
|
14
|
+
"tsc": "tsc",
|
|
12
15
|
"build": "tsc && api-extractor run --local --verbose",
|
|
13
16
|
"prepublishOnly": "npm run build",
|
|
14
17
|
"version:patch": "npm version patch --commit-hooks --git-tag-version --message 'chore: bump to version %s'",
|
|
@@ -46,9 +46,10 @@ async function initialize(opts: SarifToSlackServiceOptions): Promise<Map<string,
|
|
|
46
46
|
* @public
|
|
47
47
|
*/
|
|
48
48
|
export class SarifToSlackService {
|
|
49
|
-
private _slackMessages:
|
|
49
|
+
private readonly _slackMessages: Map<string, SlackMessage>;
|
|
50
50
|
|
|
51
51
|
private constructor() {
|
|
52
|
+
this._slackMessages = new Map<string, SlackMessage>();
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/**
|
|
@@ -72,7 +73,8 @@ export class SarifToSlackService {
|
|
|
72
73
|
logLevel: processLogLevel(opts.logLevel)
|
|
73
74
|
})
|
|
74
75
|
const instance: SarifToSlackService = new SarifToSlackService()
|
|
75
|
-
|
|
76
|
+
const map: Map<string, SlackMessage> = await initialize(opts)
|
|
77
|
+
map.forEach((val: SlackMessage, key: string) => instance._slackMessages.set(key, val))
|
|
76
78
|
return instance
|
|
77
79
|
}
|
|
78
80
|
|
package/tsconfig.json
CHANGED
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json.schemastore.org/tsconfig",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"
|
|
5
|
-
"
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"outDir": "dist",
|
|
6
6
|
"declaration": true,
|
|
7
|
-
"
|
|
7
|
+
"declarationDir": "dist",
|
|
8
8
|
"declarationMap": true,
|
|
9
|
-
"
|
|
10
|
-
"
|
|
9
|
+
"target": "es2024",
|
|
10
|
+
"lib": ["es2024"],
|
|
11
|
+
"module": "es2022",
|
|
12
|
+
"moduleResolution": "node",
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"noImplicitThis": true,
|
|
15
|
+
"alwaysStrict": true,
|
|
16
|
+
"noFallthroughCasesInSwitch": true,
|
|
17
|
+
"forceConsistentCasingInFileNames": true,
|
|
18
|
+
"downlevelIteration": true,
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noImplicitAny": true,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"allowSyntheticDefaultImports": true,
|
|
24
|
+
"emitDecoratorMetadata": true,
|
|
25
|
+
"experimentalDecorators": true,
|
|
26
|
+
"typeRoots": ["node_modules/@types", "@types"],
|
|
27
|
+
"skipLibCheck": true,
|
|
11
28
|
"newLine": "lf",
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
]
|
|
15
|
-
"outDir": "lib"
|
|
29
|
+
"sourceMap": true,
|
|
30
|
+
"stripInternal": true,
|
|
31
|
+
"types": ["node", "jest"]
|
|
16
32
|
},
|
|
17
|
-
"include": [
|
|
18
|
-
|
|
19
|
-
],
|
|
20
|
-
"exclude": ["node_modules", "tests"]
|
|
33
|
+
"include": ["src"],
|
|
34
|
+
"exclude": ["node_modules", "dist", "tests"]
|
|
21
35
|
}
|