@fabasoad/sarif-to-slack 1.3.5 → 1.4.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.
- package/.github/workflows/security.yml +1 -0
- package/.github/workflows/send-sarif-to-slack.yml +39 -15
- package/README.md +8 -7
- package/dist/Logger.js +40 -30
- package/dist/SarifToSlackClient.d.ts +0 -1
- package/dist/SarifToSlackClient.d.ts.map +1 -1
- package/dist/SarifToSlackClient.js +11 -8
- package/dist/globalState.d.ts +2 -0
- package/dist/globalState.d.ts.map +1 -0
- package/dist/globalState.js +2 -0
- package/dist/index.cjs +111 -81
- package/dist/index.d.ts +40 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/model/Finding.js +7 -5
- package/dist/model/FindingArray.js +1 -1
- package/dist/model/SendIf.js +1 -1
- package/dist/model/SlackMessage.js +6 -6
- package/dist/model/color/Color.d.ts.map +1 -1
- package/dist/model/color/Color.js +1 -1
- package/dist/model/color/ColorIdentification.js +5 -5
- package/dist/model/color/ColorOptions.d.ts.map +1 -1
- package/dist/processors/CodeQLProcessor.js +1 -1
- package/dist/processors/CommonProcessor.js +1 -1
- package/dist/processors/ProcessorFactory.js +1 -1
- package/dist/processors/SnykProcessor.js +2 -1
- package/dist/representations/CompactGroupByRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/CompactTotalPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactTotalPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactTotalRepresentation.js +1 -1
- package/dist/representations/Representation.js +1 -1
- package/dist/representations/RepresentationFactory.js +1 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupByRunRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNameRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/TableGroupRepresentation.d.ts +0 -1
- package/dist/representations/TableGroupRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupRepresentation.js +3 -3
- package/dist/representations/table/Cell.d.ts.map +1 -1
- package/dist/representations/table/Cell.js +1 -1
- package/dist/representations/table/Column.d.ts +0 -1
- package/dist/representations/table/Column.d.ts.map +1 -1
- package/dist/representations/table/Column.js +4 -3
- package/dist/representations/table/Row.d.ts +0 -1
- package/dist/representations/table/Row.d.ts.map +1 -1
- package/dist/representations/table/Row.js +3 -3
- package/dist/representations/table/Table.d.ts.map +1 -1
- package/dist/representations/table/Table.js +1 -1
- package/dist/system.js +5 -5
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types.d.ts +29 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -1
- package/dist/utils/Comparators.js +1 -1
- package/dist/utils/ExtendedArray.js +1 -1
- package/dist/utils/FileUtils.js +2 -2
- package/dist/utils/SarifUtils.js +1 -1
- package/dist/utils/StringUtils.js +1 -1
- package/etc/sarif-to-slack.api.md +21 -1
- package/jest.config.json +4 -4
- package/package.json +5 -4
- package/src/Logger.ts +50 -34
- package/src/SarifToSlackClient.ts +73 -68
- package/src/globalState.ts +11 -0
- package/src/index.ts +23 -12
- package/src/model/Finding.ts +36 -35
- package/src/model/FindingArray.ts +5 -5
- package/src/model/SendIf.ts +25 -25
- package/src/model/SlackMessage.ts +49 -49
- package/src/model/color/Color.ts +7 -7
- package/src/model/color/ColorIdentification.ts +77 -77
- package/src/model/color/ColorOptions.ts +1 -1
- package/src/processors/CodeQLProcessor.ts +3 -3
- package/src/processors/CommonProcessor.ts +24 -24
- package/src/processors/ProcessorFactory.ts +9 -9
- package/src/processors/SnykProcessor.ts +3 -2
- package/src/representations/CompactGroupByRepresentation.ts +20 -20
- package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunRepresentation.ts +10 -10
- package/src/representations/CompactGroupBySarifPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifRepresentation.ts +11 -11
- package/src/representations/CompactGroupByToolNamePerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNameRepresentation.ts +10 -10
- package/src/representations/CompactTotalPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactTotalPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactTotalRepresentation.ts +5 -5
- package/src/representations/Representation.ts +8 -8
- package/src/representations/RepresentationFactory.ts +32 -32
- package/src/representations/TableGroupByRunPerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupByRunPerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupByRunRepresentation.ts +5 -5
- package/src/representations/TableGroupBySarifPerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupBySarifPerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupBySarifRepresentation.ts +9 -9
- package/src/representations/TableGroupByToolNamePerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupByToolNamePerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupByToolNameRepresentation.ts +4 -4
- package/src/representations/TableGroupRepresentation.ts +32 -32
- package/src/representations/table/Cell.ts +8 -8
- package/src/representations/table/Column.ts +13 -13
- package/src/representations/table/Row.ts +17 -17
- package/src/representations/table/Table.ts +21 -21
- package/src/system.ts +5 -5
- package/src/types.ts +43 -13
- package/src/utils/Comparators.ts +6 -6
- package/src/utils/ExtendedArray.ts +1 -1
- package/src/utils/FileUtils.ts +3 -3
- package/src/utils/SarifUtils.ts +6 -6
- package/src/utils/StringUtils.ts +3 -3
- package/tests/integration/SendSarifToSlack.spec.ts +73 -67
- package/tests/representations/CompactGroupByRunPerLevelRepresentation.spec.ts +121 -0
- package/tests/representations/CompactGroupByRunPerSeverityRepresentation.spec.ts +122 -0
- package/tests/representations/CompactGroupBySarifPerLevelRepresentation.spec.ts +132 -0
- package/tests/representations/CompactGroupBySarifPerSeverityRepresentation.spec.ts +133 -0
- package/tsconfig.json +1 -1
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import type { SarifModel } from '../types'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
3
|
-
import TableGroupRepresentation from './TableGroupRepresentation'
|
|
1
|
+
import type { SarifModel } from '../types';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
|
+
import TableGroupRepresentation from './TableGroupRepresentation';
|
|
4
4
|
|
|
5
5
|
export default abstract class TableGroupBySarifRepresentation<
|
|
6
6
|
KPer extends keyof Pick<Finding, 'level' | 'severity'>
|
|
7
7
|
> extends TableGroupRepresentation<'sarifPath', KPer> {
|
|
8
|
-
private readonly _fileToNumberMap = new Map<string, number>()
|
|
8
|
+
private readonly _fileToNumberMap = new Map<string, number>();
|
|
9
9
|
|
|
10
10
|
protected constructor(
|
|
11
11
|
keyPer: KPer,
|
|
12
12
|
values: string[],
|
|
13
|
-
model: SarifModel
|
|
13
|
+
model: SarifModel,
|
|
14
14
|
) {
|
|
15
|
-
super('sarifPath', keyPer, values, model)
|
|
15
|
+
super('sarifPath', keyPer, values, model);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
protected override keyByToString(key: Finding['sarifPath']): string {
|
|
19
|
-
const keyStr: string = key.toString()
|
|
19
|
+
const keyStr: string = key.toString();
|
|
20
20
|
if (!this._fileToNumberMap.has(keyStr)) {
|
|
21
|
-
this._fileToNumberMap.set(keyStr, this._fileToNumberMap.size + 1)
|
|
21
|
+
this._fileToNumberMap.set(keyStr, this._fileToNumberMap.size + 1);
|
|
22
22
|
}
|
|
23
|
-
return this._fileToNumberMap.get(keyStr)?.toString() as string
|
|
23
|
+
return this._fileToNumberMap.get(keyStr)?.toString() as string;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type SarifModel, SecurityLevelValues } from '../types'
|
|
1
|
+
import { type SarifModel, SecurityLevelValues } from '../types';
|
|
2
2
|
import TableGroupByToolNameRepresentation
|
|
3
|
-
from './TableGroupByToolNameRepresentation'
|
|
3
|
+
from './TableGroupByToolNameRepresentation';
|
|
4
4
|
|
|
5
5
|
export default class TableGroupByToolNamePerLevelRepresentation extends TableGroupByToolNameRepresentation<'level'> {
|
|
6
6
|
|
|
7
7
|
public constructor(model: SarifModel) {
|
|
8
|
-
super('level', SecurityLevelValues, model)
|
|
8
|
+
super('level', SecurityLevelValues, model);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type SarifModel, SecuritySeverityValues } from '../types'
|
|
1
|
+
import { type SarifModel, SecuritySeverityValues } from '../types';
|
|
2
2
|
import TableGroupByToolNameRepresentation
|
|
3
|
-
from './TableGroupByToolNameRepresentation'
|
|
3
|
+
from './TableGroupByToolNameRepresentation';
|
|
4
4
|
|
|
5
5
|
export default class TableGroupByToolNamePerSeverityRepresentation extends TableGroupByToolNameRepresentation<'severity'> {
|
|
6
6
|
|
|
7
7
|
public constructor(model: SarifModel) {
|
|
8
|
-
super('severity', SecuritySeverityValues, model)
|
|
8
|
+
super('severity', SecuritySeverityValues, model);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { SarifModel } from '../types'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
1
|
+
import type { SarifModel } from '../types';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
3
|
import TableGroupRepresentation from './TableGroupRepresentation';
|
|
4
4
|
|
|
5
5
|
export default abstract class TableGroupByToolNameRepresentation<
|
|
@@ -8,8 +8,8 @@ export default abstract class TableGroupByToolNameRepresentation<
|
|
|
8
8
|
protected constructor(
|
|
9
9
|
keyPer: KPer,
|
|
10
10
|
values: string[],
|
|
11
|
-
model: SarifModel
|
|
11
|
+
model: SarifModel,
|
|
12
12
|
) {
|
|
13
|
-
super('toolName', keyPer, values, model)
|
|
13
|
+
super('toolName', keyPer, values, model);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
import type { SarifModel } from '../types'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
3
|
-
import Representation from './Representation'
|
|
4
|
-
import Table from './table/Table'
|
|
5
|
-
import Logger from '../Logger'
|
|
1
|
+
import type { SarifModel } from '../types';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
|
+
import Representation from './Representation';
|
|
4
|
+
import Table from './table/Table';
|
|
5
|
+
import Logger from '../Logger';
|
|
6
6
|
|
|
7
7
|
export default abstract class TableGroupRepresentation<
|
|
8
8
|
KBy extends keyof Pick<Finding, 'toolName' | 'runId' | 'sarifPath'>,
|
|
9
9
|
KPer extends keyof Pick<Finding, 'level' | 'severity'>
|
|
10
10
|
> extends Representation {
|
|
11
|
-
private readonly _logger = new Logger('TableGroupRepresentation');
|
|
12
11
|
|
|
13
12
|
protected constructor(
|
|
14
13
|
private readonly _keyBy: KBy,
|
|
15
14
|
private readonly _keyPer: KPer,
|
|
16
15
|
private readonly _values: string[],
|
|
17
|
-
model: SarifModel
|
|
16
|
+
model: SarifModel,
|
|
18
17
|
) {
|
|
19
|
-
super(model, 'toolName')
|
|
18
|
+
super(model, 'toolName');
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
private groupFindingsPer(findings: Finding[]): Finding[][] {
|
|
23
22
|
return findings.reduce(
|
|
24
23
|
(grouped: Finding[][], f: Finding): Finding[][] => {
|
|
25
|
-
grouped[f[this._keyPer]].push(f)
|
|
26
|
-
return grouped
|
|
24
|
+
grouped[f[this._keyPer]].push(f);
|
|
25
|
+
return grouped;
|
|
27
26
|
},
|
|
28
|
-
Array.from({ length: this._values.length }, (): Finding[] => [] as Finding[])
|
|
29
|
-
)
|
|
27
|
+
Array.from({ length: this._values.length }, (): Finding[] => [] as Finding[]),
|
|
28
|
+
);
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
protected keyByToString(key: Finding[KBy]): string {
|
|
33
|
-
return key.toString()
|
|
32
|
+
return key.toString();
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
private groupFindingsBy(findings: Finding[]): Map<string, Finding[]> {
|
|
37
36
|
return findings.reduce(
|
|
38
37
|
(grouped: Map<string, Finding[]>, f: Finding): Map<string, Finding[]> => {
|
|
39
|
-
const key: string = this.keyByToString(f[this._keyBy])
|
|
38
|
+
const key: string = this.keyByToString(f[this._keyBy]);
|
|
40
39
|
if (!grouped.has(key)) {
|
|
41
|
-
grouped.set(key, [])
|
|
40
|
+
grouped.set(key, []);
|
|
42
41
|
}
|
|
43
|
-
grouped.get(key)?.push(f)
|
|
44
|
-
return grouped
|
|
42
|
+
grouped.get(key)?.push(f);
|
|
43
|
+
return grouped;
|
|
45
44
|
},
|
|
46
|
-
new Map<string, Finding[]>()
|
|
47
|
-
)
|
|
45
|
+
new Map<string, Finding[]>(),
|
|
46
|
+
);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
private get title(): string {
|
|
51
50
|
switch (this._keyBy) {
|
|
52
|
-
case 'toolName': return 'Tool'
|
|
53
|
-
case 'runId': return 'Run #'
|
|
54
|
-
case 'sarifPath': return 'File #'
|
|
55
|
-
default: return ''
|
|
51
|
+
case 'toolName': return 'Tool';
|
|
52
|
+
case 'runId': return 'Run #';
|
|
53
|
+
case 'sarifPath': return 'File #';
|
|
54
|
+
default: return '';
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
public override compose(): string {
|
|
60
|
-
const
|
|
59
|
+
const logger = new Logger();
|
|
60
|
+
const groupedBy: Map<string, Finding[]> = this.groupFindingsBy(this._model.findings);
|
|
61
61
|
const table = new Table({
|
|
62
62
|
main: this.title,
|
|
63
63
|
rows: Array.from(groupedBy.keys()),
|
|
64
64
|
columns: this._values,
|
|
65
|
-
})
|
|
66
|
-
let i = 0
|
|
65
|
+
});
|
|
66
|
+
let i: number = 0;
|
|
67
67
|
for (const findings of groupedBy.values()) {
|
|
68
|
-
const grouped: Finding[][] = this.groupFindingsPer(findings)
|
|
68
|
+
const grouped: Finding[][] = this.groupFindingsPer(findings);
|
|
69
69
|
for (let j = 0; j < grouped.length; j++) {
|
|
70
|
-
table.set(i, j, grouped[j].length)
|
|
70
|
+
table.set(i, j, grouped[j].length);
|
|
71
71
|
}
|
|
72
|
-
i
|
|
72
|
+
i++;
|
|
73
73
|
}
|
|
74
|
-
const result: string = this.codeBlock(table.toString())
|
|
75
|
-
|
|
76
|
-
return result
|
|
74
|
+
const result: string = this.codeBlock(table.toString());
|
|
75
|
+
logger.trace(result);
|
|
76
|
+
return result;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
export default class Cell {
|
|
2
|
-
private _width: number
|
|
2
|
+
private _width: number;
|
|
3
3
|
|
|
4
4
|
public constructor(private _value: number = 0) {
|
|
5
|
-
this._width = _value.toString().length
|
|
5
|
+
this._width = _value.toString().length;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
public setWidth(width: number): void {
|
|
9
|
-
this._width = width > this._width ? width : this._width
|
|
9
|
+
this._width = width > this._width ? width : this._width;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
public getWidth(): number {
|
|
13
|
-
return this._width
|
|
13
|
+
return this._width;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
public get value(): number {
|
|
17
|
-
return this._value
|
|
17
|
+
return this._value;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
public toString(): string {
|
|
21
|
-
const str: string = this._value.toString()
|
|
22
|
-
const repeatCount: number = this._width - str.length
|
|
23
|
-
return `${str}${repeatCount > 0 ? ' '.repeat(repeatCount) : ''}
|
|
21
|
+
const str: string = this._value.toString();
|
|
22
|
+
const repeatCount: number = this._width - str.length;
|
|
23
|
+
return `${str}${repeatCount > 0 ? ' '.repeat(repeatCount) : ''}`;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import type Cell from './Cell'
|
|
2
|
-
import Logger from '../../Logger'
|
|
1
|
+
import type Cell from './Cell';
|
|
2
|
+
import Logger from '../../Logger';
|
|
3
3
|
|
|
4
4
|
export default class Column {
|
|
5
|
-
private readonly _logger: Logger = new Logger('Column');
|
|
6
5
|
private readonly _cells: Cell[];
|
|
7
6
|
|
|
8
7
|
public constructor(
|
|
9
8
|
public readonly header: string,
|
|
10
9
|
cellsCount: number,
|
|
11
10
|
) {
|
|
12
|
-
this._cells = new Array<Cell>(cellsCount)
|
|
11
|
+
this._cells = new Array<Cell>(cellsCount);
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
public get total(): number {
|
|
16
15
|
return this._cells
|
|
17
16
|
.reduce((sum: number, c: Cell): number => {
|
|
18
|
-
sum += Number(c.value)
|
|
19
|
-
return sum
|
|
20
|
-
}, 0)
|
|
17
|
+
sum += Number(c.value);
|
|
18
|
+
return sum;
|
|
19
|
+
}, 0);
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
public get width(): number {
|
|
24
23
|
return Math.max(
|
|
25
24
|
...this._cells.map((c: Cell): number => c.getWidth()),
|
|
26
|
-
this.total.toString().length
|
|
27
|
-
)
|
|
25
|
+
this.total.toString().length,
|
|
26
|
+
);
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
public setCell(index: number, value: Cell): void {
|
|
31
30
|
if (index >= 0 && index < this._cells.length) {
|
|
32
|
-
this._cells[index] = value
|
|
33
|
-
const width: number = this.width
|
|
34
|
-
this._cells.forEach((c: Cell): void => c.setWidth(width))
|
|
31
|
+
this._cells[index] = value;
|
|
32
|
+
const width: number = this.width;
|
|
33
|
+
this._cells.forEach((c: Cell): void => c.setWidth(width));
|
|
35
34
|
} else {
|
|
36
|
-
|
|
35
|
+
const logger = new Logger();;
|
|
36
|
+
logger.warn(`Cell index out of range. Requested index: ${index}. Cells count: ${this._cells.length}.`);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import Cell from './Cell'
|
|
2
|
-
import Logger from '../../Logger'
|
|
1
|
+
import Cell from './Cell';
|
|
2
|
+
import Logger from '../../Logger';
|
|
3
3
|
|
|
4
4
|
export default class Row {
|
|
5
|
-
private readonly _logger = new Logger('Row');
|
|
6
5
|
private readonly _cells: Cell[];
|
|
7
6
|
private _totalWidth: number;
|
|
8
7
|
|
|
@@ -11,40 +10,41 @@ export default class Row {
|
|
|
11
10
|
public readonly headerWidth: number,
|
|
12
11
|
cellsCount: number,
|
|
13
12
|
) {
|
|
14
|
-
this._cells = Array.from({ length: cellsCount }, (): Cell => new Cell())
|
|
15
|
-
this._totalWidth = 1
|
|
13
|
+
this._cells = Array.from({ length: cellsCount }, (): Cell => new Cell());
|
|
14
|
+
this._totalWidth = 1;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
public get total(): number {
|
|
19
18
|
return this._cells
|
|
20
19
|
.reduce((sum: number, c: Cell): number => {
|
|
21
|
-
sum += Number(c.value)
|
|
22
|
-
return sum
|
|
23
|
-
}, 0)
|
|
20
|
+
sum += Number(c.value);
|
|
21
|
+
return sum;
|
|
22
|
+
}, 0);
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
public setCell(index: number, value: Cell): void {
|
|
27
26
|
if (index >= 0 && index < this._cells.length) {
|
|
28
|
-
this._cells[index] = value
|
|
27
|
+
this._cells[index] = value;
|
|
29
28
|
} else {
|
|
30
|
-
|
|
29
|
+
const logger = new Logger();
|
|
30
|
+
logger.warn(`Setting cell failed. Reason: index out of range. Requested index: ${index}. Cells count: ${this._cells.length}.`);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
public get totalWidth(): number {
|
|
35
|
-
return this._totalWidth
|
|
35
|
+
return this._totalWidth;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
public setTotalWidth(value: number): void {
|
|
39
|
-
this._totalWidth = value
|
|
39
|
+
this._totalWidth = value;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
public toString(): string {
|
|
43
|
-
const result: string[] = []
|
|
44
|
-
result.push(`${this._header}${this.headerWidth > this._header.length ? ' '.repeat(this.headerWidth - this._header.length) : ''}`)
|
|
45
|
-
this._cells.map((c: Cell): string => c.toString()).forEach((v: string): number => result.push(v))
|
|
43
|
+
const result: string[] = [];
|
|
44
|
+
result.push(`${this._header}${this.headerWidth > this._header.length ? ' '.repeat(this.headerWidth - this._header.length) : ''}`);
|
|
45
|
+
this._cells.map((c: Cell): string => c.toString()).forEach((v: string): number => result.push(v));
|
|
46
46
|
const totalStr: string = this.total.toString();
|
|
47
|
-
result.push(`${totalStr}${this._totalWidth > totalStr.length ? ' '.repeat(this._totalWidth - totalStr.length) : ''}`)
|
|
48
|
-
return `|${result.join('|')}
|
|
47
|
+
result.push(`${totalStr}${this._totalWidth > totalStr.length ? ' '.repeat(this._totalWidth - totalStr.length) : ''}`);
|
|
48
|
+
return `|${result.join('|')}|`;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import Column from './Column'
|
|
2
|
-
import Row from './Row'
|
|
3
|
-
import Cell from './Cell'
|
|
1
|
+
import Column from './Column';
|
|
2
|
+
import Row from './Row';
|
|
3
|
+
import Cell from './Cell';
|
|
4
4
|
|
|
5
|
-
const HEADER_TOTAL: string = 'Total'
|
|
5
|
+
const HEADER_TOTAL: string = 'Total';
|
|
6
6
|
|
|
7
7
|
export type TableHeaders = {
|
|
8
8
|
main?: string,
|
|
@@ -11,47 +11,47 @@ export type TableHeaders = {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export default class Table {
|
|
14
|
-
private readonly header: string
|
|
15
|
-
private readonly columns: Column[]
|
|
16
|
-
private readonly rows: Row[]
|
|
14
|
+
private readonly header: string;
|
|
15
|
+
private readonly columns: Column[];
|
|
16
|
+
private readonly rows: Row[];
|
|
17
17
|
|
|
18
18
|
public constructor(
|
|
19
19
|
headers: TableHeaders,
|
|
20
20
|
) {
|
|
21
|
-
this.header = headers.main ?? ''
|
|
21
|
+
this.header = headers.main ?? '';
|
|
22
22
|
this.columns = Array.from(
|
|
23
23
|
{ length: headers.columns.length },
|
|
24
|
-
(_: unknown, index: number): Column => new Column(headers.columns[index], headers.rows.length)
|
|
25
|
-
)
|
|
24
|
+
(_: unknown, index: number): Column => new Column(headers.columns[index], headers.rows.length),
|
|
25
|
+
);
|
|
26
26
|
const headerWidth: number = Math.max(
|
|
27
27
|
this.header.length,
|
|
28
28
|
...headers.rows.map((v: string): number => v.length),
|
|
29
29
|
HEADER_TOTAL.length,
|
|
30
|
-
)
|
|
30
|
+
);
|
|
31
31
|
this.rows = Array.from(
|
|
32
32
|
{ length: headers.rows.length },
|
|
33
|
-
(_: unknown, index: number): Row => new Row(headers.rows[index], headerWidth, headers.columns.length)
|
|
34
|
-
)
|
|
33
|
+
(_: unknown, index: number): Row => new Row(headers.rows[index], headerWidth, headers.columns.length),
|
|
34
|
+
);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
public set(rowIndex: number, columnIndex: number, v: number): void {
|
|
38
38
|
if (rowIndex >= 0 && rowIndex < this.rows.length && columnIndex >= 0 && columnIndex < this.columns.length) {
|
|
39
|
-
const cell = new Cell(v)
|
|
40
|
-
cell.setWidth(this.columns[columnIndex].header.length)
|
|
41
|
-
this.columns[columnIndex].setCell(rowIndex, cell)
|
|
42
|
-
this.rows[rowIndex].setCell(columnIndex, cell)
|
|
39
|
+
const cell = new Cell(v);
|
|
40
|
+
cell.setWidth(this.columns[columnIndex].header.length);
|
|
41
|
+
this.columns[columnIndex].setCell(rowIndex, cell);
|
|
42
|
+
this.rows[rowIndex].setCell(columnIndex, cell);
|
|
43
43
|
// Update width of the last cell ("Total") of every row, so that it is shown
|
|
44
44
|
// correctly in string representation
|
|
45
45
|
const rowTotalWidth: number = Math.max(
|
|
46
46
|
// Based on the sum of all total values
|
|
47
47
|
this.rows.reduce((sum: number, r: Row): number => {
|
|
48
|
-
sum += r.total
|
|
49
|
-
return sum
|
|
48
|
+
sum += r.total;
|
|
49
|
+
return sum;
|
|
50
50
|
}, 0).toString().length,
|
|
51
51
|
// Based on the width of "Total" header
|
|
52
52
|
HEADER_TOTAL.length,
|
|
53
|
-
)
|
|
54
|
-
this.rows.forEach((r: Row): void => r.setTotalWidth(rowTotalWidth))
|
|
53
|
+
);
|
|
54
|
+
this.rows.forEach((r: Row): void => r.setTotalWidth(rowTotalWidth));
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
package/src/system.ts
CHANGED
|
@@ -8,10 +8,10 @@ import { version, sha, buildAt } from './metadata.json';
|
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
10
|
export function logMetadata(): void {
|
|
11
|
-
const logger = new Logger(
|
|
12
|
-
logger.
|
|
13
|
-
logger.
|
|
14
|
-
logger.
|
|
11
|
+
const logger = new Logger();
|
|
12
|
+
logger.debug(`version: ${version}`);
|
|
13
|
+
logger.debug(`sha: ${sha}`);
|
|
14
|
+
logger.debug(`built at: ${buildAt}`);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -21,7 +21,7 @@ export function logMetadata(): void {
|
|
|
21
21
|
*/
|
|
22
22
|
export function isDebug(): boolean {
|
|
23
23
|
const parseResult: ZodSafeParseResult<boolean> = z.stringbool().safeParse(
|
|
24
|
-
process.env.ACTIONS_STEP_DEBUG
|
|
24
|
+
process.env.ACTIONS_STEP_DEBUG,
|
|
25
25
|
);
|
|
26
26
|
return parseResult.success && parseResult.data;
|
|
27
27
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Run } from 'sarif'
|
|
2
|
-
import type { ColorOptions } from './model/color/ColorOptions'
|
|
3
|
-
import type FindingArray from './model/FindingArray'
|
|
4
|
-
import type { SendIf } from './model/SendIf'
|
|
1
|
+
import type { Run } from 'sarif';
|
|
2
|
+
import type { ColorOptions } from './model/color/ColorOptions';
|
|
3
|
+
import type FindingArray from './model/FindingArray';
|
|
4
|
+
import type { SendIf } from './model/SendIf';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Type representing properties that indicate whether to include certain information
|
|
@@ -9,7 +9,7 @@ import type { SendIf } from './model/SendIf'
|
|
|
9
9
|
* @public
|
|
10
10
|
*/
|
|
11
11
|
export type IncludeAwareOptions = {
|
|
12
|
-
include: boolean
|
|
12
|
+
include: boolean,
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -18,7 +18,7 @@ export type IncludeAwareOptions = {
|
|
|
18
18
|
* @public
|
|
19
19
|
*/
|
|
20
20
|
export type IncludeAwareWithValueOptions = IncludeAwareOptions & {
|
|
21
|
-
value?: string
|
|
21
|
+
value?: string,
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -34,7 +34,7 @@ export enum FooterType {
|
|
|
34
34
|
* Represents a footer with Markdown formatting. Text can include formatting
|
|
35
35
|
* such as bold, italics, and links.
|
|
36
36
|
*/
|
|
37
|
-
Markdown = 'mrkdwn'
|
|
37
|
+
Markdown = 'mrkdwn',
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -43,7 +43,7 @@ export enum FooterType {
|
|
|
43
43
|
* @public
|
|
44
44
|
*/
|
|
45
45
|
export type FooterOptions = IncludeAwareWithValueOptions & {
|
|
46
|
-
type?: FooterType
|
|
46
|
+
type?: FooterType,
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
@@ -221,11 +221,16 @@ export enum RepresentationType {
|
|
|
221
221
|
TableGroupBySarifPerSeverity = 13,
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Valid SARIF file extensions.
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
export const SarifFileExtensionItems = ['sarif', 'json'] as const;
|
|
224
229
|
/**
|
|
225
230
|
* SARIF file extension.
|
|
226
231
|
* @public
|
|
227
232
|
*/
|
|
228
|
-
export type SarifFileExtension =
|
|
233
|
+
export type SarifFileExtension = typeof SarifFileExtensionItems[number];
|
|
229
234
|
|
|
230
235
|
/**
|
|
231
236
|
* Represents options for the provided SARIF file(s), such as path, should files
|
|
@@ -238,6 +243,30 @@ export type SarifOptions = {
|
|
|
238
243
|
extension?: SarifFileExtension,
|
|
239
244
|
}
|
|
240
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Valid log levels for the Logger.
|
|
248
|
+
* @public
|
|
249
|
+
*/
|
|
250
|
+
export const LogLevelItems = ['silly', 'trace', 'debug', 'info', 'warning', 'error', 'fatal'] as const;
|
|
251
|
+
/**
|
|
252
|
+
* Log levels for the Logger.
|
|
253
|
+
* @public
|
|
254
|
+
*/
|
|
255
|
+
export type LogLevel = typeof LogLevelItems[number];
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* It is used to stored logging options in global state
|
|
259
|
+
* @public
|
|
260
|
+
*/
|
|
261
|
+
export type LoggerOptions = {
|
|
262
|
+
logFunctionName?: boolean,
|
|
263
|
+
logFunctionNameOnPosition?: number,
|
|
264
|
+
minLevel?: LogLevel,
|
|
265
|
+
name?: string,
|
|
266
|
+
stylePrettyLogs?: boolean,
|
|
267
|
+
prettyLogTemplate?: string,
|
|
268
|
+
}
|
|
269
|
+
|
|
241
270
|
/**
|
|
242
271
|
* Options for the SarifToSlackClient.
|
|
243
272
|
* @public
|
|
@@ -253,6 +282,7 @@ export type SarifToSlackClientOptions = {
|
|
|
253
282
|
run?: IncludeAwareOptions,
|
|
254
283
|
representation?: RepresentationType,
|
|
255
284
|
sendIf?: SendIf,
|
|
285
|
+
loggerOptions?: LoggerOptions,
|
|
256
286
|
}
|
|
257
287
|
|
|
258
288
|
/**
|
|
@@ -273,8 +303,8 @@ export enum SecuritySeverity {
|
|
|
273
303
|
|
|
274
304
|
export const SecuritySeverityValues: string[] =
|
|
275
305
|
Object.values(SecuritySeverity).filter(
|
|
276
|
-
(v: string | SecuritySeverity): v is string => typeof v === 'string'
|
|
277
|
-
)
|
|
306
|
+
(v: string | SecuritySeverity): v is string => typeof v === 'string',
|
|
307
|
+
);
|
|
278
308
|
|
|
279
309
|
/**
|
|
280
310
|
* Enum of security level.
|
|
@@ -293,8 +323,8 @@ export enum SecurityLevel {
|
|
|
293
323
|
|
|
294
324
|
export const SecurityLevelValues: string[] =
|
|
295
325
|
Object.values(SecurityLevel).filter(
|
|
296
|
-
(v: string | SecurityLevel): v is string => typeof v === 'string'
|
|
297
|
-
)
|
|
326
|
+
(v: string | SecurityLevel): v is string => typeof v === 'string',
|
|
327
|
+
);
|
|
298
328
|
|
|
299
329
|
/**
|
|
300
330
|
* The data about run, such as {@link Run} itself, tool name of the run and ID
|
package/src/utils/Comparators.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type Finding from '../model/Finding'
|
|
1
|
+
import type Finding from '../model/Finding';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* This function returns a comparator function based on the property of the
|
|
@@ -9,11 +9,11 @@ import type Finding from '../model/Finding'
|
|
|
9
9
|
export function findingsComparatorByKey<K extends keyof Finding>(key: K): (a: Finding, b: Finding) => number {
|
|
10
10
|
return (a: Finding, b: Finding): number => {
|
|
11
11
|
switch (key) {
|
|
12
|
-
case 'severity': return b.severity - a.severity
|
|
13
|
-
case 'level': return b.level - a.level
|
|
14
|
-
case 'runId': return a.runId - b.runId
|
|
15
|
-
case 'toolName': return a.toolName.toLowerCase().localeCompare(b.toolName.toLowerCase())
|
|
16
|
-
default: return 1
|
|
12
|
+
case 'severity': return b.severity - a.severity;
|
|
13
|
+
case 'level': return b.level - a.level;
|
|
14
|
+
case 'runId': return a.runId - b.runId;
|
|
15
|
+
case 'toolName': return a.toolName.toLowerCase().localeCompare(b.toolName.toLowerCase());
|
|
16
|
+
default: return 1;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
package/src/utils/FileUtils.ts
CHANGED
|
@@ -16,7 +16,7 @@ function listFiles(
|
|
|
16
16
|
dir: string,
|
|
17
17
|
recursive: boolean,
|
|
18
18
|
extension: SarifFileExtension,
|
|
19
|
-
fileList: string[] = []
|
|
19
|
+
fileList: string[] = [],
|
|
20
20
|
): string[] {
|
|
21
21
|
if (fs.statSync(dir).isDirectory()) {
|
|
22
22
|
const entries: string[] = fs.readdirSync(dir);
|
|
@@ -27,7 +27,7 @@ function listFiles(
|
|
|
27
27
|
} else if (path.extname(fullPath).toLowerCase() === `.${extension}`) {
|
|
28
28
|
fileList.push(fullPath);
|
|
29
29
|
}
|
|
30
|
-
})
|
|
30
|
+
});
|
|
31
31
|
}
|
|
32
32
|
return fileList;
|
|
33
33
|
}
|
|
@@ -39,11 +39,11 @@ function listFiles(
|
|
|
39
39
|
* @internal
|
|
40
40
|
*/
|
|
41
41
|
export function extractListOfFiles(opts: SarifOptions): string[] {
|
|
42
|
-
const logger = new Logger(extractListOfFiles.name);
|
|
43
42
|
if (!fs.existsSync(opts.path)) {
|
|
44
43
|
throw new Error(`Provided path does not exist: ${opts.path}`);
|
|
45
44
|
}
|
|
46
45
|
|
|
46
|
+
const logger = new Logger();
|
|
47
47
|
const stats: fs.Stats = fs.statSync(opts.path);
|
|
48
48
|
|
|
49
49
|
if (stats.isDirectory()) {
|