Skip to content

Commit 0337c4c

Browse files
authored
Merge pull request #3123 from github/mbg/fix/upload-sarif-cq-only
2 parents c22ae04 + db37d92 commit 0337c4c

File tree

5 files changed

+181
-94
lines changed

5 files changed

+181
-94
lines changed

.github/workflows/__upload-quality-sarif.yml

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/upload-sarif-action.js

Lines changed: 68 additions & 57 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pr-checks/checks/upload-quality-sarif.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ steps:
66
- uses: ./../action/init
77
with:
88
tools: ${{ steps.prepare-test.outputs.tools-url }}
9-
languages: cpp,csharp,java,javascript,python
10-
config-file: ${{ github.repository }}/tests/multi-language-repo/.github/codeql/custom-queries.yml@${{ github.sha }}
11-
analysis-kinds: code-scanning,code-quality
9+
languages: csharp,java,javascript,python
10+
analysis-kinds: code-quality
1211
- name: Build code
1312
run: ./build.sh
1413
# Generate some SARIF we can upload with the upload-sarif step
@@ -18,6 +17,10 @@ steps:
1817
sha: '5e235361806c361d4d3f8859e3c897658025a9a2'
1918
upload: never
2019
- uses: ./../action/upload-sarif
20+
id: upload-sarif
2121
with:
2222
ref: 'refs/heads/main'
2323
sha: '5e235361806c361d4d3f8859e3c897658025a9a2'
24+
- name: "Check output from `upload-sarif` step"
25+
if: fromJSON(steps.upload-sarif.outputs.sarif-ids)[0].analysis != 'code-quality'
26+
run: exit 1

src/upload-sarif-action.ts

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
3584
async 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) &&

upload-sarif/action.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ inputs:
3434
default: "true"
3535
outputs:
3636
sarif-id:
37-
description: The ID of the uploaded SARIF file.
37+
description: The ID of the uploaded Code Scanning SARIF file, if any.
38+
sarif-ids:
39+
description: |
40+
A stringified JSON object containing the SARIF ID for each kind of analysis. For example:
41+
42+
{ "code-scanning": "some-id", "code-quality": "some-other-id" }
3843
runs:
3944
using: node20
4045
main: '../lib/upload-sarif-action.js'

0 commit comments

Comments
 (0)