FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
codeql-action/src/analyses.ts at default-setup-testing · github/codeql-action · GitHub
github
codeql-action
Repository navigation
Code
Issues
165
(165)
Pull requests
44
(44)
Actions
Security and quality
2
(2)
Insights
Expand file tree
Breadcrumbs
codeql-action
/
src
/
analyses.ts
Copy path
More file actions
More file actions
Latest commit
History
History
History
301 lines (269 loc) · 10.7 KB
Breadcrumbs
codeql-action
/
src
/
analyses.ts
Copy path
File metadata and controls
301 lines (269 loc) · 10.7 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
import
{
fixCodeQualityCategory
,
getOptionalInput
,
getRequiredInput
,
isDynamicWorkflow
,
}
from
"./actions-util"
;
import
{
EnvVar
}
from
"./environment"
;
import
{
Feature
,
FeatureEnablement
}
from
"./feature-flags"
;
import
{
Logger
}
from
"./logging"
;
import
{
AssessmentPayload
,
BasePayload
,
UploadPayload
,
}
from
"./upload-lib/types"
;
import
{
ConfigurationError
,
getRequiredEnvParam
,
isInTestMode
}
from
"./util"
;
export
enum
AnalysisKind
{
CodeScanning
=
"code-scanning"
,
CodeQuality
=
"code-quality"
,
RiskAssessment
=
"risk-assessment"
,
}
export
type
CompatibilityMatrix
=
Record
<
AnalysisKind
,
Set
<
AnalysisKind
>
>
;
/** A mapping from analysis kinds to other analysis kinds which can be enabled concurrently. */
export
const
compatibilityMatrix
:
CompatibilityMatrix
=
{
[
AnalysisKind
.
CodeScanning
]
:
new
Set
(
[
AnalysisKind
.
CodeQuality
]
)
,
[
AnalysisKind
.
CodeQuality
]
:
new
Set
(
[
AnalysisKind
.
CodeScanning
]
)
,
[
AnalysisKind
.
RiskAssessment
]
:
new
Set
(
)
,
}
;
// Exported for testing. A set of all known analysis kinds.
export
const
supportedAnalysisKinds
=
new
Set
(
Object
.
values
(
AnalysisKind
)
)
;
/**
* Parses a comma-separated string into a list of unique analysis kinds.
* Throws a configuration error if the input contains unknown analysis kinds
* or doesn't contain at least one element.
*
*
@param
input The comma-separated string to parse.
*
@returns
The array of unique analysis kinds that were parsed from the input string.
*/
export
async
function
parseAnalysisKinds
(
input
:
string
,
)
:
Promise
<
AnalysisKind
[
]
>
{
const
components
=
input
.
split
(
","
)
;
if
(
components
.
length
<
1
)
{
throw
new
ConfigurationError
(
"At least one analysis kind must be configured."
,
)
;
}
for
(
const
component
of
components
)
{
if
(
!
supportedAnalysisKinds
.
has
(
component
as
AnalysisKind
)
)
{
throw
new
ConfigurationError
(
`Unknown analysis kind:
${
component
}
`
)
;
}
}
// Return all unique elements.
return
Array
.
from
(
new
Set
(
components
.
map
(
(
component
)
=>
component
as
AnalysisKind
)
)
,
)
;
}
// Used to avoid re-parsing the input after we have done it once.
let
cachedAnalysisKinds
:
AnalysisKind
[
]
|
undefined
;
/** Determines whether `code-scanning` is the only enabled analysis kind in `analysisKinds`. */
function
isOnlyCodeScanningEnabled
(
analysisKinds
:
AnalysisKind
[
]
)
{
return
(
analysisKinds
.
length
===
1
&&
analysisKinds
[
0
]
===
AnalysisKind
.
CodeScanning
)
;
}
/** Prepends a generic message about the intended usage for `analysis-kinds` to `message`. */
function
makeAnalysisKindUsageError
(
message
:
string
)
{
return
(
"The `analysis-kinds` input is experimental and for GitHub-internal use only. "
+
`Its behaviour may change at any time or be removed entirely.
${
message
}
`
)
;
}
/**
* Initialises the analysis kinds for the analysis based on the `analysis-kinds` input.
* This function will also use the deprecated `quality-queries` input as an indicator to enable `code-quality`.
* If the `analysis-kinds` input cannot be parsed, a `ConfigurationError` is thrown.
*
*
@param
logger The logger to use.
*
@param
skipCache For testing, whether to ignore the cached values (default: false).
*
*
@returns
The array of enabled analysis kinds.
*
@throws
A `ConfigurationError` if the `analysis-kinds` input cannot be parsed.
*/
export
async
function
getAnalysisKinds
(
logger
:
Logger
,
features
:
FeatureEnablement
,
skipCache
:
boolean
=
false
,
)
:
Promise
<
AnalysisKind
[
]
>
{
if
(
!
skipCache
&&
cachedAnalysisKinds
!==
undefined
)
{
return
cachedAnalysisKinds
;
}
const
analysisKinds
=
await
parseAnalysisKinds
(
getRequiredInput
(
"analysis-kinds"
)
,
)
;
// Log an error if we are outside of a GitHub-managed workflow and an analysis kind
// other than `code-scanning` is enabled.
if
(
!
isInTestMode
(
)
&&
!
isDynamicWorkflow
(
)
&&
!
isOnlyCodeScanningEnabled
(
analysisKinds
)
)
{
const
codeQualityHint
=
analysisKinds
.
includes
(
AnalysisKind
.
CodeQuality
)
?
" If your intention is to use quality queries outside of Code Quality, "
+
"use the `queries` input with `code-quality` instead."
:
""
;
logger
.
error
(
makeAnalysisKindUsageError
(
"An analysis kind other than `code-scanning` was specified in a custom workflow. "
+
`This is not supported and will become a fatal error in a future version of the CodeQL Action.
${
codeQualityHint
}
`
,
)
,
)
;
}
// Warn that `quality-queries` is deprecated if there is an argument for it.
const
qualityQueriesInput
=
getOptionalInput
(
"quality-queries"
)
;
if
(
qualityQueriesInput
!==
undefined
)
{
logger
.
warning
(
"The `quality-queries` input is deprecated and will be removed in a future version of the CodeQL Action. "
+
"Use the `analysis-kinds` input to configure different analysis kinds instead."
,
)
;
}
// For backwards compatibility, add Code Quality to the enabled analysis kinds
// if an input to `quality-queries` was specified. We should remove this once
// `quality-queries` is no longer used.
if
(
!
analysisKinds
.
includes
(
AnalysisKind
.
CodeQuality
)
&&
qualityQueriesInput
!==
undefined
)
{
analysisKinds
.
push
(
AnalysisKind
.
CodeQuality
)
;
}
// Check that all enabled analysis kinds are compatible with each other.
for
(
const
analysisKind
of
analysisKinds
)
{
for
(
const
otherAnalysisKind
of
analysisKinds
)
{
if
(
analysisKind
===
otherAnalysisKind
)
continue
;
if
(
!
compatibilityMatrix
[
analysisKind
]
.
has
(
otherAnalysisKind
)
)
{
throw
new
ConfigurationError
(
`
${
analysisKind
}
and
${
otherAnalysisKind
}
cannot be enabled at the same time`
,
)
;
}
}
}
// Log an error if we have multiple inputs for `analysis-kinds` outside of test mode,
// and enable only `code-scanning`.
if
(
!
isInTestMode
(
)
&&
analysisKinds
.
length
>
1
&&
!
(
await
features
.
getValue
(
Feature
.
AllowMultipleAnalysisKinds
)
)
)
{
logger
.
error
(
makeAnalysisKindUsageError
(
"Specifying multiple values as input is no longer supported. "
+
"Continuing with only `analysis-kinds: code-scanning`."
,
)
,
)
;
// Only enable Code Scanning.
cachedAnalysisKinds
=
[
AnalysisKind
.
CodeScanning
]
;
return
cachedAnalysisKinds
;
}
// Cache the analysis kinds and return them.
cachedAnalysisKinds
=
analysisKinds
;
return
cachedAnalysisKinds
;
}
/** The queries to use for Code Quality analyses. */
export
const
codeQualityQueries
:
string
[
]
=
[
"code-quality"
]
;
// Enumerates API endpoints that accept SARIF files.
enum
SARIF_UPLOAD_ENDPOINT
{
CODE_SCANNING
=
"PUT /repos/:owner/:repo/code-scanning/analysis"
,
CODE_QUALITY
=
"PUT /repos/:owner/:repo/code-quality/analysis"
,
RISK_ASSESSMENT
=
"PUT /repos/:owner/:repo/code-scanning/risk-assessment"
,
}
// Represents configurations for different analysis kinds.
export
interface
AnalysisConfig
{
/** The analysis kind the configuration is for. */
kind
:
AnalysisKind
;
/** A display friendly name for logs. */
name
:
string
;
/** The API endpoint to upload SARIF files to. */
target
:
SARIF_UPLOAD_ENDPOINT
;
/** The file extension for SARIF files generated by this kind of analysis. */
sarifExtension
:
string
;
/** A predicate on filenames to decide whether a SARIF file
* belongs to this kind of analysis. */
sarifPredicate
:
(
name
:
string
)
=>
boolean
;
/** Analysis-specific adjustment of the category. */
fixCategory
:
(
logger
:
Logger
,
category
?:
string
)
=>
string
|
undefined
;
/** A prefix for environment variables used to track the uniqueness of SARIF uploads. */
sentinelPrefix
:
string
;
/** Transforms the upload payload in an analysis-specific way. */
transformPayload
:
(
payload
:
UploadPayload
)
=>
BasePayload
;
}
// Represents the Code Scanning analysis configuration.
export
const
CodeScanning
:
AnalysisConfig
=
{
kind
:
AnalysisKind
.
CodeScanning
,
name
:
"code scanning"
,
target
:
SARIF_UPLOAD_ENDPOINT
.
CODE_SCANNING
,
sarifExtension
:
".sarif"
,
sarifPredicate
:
(
name
)
=>
name
.
endsWith
(
CodeScanning
.
sarifExtension
)
&&
!
CodeQuality
.
sarifPredicate
(
name
)
&&
!
RiskAssessment
.
sarifPredicate
(
name
)
,
fixCategory
:
(
_
,
category
)
=>
category
,
sentinelPrefix
:
"CODEQL_UPLOAD_SARIF_"
,
transformPayload
:
(
payload
)
=>
payload
,
}
;
// Represents the Code Quality analysis configuration.
export
const
CodeQuality
:
AnalysisConfig
=
{
kind
:
AnalysisKind
.
CodeQuality
,
name
:
"code quality"
,
target
:
SARIF_UPLOAD_ENDPOINT
.
CODE_QUALITY
,
sarifExtension
:
".quality.sarif"
,
sarifPredicate
:
(
name
)
=>
name
.
endsWith
(
CodeQuality
.
sarifExtension
)
,
fixCategory
:
fixCodeQualityCategory
,
sentinelPrefix
:
"CODEQL_UPLOAD_QUALITY_SARIF_"
,
transformPayload
:
(
payload
)
=>
payload
,
}
;
/**
* Retrieves the CSRA assessment id from an environment variable and adds it to the payload.
*
@param
payload The base payload.
*/
function
addAssessmentId
(
payload
:
UploadPayload
)
:
AssessmentPayload
{
const
rawAssessmentId
=
getRequiredEnvParam
(
EnvVar
.
RISK_ASSESSMENT_ID
)
;
const
assessmentId
=
parseInt
(
rawAssessmentId
,
10
)
;
if
(
Number
.
isNaN
(
assessmentId
)
)
{
throw
new
Error
(
`
${
EnvVar
.
RISK_ASSESSMENT_ID
}
must not be NaN:
${
rawAssessmentId
}
`
,
)
;
}
if
(
assessmentId
<
0
)
{
throw
new
Error
(
`
${
EnvVar
.
RISK_ASSESSMENT_ID
}
must not be negative:
${
rawAssessmentId
}
`
,
)
;
}
return
{
sarif
:
payload
.
sarif
,
assessment_id
:
assessmentId
}
;
}
export
const
RiskAssessment
:
AnalysisConfig
=
{
kind
:
AnalysisKind
.
RiskAssessment
,
name
:
"code scanning risk assessment"
,
target
:
SARIF_UPLOAD_ENDPOINT
.
RISK_ASSESSMENT
,
sarifExtension
:
".csra.sarif"
,
sarifPredicate
:
(
name
)
=>
name
.
endsWith
(
RiskAssessment
.
sarifExtension
)
,
fixCategory
:
(
_
,
category
)
=>
category
,
sentinelPrefix
:
"CODEQL_UPLOAD_CSRA_SARIF_"
,
transformPayload
:
addAssessmentId
,
}
;
/**
* Gets the `AnalysisConfig` corresponding to `kind`.
*
@param
kind The analysis kind to get the `AnalysisConfig` for.
*
@returns
The `AnalysisConfig` corresponding to `kind`.
*/
export
function
getAnalysisConfig
(
kind
:
AnalysisKind
)
:
AnalysisConfig
{
// Using a switch statement here accomplishes two things:
// 1. The type checker believes us that we have a case for every `AnalysisKind`.
// 2. If we ever add another member to `AnalysisKind`, the type checker will alert us that we have to add a case.
switch
(
kind
)
{
case
AnalysisKind
.
CodeScanning
:
return
CodeScanning
;
case
AnalysisKind
.
CodeQuality
:
return
CodeQuality
;
case
AnalysisKind
.
RiskAssessment
:
return
RiskAssessment
;
}
}
// Since we have overlapping extensions (i.e. ".sarif" includes ".quality.sarif"),
// we want to scan a folder containing SARIF files in an order that finds the more
// specific extensions first. This constant defines an array in the order of analyis
// configurations with more specific extensions to less specific extensions.
export
const
SarifScanOrder
:
AnalysisConfig
[
]
=
[
RiskAssessment
,
CodeQuality
,
CodeScanning
,
]
;
Back
|
FazBrowse Home
|
New Git URL