Upload quality SARIFs to CQ endpoint

This commit is contained in:
Michael B. Gale 2025-06-17 14:36:36 +01:00
parent 22444a650f
commit 45b3bec064
No known key found for this signature in database
GPG key ID: FF5E2765BD00628F
6 changed files with 78 additions and 18 deletions

4
lib/analyze-action.js generated
View file

@ -218,6 +218,10 @@ async function run() {
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger);
core.setOutput("sarif-id", uploadResult.sarifID);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
const qualityUploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger, uploadLib.CodeQualityTarget);
core.setOutput("quality-sarif-id", qualityUploadResult.sarifID);
}
}
else {
logger.info("Not uploading results");

File diff suppressed because one or more lines are too long

28
lib/upload-lib.js generated
View file

@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InvalidSarifUploadError = void 0;
exports.InvalidSarifUploadError = exports.CodeQualityTarget = exports.CodeScanningTarget = exports.SARIF_UPLOAD_TARGET = void 0;
exports.shouldShowCombineSarifFilesDeprecationWarning = shouldShowCombineSarifFilesDeprecationWarning;
exports.populateRunAutomationDetails = populateRunAutomationDetails;
exports.findSarifFilesInDir = findSarifFilesInDir;
@ -234,9 +234,15 @@ function getAutomationID(category, analysis_key, environment) {
}
return api.computeAutomationID(analysis_key, environment);
}
// Enumerates API endpoints that accept SARIF files.
var SARIF_UPLOAD_TARGET;
(function (SARIF_UPLOAD_TARGET) {
SARIF_UPLOAD_TARGET["CODE_SCANNING_UPLOAD_TARGET"] = "PUT /repos/:owner/:repo/code-scanning/analysis";
SARIF_UPLOAD_TARGET["CODE_QUALITY_UPLOAD_TARGET"] = "PUT /repos/:owner/:repo/code-quality/analysis";
})(SARIF_UPLOAD_TARGET || (exports.SARIF_UPLOAD_TARGET = SARIF_UPLOAD_TARGET = {}));
// Upload the given payload.
// If the request fails then this will retry a small number of times.
async function uploadPayload(payload, repositoryNwo, logger) {
async function uploadPayload(payload, repositoryNwo, logger, target = SARIF_UPLOAD_TARGET.CODE_SCANNING_UPLOAD_TARGET) {
logger.info("Uploading results");
// If in test mode we don't want to upload the results
if (util.isInTestMode()) {
@ -248,7 +254,7 @@ async function uploadPayload(payload, repositoryNwo, logger) {
}
const client = api.getApiClient();
try {
const response = await client.request("PUT /repos/:owner/:repo/code-scanning/analysis", {
const response = await client.request(target, {
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
data: payload,
@ -411,13 +417,23 @@ function buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, wo
}
return payloadObj;
}
exports.CodeScanningTarget = {
name: "code scanning",
target: SARIF_UPLOAD_TARGET.CODE_SCANNING_UPLOAD_TARGET,
sarifFilter: defaultIsSarif,
};
exports.CodeQualityTarget = {
name: "code quality",
target: SARIF_UPLOAD_TARGET.CODE_QUALITY_UPLOAD_TARGET,
sarifFilter: qualityIsSarif,
};
/**
* Uploads a single SARIF file or a directory of SARIF files depending on what `inputSarifPath` refers
* to.
*/
async function uploadFiles(inputSarifPath, checkoutPath, category, features, logger) {
async function uploadFiles(inputSarifPath, checkoutPath, category, features, logger, uploadTarget = exports.CodeScanningTarget) {
const sarifPaths = getSarifFilePaths(inputSarifPath);
logger.startGroup("Uploading results");
logger.startGroup(`Uploading ${uploadTarget.name} results`);
logger.info(`Processing sarif files: ${JSON.stringify(sarifPaths)}`);
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
let sarif;
@ -456,7 +472,7 @@ async function uploadFiles(inputSarifPath, checkoutPath, category, features, log
const numResultInSarif = countResultsInSarif(sarifPayload);
logger.debug(`Number of results in upload: ${numResultInSarif}`);
// Make the upload
const sarifID = await uploadPayload(payload, (0, repository_1.getRepositoryNwo)(), logger);
const sarifID = await uploadPayload(payload, (0, repository_1.getRepositoryNwo)(), logger, uploadTarget.target);
logger.endGroup();
return {
statusReport: {

File diff suppressed because one or more lines are too long

View file

@ -329,6 +329,18 @@ async function run() {
logger,
);
core.setOutput("sarif-id", uploadResult.sarifID);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
const qualityUploadResult = await uploadLib.uploadFiles(
outputDir,
actionsUtil.getRequiredInput("checkout_path"),
actionsUtil.getOptionalInput("category"),
features,
logger,
uploadLib.CodeQualityTarget,
);
core.setOutput("quality-sarif-id", qualityUploadResult.sarifID);
}
} else {
logger.info("Not uploading results");
}

View file

@ -306,12 +306,19 @@ function getAutomationID(
return api.computeAutomationID(analysis_key, environment);
}
// Enumerates API endpoints that accept SARIF files.
export enum SARIF_UPLOAD_TARGET {
CODE_SCANNING_UPLOAD_TARGET = "PUT /repos/:owner/:repo/code-scanning/analysis",
CODE_QUALITY_UPLOAD_TARGET = "PUT /repos/:owner/:repo/code-quality/analysis",
}
// Upload the given payload.
// If the request fails then this will retry a small number of times.
async function uploadPayload(
payload: any,
repositoryNwo: RepositoryNwo,
logger: Logger,
target: SARIF_UPLOAD_TARGET = SARIF_UPLOAD_TARGET.CODE_SCANNING_UPLOAD_TARGET,
): Promise<string> {
logger.info("Uploading results");
@ -332,14 +339,11 @@ async function uploadPayload(
const client = api.getApiClient();
try {
const response = await client.request(
"PUT /repos/:owner/:repo/code-scanning/analysis",
{
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
data: payload,
},
);
const response = await client.request(target, {
owner: repositoryNwo.owner,
repo: repositoryNwo.repo,
data: payload,
});
logger.debug(`response status: ${response.status}`);
logger.info("Successfully uploaded results");
@ -574,6 +578,24 @@ export function buildPayload(
return payloadObj;
}
export interface UploadTarget {
name: string;
target: SARIF_UPLOAD_TARGET;
sarifFilter: (name: string) => boolean;
}
export const CodeScanningTarget: UploadTarget = {
name: "code scanning",
target: SARIF_UPLOAD_TARGET.CODE_SCANNING_UPLOAD_TARGET,
sarifFilter: defaultIsSarif,
};
export const CodeQualityTarget: UploadTarget = {
name: "code quality",
target: SARIF_UPLOAD_TARGET.CODE_QUALITY_UPLOAD_TARGET,
sarifFilter: qualityIsSarif,
};
/**
* Uploads a single SARIF file or a directory of SARIF files depending on what `inputSarifPath` refers
* to.
@ -584,10 +606,11 @@ export async function uploadFiles(
category: string | undefined,
features: FeatureEnablement,
logger: Logger,
uploadTarget: UploadTarget = CodeScanningTarget,
): Promise<UploadResult> {
const sarifPaths = getSarifFilePaths(inputSarifPath);
logger.startGroup("Uploading results");
logger.startGroup(`Uploading ${uploadTarget.name} results`);
logger.info(`Processing sarif files: ${JSON.stringify(sarifPaths)}`);
const gitHubVersion = await getGitHubVersion();
@ -658,7 +681,12 @@ export async function uploadFiles(
logger.debug(`Number of results in upload: ${numResultInSarif}`);
// Make the upload
const sarifID = await uploadPayload(payload, getRepositoryNwo(), logger);
const sarifID = await uploadPayload(
payload,
getRepositoryNwo(),
logger,
uploadTarget.target,
);
logger.endGroup();