@fabasoad/sarif-to-slack 1.1.0 → 1.2.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/.github/workflows/security.yml +10 -2
- package/.github/workflows/send-sarif-to-slack.yml +6 -1
- package/.tool-versions +1 -1
- package/dist/SarifToSlackClient.d.ts.map +1 -1
- package/dist/SarifToSlackClient.js +8 -10
- package/dist/index.cjs +158 -93
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/model/Color.d.ts +5 -2
- package/dist/model/Color.d.ts.map +1 -1
- package/dist/model/Color.js +26 -17
- package/dist/model/Finding.js +3 -3
- package/dist/model/FindingArray.d.ts +2 -0
- package/dist/model/FindingArray.d.ts.map +1 -0
- package/dist/model/FindingArray.js +24 -0
- package/dist/model/SendIf.d.ts +116 -0
- package/dist/model/SendIf.d.ts.map +1 -0
- package/dist/model/SendIf.js +176 -0
- package/dist/model/SlackMessage.d.ts +23 -0
- package/dist/model/SlackMessage.d.ts.map +1 -0
- package/dist/model/SlackMessage.js +99 -0
- 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/CompactGroupBySarifRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/CompactTotalRepresentation.js +1 -1
- package/dist/representations/Representation.js +3 -3
- package/dist/sarif-to-slack.d.ts +14 -3
- package/dist/types.d.ts +1 -130
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -117
- package/etc/sarif-to-slack.api.md +1 -0
- package/package.json +1 -1
- package/src/SarifToSlackClient.ts +8 -12
- package/src/index.ts +12 -4
- package/src/model/Color.ts +37 -25
- package/src/model/Finding.ts +3 -3
- package/src/model/{FindingsArray.ts → FindingArray.ts} +3 -3
- package/src/model/SendIf.ts +175 -0
- package/src/{SlackMessageBuilder.ts → model/SlackMessage.ts} +31 -6
- package/src/processors/CodeQLProcessor.ts +1 -1
- package/src/representations/CompactGroupByRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +1 -1
- package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +1 -1
- package/src/representations/CompactGroupByRunRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNameRepresentation.ts +2 -2
- package/src/representations/CompactTotalRepresentation.ts +2 -2
- package/src/representations/Representation.ts +4 -4
- package/src/types.ts +3 -134
- package/src/utils/Comparators.ts +1 -1
- package/test-data/sarif/osv-scanner-yarn.sarif +4 -4
- package/tests/integration/SendSarifToSlack.spec.ts +21 -5
- package/dist/SlackMessageBuilder.d.ts +0 -2
- package/dist/SlackMessageBuilder.d.ts.map +0 -1
- package/dist/SlackMessageBuilder.js +0 -91
- package/dist/model/FindingsArray.d.ts +0 -2
- package/dist/model/FindingsArray.d.ts.map +0 -1
- package/dist/model/FindingsArray.js +0 -24
package/src/model/Color.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SecurityLevel, SecuritySeverity } from '../types'
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import Finding from './Finding'
|
|
3
|
+
import FindingArray from './FindingArray'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* This class represents a color in hex format.
|
|
@@ -20,7 +20,7 @@ export class Color {
|
|
|
20
20
|
*/
|
|
21
21
|
public constructor(color?: string) {
|
|
22
22
|
this._color = this.mapColor(color)
|
|
23
|
-
this.
|
|
23
|
+
this.assertHexColor()
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -30,12 +30,12 @@ export class Color {
|
|
|
30
30
|
return this._color
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
private
|
|
33
|
+
private assertHexColor(): void {
|
|
34
34
|
if (this._color != null) {
|
|
35
|
-
const hexColorRegex = /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})
|
|
35
|
+
const hexColorRegex = /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/
|
|
36
36
|
|
|
37
37
|
if (!hexColorRegex.test(this._color)) {
|
|
38
|
-
throw new Error(`Invalid hex color: "${this._color}"`)
|
|
38
|
+
throw new Error(`Invalid hex color: "${this._color}"`)
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -64,7 +64,6 @@ export class Color {
|
|
|
64
64
|
type ColorGroupCommon = {
|
|
65
65
|
none?: Color,
|
|
66
66
|
unknown?: Color,
|
|
67
|
-
empty?: Color,
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
/**
|
|
@@ -113,15 +112,18 @@ export type ColorOptions = {
|
|
|
113
112
|
* Color scheme for the findings where certain severity is presented.
|
|
114
113
|
*/
|
|
115
114
|
bySeverity?: ColorGroupBySeverity,
|
|
115
|
+
/**
|
|
116
|
+
* Color when no findings are found.
|
|
117
|
+
*/
|
|
118
|
+
empty?: Color,
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
function identifyColorCommon<K extends keyof Finding>(
|
|
119
|
-
findings:
|
|
122
|
+
findings: FindingArray,
|
|
120
123
|
prop: K,
|
|
121
124
|
none: Finding[K],
|
|
122
125
|
unknown: Finding[K],
|
|
123
|
-
color: ColorGroupCommon
|
|
124
|
-
defaultColor?: Color
|
|
126
|
+
color: ColorGroupCommon
|
|
125
127
|
): string | undefined {
|
|
126
128
|
if (color.none != null && findings.findByProperty(prop, none) != null) {
|
|
127
129
|
return color.none.value
|
|
@@ -131,14 +133,10 @@ function identifyColorCommon<K extends keyof Finding>(
|
|
|
131
133
|
return color.unknown.value
|
|
132
134
|
}
|
|
133
135
|
|
|
134
|
-
|
|
135
|
-
return color.empty.value
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return defaultColor?.value
|
|
136
|
+
return undefined
|
|
139
137
|
}
|
|
140
138
|
|
|
141
|
-
function identifyColorBySeverity(findings:
|
|
139
|
+
function identifyColorBySeverity(findings: FindingArray, color: ColorGroupBySeverity): string | undefined {
|
|
142
140
|
if (color.critical != null && findings.findByProperty('severity', SecuritySeverity.Critical) != null) {
|
|
143
141
|
return color.critical.value
|
|
144
142
|
}
|
|
@@ -155,10 +153,10 @@ function identifyColorBySeverity(findings: FindingsArray, color: ColorGroupBySev
|
|
|
155
153
|
return color.low.value
|
|
156
154
|
}
|
|
157
155
|
|
|
158
|
-
return identifyColorCommon(findings, 'severity', SecuritySeverity.None, SecuritySeverity.Unknown, color
|
|
156
|
+
return identifyColorCommon(findings, 'severity', SecuritySeverity.None, SecuritySeverity.Unknown, color)
|
|
159
157
|
}
|
|
160
158
|
|
|
161
|
-
function identifyColorByLevel(findings:
|
|
159
|
+
function identifyColorByLevel(findings: FindingArray, color: ColorGroupByLevel): string | undefined {
|
|
162
160
|
if (color.error != null && findings.findByProperty('level', SecurityLevel.Error) != null) {
|
|
163
161
|
return color.error.value
|
|
164
162
|
}
|
|
@@ -171,24 +169,38 @@ function identifyColorByLevel(findings: FindingsArray, color: ColorGroupByLevel,
|
|
|
171
169
|
return color.note.value
|
|
172
170
|
}
|
|
173
171
|
|
|
174
|
-
return identifyColorCommon(findings, 'level', SecurityLevel.None, SecurityLevel.Unknown, color
|
|
172
|
+
return identifyColorCommon(findings, 'level', SecurityLevel.None, SecurityLevel.Unknown, color)
|
|
175
173
|
}
|
|
176
174
|
|
|
177
175
|
/**
|
|
178
176
|
* Makes an ultimate decision on what color should be Slack message. The decision
|
|
179
177
|
* is based on the provided {@param colorOpts} parameter and {@param findings}
|
|
180
178
|
* list.
|
|
181
|
-
* @param findings An instance of {@link
|
|
179
|
+
* @param findings An instance of {@link FindingArray} object.
|
|
182
180
|
* @param colorOpts An instance of {@link ColorOptions} type.
|
|
183
181
|
* @internal
|
|
184
182
|
*/
|
|
185
|
-
export function identifyColor(findings:
|
|
186
|
-
if (colorOpts
|
|
187
|
-
return
|
|
183
|
+
export function identifyColor(findings: FindingArray, colorOpts?: ColorOptions): string | undefined {
|
|
184
|
+
if (!colorOpts) {
|
|
185
|
+
return undefined
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (colorOpts.bySeverity) {
|
|
189
|
+
const color: string | undefined = identifyColorBySeverity(findings, colorOpts.bySeverity)
|
|
190
|
+
if (color !== undefined) {
|
|
191
|
+
return color
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (colorOpts.byLevel) {
|
|
196
|
+
const color: string | undefined = identifyColorByLevel(findings, colorOpts.byLevel)
|
|
197
|
+
if (color !== undefined) {
|
|
198
|
+
return color
|
|
199
|
+
}
|
|
188
200
|
}
|
|
189
201
|
|
|
190
|
-
if (colorOpts?.
|
|
191
|
-
return
|
|
202
|
+
if (findings.length === 0 && colorOpts.empty?.value !== undefined) {
|
|
203
|
+
return colorOpts.empty.value
|
|
192
204
|
}
|
|
193
205
|
|
|
194
206
|
return colorOpts?.default?.value
|
package/src/model/Finding.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type FindingOptions = {
|
|
|
18
18
|
* This interface represents a finding from SARIF file.
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
export interface Finding {
|
|
21
|
+
export default interface Finding {
|
|
22
22
|
get sarifPath(): string,
|
|
23
23
|
get runId(): number,
|
|
24
24
|
get toolName(): string,
|
|
@@ -33,7 +33,7 @@ export interface Finding {
|
|
|
33
33
|
* @internal
|
|
34
34
|
*/
|
|
35
35
|
export function createFinding(opts: FindingOptions): Finding {
|
|
36
|
-
return new
|
|
36
|
+
return new FindingImpl(opts)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -42,7 +42,7 @@ export function createFinding(opts: FindingOptions): Finding {
|
|
|
42
42
|
* create a new {@link Finding}.
|
|
43
43
|
* @private
|
|
44
44
|
*/
|
|
45
|
-
class
|
|
45
|
+
class FindingImpl implements Finding {
|
|
46
46
|
private readonly _runMetadata: RunData
|
|
47
47
|
private readonly _result: Result
|
|
48
48
|
private readonly _sarifPath: string
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import ExtendedArray from '../utils/ExtendedArray'
|
|
1
|
+
import Finding from './Finding'
|
|
3
2
|
import { SecurityLevel, SecuritySeverity } from '../types'
|
|
3
|
+
import ExtendedArray from '../utils/ExtendedArray'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* This class represents an array of {@link Finding} objects and adds additional
|
|
7
7
|
* useful methods to it.
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
export default class
|
|
10
|
+
export default class FindingArray extends ExtendedArray<Finding> {
|
|
11
11
|
|
|
12
12
|
public hasSeverityOrHigher(severity: SecuritySeverity): boolean {
|
|
13
13
|
return Object
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This enum represents the condition on when message should be sent. If this
|
|
3
|
+
* condition is satisfied then message is sent, otherwise - message is not sent.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export enum SendIf {
|
|
7
|
+
/**
|
|
8
|
+
* Send message only if there is at least one finding with "Critical" severity.
|
|
9
|
+
* Since it is the higher possible severity, it is the same as "Critical" or
|
|
10
|
+
* higher.
|
|
11
|
+
*/
|
|
12
|
+
SeverityCritical,
|
|
13
|
+
/**
|
|
14
|
+
* Send message only if there is at least one finding with "High" severity.
|
|
15
|
+
*/
|
|
16
|
+
SeverityHigh,
|
|
17
|
+
/**
|
|
18
|
+
* Send message only if there is at least one finding with "High" severity or
|
|
19
|
+
* higher, that includes "High" and "Critical".
|
|
20
|
+
*/
|
|
21
|
+
SeverityHighOrHigher,
|
|
22
|
+
/**
|
|
23
|
+
* Send message only if there is at least one finding with "Medium" severity.
|
|
24
|
+
*/
|
|
25
|
+
SeverityMedium,
|
|
26
|
+
/**
|
|
27
|
+
* Send message only if there is at least one finding with "Medium" severity
|
|
28
|
+
* or higher, that includes "Medium", "High" and "Critical".
|
|
29
|
+
*/
|
|
30
|
+
SeverityMediumOrHigher,
|
|
31
|
+
/**
|
|
32
|
+
* Send message only if there is at least one finding with "Low" severity.
|
|
33
|
+
*/
|
|
34
|
+
SeverityLow,
|
|
35
|
+
/**
|
|
36
|
+
* Send message only if there is at least one finding with "Low" severity or
|
|
37
|
+
* higher, that includes "Low", "Medium", "High" and "Critical".
|
|
38
|
+
*/
|
|
39
|
+
SeverityLowOrHigher,
|
|
40
|
+
/**
|
|
41
|
+
* Send message only if there is at least one finding with "None" severity.
|
|
42
|
+
*/
|
|
43
|
+
SeverityNone,
|
|
44
|
+
/**
|
|
45
|
+
* Send message only if there is at least one finding with "None" severity or
|
|
46
|
+
* higher, that includes "None", "Low", "Medium", "High" and "Critical".
|
|
47
|
+
*/
|
|
48
|
+
SeverityNoneOrHigher,
|
|
49
|
+
/**
|
|
50
|
+
* Send message only if there is at least one finding with "Unknown" severity.
|
|
51
|
+
*/
|
|
52
|
+
SeverityUnknown,
|
|
53
|
+
/**
|
|
54
|
+
* Send message only if there is at least one finding with "Unknown" severity
|
|
55
|
+
* or higher, that includes "Unknown", "None", "Low", "Medium", "High" and "Critical".
|
|
56
|
+
*/
|
|
57
|
+
SeverityUnknownOrHigher,
|
|
58
|
+
/**
|
|
59
|
+
* Send message only if there is at least one finding with "Error" level.
|
|
60
|
+
* Since it is the higher possible level, it is the same as "Error" or higher.
|
|
61
|
+
*/
|
|
62
|
+
LevelError,
|
|
63
|
+
/**
|
|
64
|
+
* Send message only if there is at least one finding with "Warning" level.
|
|
65
|
+
*/
|
|
66
|
+
LevelWarning,
|
|
67
|
+
/**
|
|
68
|
+
* Send message only if there is at least one finding with "Warning" level or
|
|
69
|
+
* higher, that includes "Warning" and "Error".
|
|
70
|
+
*/
|
|
71
|
+
LevelWarningOrHigher,
|
|
72
|
+
/**
|
|
73
|
+
* Send message only if there is at least one finding with "Note" level.
|
|
74
|
+
*/
|
|
75
|
+
LevelNote,
|
|
76
|
+
/**
|
|
77
|
+
* Send message only if there is at least one finding with "Note" level or
|
|
78
|
+
* higher, that includes "Note", "Warning" and "Error.
|
|
79
|
+
*/
|
|
80
|
+
LevelNoteOrHigher,
|
|
81
|
+
/**
|
|
82
|
+
* Send message only if there is at least one finding with "None" level.
|
|
83
|
+
*/
|
|
84
|
+
LevelNone,
|
|
85
|
+
/**
|
|
86
|
+
* Send message only if there is at least one finding with "None" level or
|
|
87
|
+
* higher, that includes "None", "Note", "Warning" and "Error.
|
|
88
|
+
*/
|
|
89
|
+
LevelNoneOrHigher,
|
|
90
|
+
/**
|
|
91
|
+
* Send message only if there is at least one finding with "Unknown" level.
|
|
92
|
+
*/
|
|
93
|
+
LevelUnknown,
|
|
94
|
+
/**
|
|
95
|
+
* Send message only if there is at least one finding with "Unknown" level or
|
|
96
|
+
* higher, that includes "Unknown", "None", "Note", "Warning" and "Error.
|
|
97
|
+
*/
|
|
98
|
+
LevelUnknownOrHigher,
|
|
99
|
+
/**
|
|
100
|
+
* Always send a message.
|
|
101
|
+
*/
|
|
102
|
+
Always,
|
|
103
|
+
/**
|
|
104
|
+
* Send a message if at least 1 vulnerability is found.
|
|
105
|
+
*/
|
|
106
|
+
Some,
|
|
107
|
+
/**
|
|
108
|
+
* Send a message only if no vulnerabilities are found.
|
|
109
|
+
*/
|
|
110
|
+
Empty,
|
|
111
|
+
/**
|
|
112
|
+
* Never send a message.
|
|
113
|
+
*/
|
|
114
|
+
Never,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Returns log message based on the provided {@param sendIf} parameter.
|
|
119
|
+
* @param sendIf An instance of {@link SendIf} enum.
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
export function sendIfLogMessage(sendIf: SendIf): string {
|
|
123
|
+
switch (sendIf) {
|
|
124
|
+
case SendIf.SeverityCritical:
|
|
125
|
+
return 'No message sent: no findings with "Critical" severity.'
|
|
126
|
+
case SendIf.SeverityHigh:
|
|
127
|
+
return 'No message sent: no findings with "High" severity.'
|
|
128
|
+
case SendIf.SeverityHighOrHigher:
|
|
129
|
+
return 'No message sent: no findings with "High" or higher severity.'
|
|
130
|
+
case SendIf.SeverityMedium:
|
|
131
|
+
return 'No message sent: no findings with "Medium" severity.'
|
|
132
|
+
case SendIf.SeverityMediumOrHigher:
|
|
133
|
+
return 'No message sent: no findings with "Medium" or higher severity.'
|
|
134
|
+
case SendIf.SeverityLow:
|
|
135
|
+
return 'No message sent: no findings with "Low" severity.'
|
|
136
|
+
case SendIf.SeverityLowOrHigher:
|
|
137
|
+
return 'No message sent: no findings with "Low" or higher severity.'
|
|
138
|
+
case SendIf.SeverityNone:
|
|
139
|
+
return 'No message sent: no findings with "None" severity.'
|
|
140
|
+
case SendIf.SeverityNoneOrHigher:
|
|
141
|
+
return 'No message sent: no findings with "None" or higher severity.'
|
|
142
|
+
case SendIf.SeverityUnknown:
|
|
143
|
+
return 'No message sent: no findings with "Unknown" severity.'
|
|
144
|
+
case SendIf.SeverityUnknownOrHigher:
|
|
145
|
+
return 'No message sent: no findings with "Unknown" or higher severity.'
|
|
146
|
+
case SendIf.LevelError:
|
|
147
|
+
return 'No message sent: no findings with "Error" level.'
|
|
148
|
+
case SendIf.LevelWarning:
|
|
149
|
+
return 'No message sent: no findings with "Warning" level.'
|
|
150
|
+
case SendIf.LevelWarningOrHigher:
|
|
151
|
+
return 'No message sent: no findings with "Warning" or higher level.'
|
|
152
|
+
case SendIf.LevelNote:
|
|
153
|
+
return 'No message sent: no findings with "Note" level.'
|
|
154
|
+
case SendIf.LevelNoteOrHigher:
|
|
155
|
+
return 'No message sent: no findings with "Note" or higher level.'
|
|
156
|
+
case SendIf.LevelNone:
|
|
157
|
+
return 'No message sent: no findings with "None" level.'
|
|
158
|
+
case SendIf.LevelNoneOrHigher:
|
|
159
|
+
return 'No message sent: no findings with "None" or higher level.'
|
|
160
|
+
case SendIf.LevelUnknown:
|
|
161
|
+
return 'No message sent: no findings with "Unknown" level.'
|
|
162
|
+
case SendIf.LevelUnknownOrHigher:
|
|
163
|
+
return 'No message sent: no findings with "Unknown" or higher level.'
|
|
164
|
+
case SendIf.Always:
|
|
165
|
+
return 'Message always sent.'
|
|
166
|
+
case SendIf.Some:
|
|
167
|
+
return 'No message sent: findings are not found.'
|
|
168
|
+
case SendIf.Empty:
|
|
169
|
+
return 'No message sent: some findings are found.'
|
|
170
|
+
case SendIf.Never:
|
|
171
|
+
return 'No message sent: sending is disabled.'
|
|
172
|
+
default:
|
|
173
|
+
return 'Unknown SendIf value.'
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -2,26 +2,51 @@ import { AnyBlock } from '@slack/types'
|
|
|
2
2
|
import { ContextBlock, HeaderBlock } from '@slack/types/dist/block-kit/blocks'
|
|
3
3
|
import { TextObject } from '@slack/types/dist/block-kit/composition-objects'
|
|
4
4
|
import { IncomingWebhook } from '@slack/webhook'
|
|
5
|
-
import { FooterType
|
|
6
|
-
import
|
|
7
|
-
import
|
|
5
|
+
import { FooterType } from '../types'
|
|
6
|
+
import Representation from '../representations/Representation'
|
|
7
|
+
import { version } from '../metadata.json'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Options for the SlackMessageBuilder.
|
|
11
11
|
* @internal
|
|
12
12
|
*/
|
|
13
|
-
export type
|
|
13
|
+
export type SlackMessageOptions = {
|
|
14
14
|
username?: string
|
|
15
15
|
iconUrl?: string
|
|
16
16
|
color?: string
|
|
17
17
|
representation: Representation,
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Interface for a Slack message that can be sent.
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export interface SlackMessage {
|
|
25
|
+
/**
|
|
26
|
+
* Sends the Slack message.
|
|
27
|
+
* @returns A promise that resolves to the response from the Slack webhook.
|
|
28
|
+
*/
|
|
29
|
+
send: () => Promise<string>
|
|
30
|
+
withActor(actor?: string): void
|
|
31
|
+
withFooter(text?: string, type?: FooterType): void
|
|
32
|
+
withHeader(header?: string): void
|
|
33
|
+
withRun(): void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Creates a new instance of {@link SlackMessage} class.
|
|
38
|
+
* @param url Slack webhook URL
|
|
39
|
+
* @param opts An instance of {@link SlackMessageOptions} type.
|
|
40
|
+
*/
|
|
41
|
+
export function createSlackMessage(url: string, opts: SlackMessageOptions): SlackMessage {
|
|
42
|
+
return new SlackMessageImpl(url, opts)
|
|
43
|
+
}
|
|
44
|
+
|
|
20
45
|
/**
|
|
21
46
|
* Class for building and sending Slack messages based on SARIF logs.
|
|
22
47
|
* @internal
|
|
23
48
|
*/
|
|
24
|
-
|
|
49
|
+
class SlackMessageImpl implements SlackMessage {
|
|
25
50
|
private readonly _webhook: IncomingWebhook
|
|
26
51
|
private readonly _gitHubServerUrl: string
|
|
27
52
|
private readonly _color?: string
|
|
@@ -32,7 +57,7 @@ export class SlackMessageBuilder implements SlackMessage {
|
|
|
32
57
|
private _actor?: string
|
|
33
58
|
private _runId?: string
|
|
34
59
|
|
|
35
|
-
constructor(url: string, opts:
|
|
60
|
+
constructor(url: string, opts: SlackMessageOptions) {
|
|
36
61
|
this._webhook = new IncomingWebhook(url, {
|
|
37
62
|
username: opts.username || 'SARIF results',
|
|
38
63
|
icon_url: opts.iconUrl
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Representation from './Representation'
|
|
2
|
-
import
|
|
2
|
+
import Finding from '../model/Finding'
|
|
3
3
|
import { findingsComparatorByKey } from '../utils/Comparators'
|
|
4
|
-
import { SecurityLevel, SecuritySeverity } from '../types'
|
|
4
|
+
import { SecurityLevel, SecuritySeverity } from '../types'
|
|
5
5
|
|
|
6
6
|
const NO_VULNS_FOUND_TEXT = 'No vulnerabilities found'
|
|
7
7
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Finding from '../model/Finding'
|
|
2
2
|
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
3
3
|
import { SarifModel } from '../types'
|
|
4
4
|
|
|
@@ -13,10 +13,10 @@ import { SarifModel } from '../types'
|
|
|
13
13
|
* [Run 2] Grype
|
|
14
14
|
* Warning: 1, Note: 20
|
|
15
15
|
* ```
|
|
16
|
-
* @internal
|
|
17
16
|
* It is an abstract class, so the only question that derived classes should
|
|
18
17
|
* "answer" is what property should be used in the compact representation, such
|
|
19
18
|
* as "level" and "severity".
|
|
19
|
+
* @internal
|
|
20
20
|
*/
|
|
21
21
|
export default abstract class CompactGroupByRunRepresentation extends CompactGroupByRepresentation {
|
|
22
22
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import
|
|
2
|
+
import Finding from '../model/Finding'
|
|
3
3
|
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
4
4
|
import { SarifModel } from '../types'
|
|
5
5
|
|
|
@@ -14,10 +14,10 @@ import { SarifModel } from '../types'
|
|
|
14
14
|
* grype-results-02.sarif
|
|
15
15
|
* Warning: 1, Note: 20
|
|
16
16
|
* ```
|
|
17
|
-
* @internal
|
|
18
17
|
* It is an abstract class, so the only question that derived classes should
|
|
19
18
|
* "answer" is what property should be used in the compact representation, such
|
|
20
19
|
* as "level" and "severity".
|
|
20
|
+
* @internal
|
|
21
21
|
*/
|
|
22
22
|
export default abstract class CompactGroupBySarifRepresentation extends CompactGroupByRepresentation {
|
|
23
23
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Finding from '../model/Finding'
|
|
2
2
|
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
3
3
|
import { SarifModel } from '../types'
|
|
4
4
|
|
|
@@ -13,10 +13,10 @@ import { SarifModel } from '../types'
|
|
|
13
13
|
* Trivy
|
|
14
14
|
* Warning: 1, Note: 20
|
|
15
15
|
* ```
|
|
16
|
-
* @internal
|
|
17
16
|
* It is an abstract class, so the only question that derived classes should
|
|
18
17
|
* "answer" is what property should be used in the compact representation, such
|
|
19
18
|
* as "level" and "severity".
|
|
19
|
+
* @internal
|
|
20
20
|
*/
|
|
21
21
|
export default abstract class CompactGroupByToolNameRepresentation extends CompactGroupByRepresentation {
|
|
22
22
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
2
|
-
import
|
|
2
|
+
import Finding from '../model/Finding'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
@@ -10,10 +10,10 @@ import { Finding } from '../model/Finding'
|
|
|
10
10
|
* Total
|
|
11
11
|
* Warning: 1, Note: 20
|
|
12
12
|
* ```
|
|
13
|
-
* @internal
|
|
14
13
|
* It is an abstract class, so the only question that derived classes should
|
|
15
14
|
* "answer" is what property should be used in the compact representation, such
|
|
16
15
|
* as "level" and "severity".
|
|
16
|
+
* @internal
|
|
17
17
|
*/
|
|
18
18
|
export default abstract class CompactTotalRepresentation extends CompactGroupByRepresentation {
|
|
19
19
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SarifModel } from '../types'
|
|
2
|
-
import
|
|
2
|
+
import Finding from '../model/Finding'
|
|
3
3
|
import { findingsComparatorByKey } from '../utils/Comparators'
|
|
4
|
-
import
|
|
4
|
+
import FindingArray from '../model/FindingArray'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The most base abstract class for the representation. Every representation class
|
|
@@ -17,10 +17,10 @@ export default abstract class Representation {
|
|
|
17
17
|
.findings
|
|
18
18
|
.map((f: Finding): Finding => f.clone())
|
|
19
19
|
.sort(findingsComparatorByKey(findingSortKey))
|
|
20
|
-
.reduce((arr:
|
|
20
|
+
.reduce((arr: FindingArray, f: Finding): FindingArray => {
|
|
21
21
|
arr.push(f)
|
|
22
22
|
return arr
|
|
23
|
-
}, new
|
|
23
|
+
}, new FindingArray())
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
protected bold(text: string): string {
|