@@ -32,6 +32,55 @@ interface UploadSarifStatusReport
3232 extends StatusReportBase ,
3333 upload_lib . UploadStatusReport { }
3434
35+ /**
36+ * Searches for SARIF files for the given `analysis` in the given `sarifPath`.
37+ * If any are found, then they are uploaded to the appropriate endpoint for the given `analysis`.
38+ *
39+ * @param logger The logger to use.
40+ * @param features Information about FFs.
41+ * @param sarifPath The path to a SARIF file or directory containing SARIF files.
42+ * @param pathStats Information about `sarifPath`.
43+ * @param checkoutPath The checkout path.
44+ * @param analysis The configuration of the analysis we should upload SARIF files for.
45+ * @param category The SARIF category to use for the upload.
46+ * @returns The result of uploading the SARIF file(s) or `undefined` if there are none.
47+ */
48+ async function findAndUpload (
49+ logger : Logger ,
50+ features : Features ,
51+ sarifPath : string ,
52+ pathStats : fs . Stats ,
53+ checkoutPath : string ,
54+ analysis : analyses . AnalysisConfig ,
55+ category ?: string ,
56+ ) : Promise < upload_lib . UploadResult | undefined > {
57+ let sarifFiles : string [ ] | undefined ;
58+
59+ if ( pathStats . isDirectory ( ) ) {
60+ sarifFiles = upload_lib . findSarifFilesInDir (
61+ sarifPath ,
62+ analysis . sarifPredicate ,
63+ ) ;
64+ } else if ( pathStats . isFile ( ) && analysis . sarifPredicate ( sarifPath ) ) {
65+ sarifFiles = [ sarifPath ] ;
66+ } else {
67+ return undefined ;
68+ }
69+
70+ if ( sarifFiles . length !== 0 ) {
71+ return await upload_lib . uploadSpecifiedFiles (
72+ sarifFiles ,
73+ checkoutPath ,
74+ category ,
75+ features ,
76+ logger ,
77+ analysis ,
78+ ) ;
79+ }
80+
81+ return undefined ;
82+ }
83+
3584async function sendSuccessStatusReport (
3685 startedAt : Date ,
3786 uploadStats : upload_lib . UploadStatusReport ,
@@ -86,54 +135,71 @@ async function run() {
86135 }
87136
88137 try {
138+ // `sarifPath` can either be a path to a single file, or a path to a directory.
89139 const sarifPath = actionsUtil . getRequiredInput ( "sarif_file" ) ;
90140 const checkoutPath = actionsUtil . getRequiredInput ( "checkout_path" ) ;
91141 const category = actionsUtil . getOptionalInput ( "category" ) ;
142+ const pathStats = fs . lstatSync ( sarifPath , { throwIfNoEntry : false } ) ;
92143
93- const uploadResult = await upload_lib . uploadFiles (
144+ if ( pathStats === undefined ) {
145+ throw new ConfigurationError ( `Path does not exist: ${ sarifPath } .` ) ;
146+ }
147+
148+ const sarifIds : Array < { analysis : string ; id : string } > = [ ] ;
149+ const uploadResult = await findAndUpload (
150+ logger ,
151+ features ,
94152 sarifPath ,
153+ pathStats ,
95154 checkoutPath ,
96- category ,
97- features ,
98- logger ,
99155 analyses . CodeScanning ,
156+ category ,
100157 ) ;
101- core . setOutput ( "sarif-id" , uploadResult . sarifID ) ;
158+ if ( uploadResult !== undefined ) {
159+ core . setOutput ( "sarif-id" , uploadResult . sarifID ) ;
160+ sarifIds . push ( {
161+ analysis : analyses . AnalysisKind . CodeScanning ,
162+ id : uploadResult . sarifID ,
163+ } ) ;
164+ }
102165
103166 // If there are `.quality.sarif` files in `sarifPath`, then upload those to the code quality service.
104- // Code quality can currently only be enabled on top of security, so we'd currently always expect to
105- // have a directory for the results here.
106- if ( fs . lstatSync ( sarifPath ) . isDirectory ( ) ) {
107- const qualitySarifFiles = upload_lib . findSarifFilesInDir (
108- sarifPath ,
109- analyses . CodeQuality . sarifPredicate ,
110- ) ;
111-
112- if ( qualitySarifFiles . length !== 0 ) {
113- await upload_lib . uploadSpecifiedFiles (
114- qualitySarifFiles ,
115- checkoutPath ,
116- actionsUtil . fixCodeQualityCategory ( logger , category ) ,
117- features ,
118- logger ,
119- analyses . CodeQuality ,
120- ) ;
121- }
167+ const qualityUploadResult = await findAndUpload (
168+ logger ,
169+ features ,
170+ sarifPath ,
171+ pathStats ,
172+ checkoutPath ,
173+ analyses . CodeQuality ,
174+ actionsUtil . fixCodeQualityCategory ( logger , category ) ,
175+ ) ;
176+ if ( qualityUploadResult !== undefined ) {
177+ sarifIds . push ( {
178+ analysis : analyses . AnalysisKind . CodeQuality ,
179+ id : qualityUploadResult . sarifID ,
180+ } ) ;
122181 }
182+ core . setOutput ( "sarif-ids" , JSON . stringify ( sarifIds ) ) ;
123183
124184 // We don't upload results in test mode, so don't wait for processing
125185 if ( isInTestMode ( ) ) {
126186 core . debug ( "In test mode. Waiting for processing is disabled." ) ;
127187 } else if ( actionsUtil . getRequiredInput ( "wait-for-processing" ) === "true" ) {
128- await upload_lib . waitForProcessing (
129- getRepositoryNwo ( ) ,
130- uploadResult . sarifID ,
131- logger ,
132- ) ;
188+ if ( uploadResult !== undefined ) {
189+ await upload_lib . waitForProcessing (
190+ getRepositoryNwo ( ) ,
191+ uploadResult . sarifID ,
192+ logger ,
193+ ) ;
194+ }
133195 // The code quality service does not currently have an endpoint to wait for SARIF processing,
134196 // so we can't wait for that here.
135197 }
136- await sendSuccessStatusReport ( startedAt , uploadResult . statusReport , logger ) ;
198+ await sendSuccessStatusReport (
199+ startedAt ,
200+ uploadResult ?. statusReport || { } ,
201+ logger ,
202+ ) ;
137203 } catch ( unwrappedError ) {
138204 const error =
139205 isThirdPartyAnalysis ( ActionName . UploadSarif ) &&
0 commit comments