Compare commits

...

5 Commits

Author SHA1 Message Date
Michael B. Gale
483613152e Remove CodeQL init code from uploadSpecifiedFiles since it shouldn't be needed anymore 2025-08-07 12:25:23 +01:00
Michael B. Gale
dca95cdb78 Make the CodeQL instance a required parameter of uploadFiles
All the places that still call `uploadFiles` instead of `uploadSpecifiedFiles` are guaranteed to already have one.
2025-08-07 12:19:56 +01:00
Michael B. Gale
55b6208ff8 Initialise CodeQL CLI at most once in upload-sarif action 2025-08-07 12:19:39 +01:00
Michael B. Gale
e84e781d34 Refactor finding SARIF files for the different upload endpoints 2025-08-07 12:19:19 +01:00
Michael B. Gale
f4bf13aa48 Refactor CodeQL init code from combineSarifFilesUsingCLI into a new function 2025-08-07 12:17:22 +01:00
15 changed files with 165 additions and 106 deletions

4
lib/analyze-action.js generated
View File

@@ -229,10 +229,10 @@ async function run() {
core.setOutput("sarif-output", path_1.default.resolve(outputDir));
const uploadInput = actionsUtil.getOptionalInput("upload");
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger, uploadLib.CodeScanningTarget);
uploadResult = await uploadLib.uploadFiles(codeql, outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.getOptionalInput("category"), features, logger, uploadLib.CodeScanningTarget);
core.setOutput("sarif-id", uploadResult.sarifID);
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
const qualityUploadResult = await uploadLib.uploadFiles(outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.fixCodeQualityCategory(logger, actionsUtil.getOptionalInput("category")), features, logger, uploadLib.CodeQualityTarget);
const qualityUploadResult = await uploadLib.uploadFiles(codeql, outputDir, actionsUtil.getRequiredInput("checkout_path"), actionsUtil.fixCodeQualityCategory(logger, actionsUtil.getOptionalInput("category")), features, logger, uploadLib.CodeQualityTarget);
core.setOutput("quality-sarif-id", qualityUploadResult.sarifID);
}
}

File diff suppressed because one or more lines are too long

View File

@@ -87,7 +87,7 @@ async function maybeUploadFailedSarif(config, repositoryNwo, features, logger) {
await codeql.databaseExportDiagnostics(databasePath, sarifFile, category);
}
logger.info(`Uploading failed SARIF file ${sarifFile}`);
const uploadResult = await uploadLib.uploadFiles(sarifFile, checkoutPath, category, features, logger, uploadLib.CodeScanningTarget);
const uploadResult = await uploadLib.uploadFiles(codeql, sarifFile, checkoutPath, category, features, logger, uploadLib.CodeScanningTarget);
await uploadLib.waitForProcessing(repositoryNwo, uploadResult.sarifID, logger, { isUnsuccessfulExecution: true });
return uploadResult
? { ...uploadResult.statusReport, sarifID: uploadResult.sarifID }

File diff suppressed because one or more lines are too long

View File

@@ -348,7 +348,7 @@ async function testFailedSarifUpload(t, actionsWorkflow, { category, databaseExi
else {
t.true(diagnosticsExportStub.calledOnceWith(sinon.match.string, category, config), `Actual args were: ${JSON.stringify(diagnosticsExportStub.args)}`);
}
t.true(uploadFiles.calledOnceWith(sinon.match.string, sinon.match.string, category, sinon.match.any, sinon.match.any), `Actual args were: ${JSON.stringify(uploadFiles.args)}`);
t.true(uploadFiles.calledOnceWith(sinon.match.any, sinon.match.string, sinon.match.string, category, sinon.match.any, sinon.match.any), `Actual args were: ${JSON.stringify(uploadFiles.args)}`);
t.true(waitForProcessing.calledOnceWith(sinon.match.any, "42", sinon.match.any, {
isUnsuccessfulExecution: true,
}));

File diff suppressed because one or more lines are too long

57
lib/upload-lib.js generated
View File

@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.InvalidSarifUploadError = exports.CodeQualityTarget = exports.CodeScanningTarget = exports.SARIF_UPLOAD_ENDPOINT = void 0;
exports.shouldShowCombineSarifFilesDeprecationWarning = shouldShowCombineSarifFilesDeprecationWarning;
exports.throwIfCombineSarifFilesDisabled = throwIfCombineSarifFilesDisabled;
exports.initCodeQLForUpload = initCodeQLForUpload;
exports.populateRunAutomationDetails = populateRunAutomationDetails;
exports.findSarifFilesInDir = findSarifFilesInDir;
exports.getSarifFilePaths = getSarifFilePaths;
@@ -60,8 +61,6 @@ const jsonschema = __importStar(require("jsonschema"));
const actionsUtil = __importStar(require("./actions-util"));
const api = __importStar(require("./api-client"));
const api_client_1 = require("./api-client");
const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const environment_1 = require("./environment");
const fingerprints = __importStar(require("./fingerprints"));
@@ -168,11 +167,28 @@ async function shouldDisableCombineSarifFiles(sarifObjects, githubVersion) {
// error if multiple runs with the same category are uploaded.
return true;
}
/**
* Minimally initialises CodeQL if needed to combine SARIF files and CodeQL
* wasn't already initialised before.
*/
async function initCodeQLForUpload(gitHubVersion, features, logger) {
logger.info("Initializing CodeQL since the 'init' Action was not called before this step.");
const apiDetails = {
auth: actionsUtil.getRequiredInput("token"),
externalRepoAuth: actionsUtil.getOptionalInput("external-repository-token"),
url: (0, util_1.getRequiredEnvParam)("GITHUB_SERVER_URL"),
apiURL: (0, util_1.getRequiredEnvParam)("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(gitHubVersion.type);
const initCodeQLResult = await (0, init_1.initCodeQL)(undefined, // There is no tools input on the upload action
apiDetails, actionsUtil.getTemporaryDirectory(), gitHubVersion.type, codeQLDefaultVersionInfo, features, logger);
return initCodeQLResult.codeql;
}
// Takes a list of paths to sarif files and combines them together using the
// CLI `github merge-results` command when all SARIF files are produced by
// CodeQL. Otherwise, it will fall back to combining the files in the action.
// Returns the contents of the combined sarif file.
async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger) {
async function combineSarifFilesUsingCLI(codeQL, sarifFiles, gitHubVersion, logger) {
logger.info("Combining SARIF files using the CodeQL CLI");
const sarifObjects = sarifFiles.map((sarifFile) => {
return JSON.parse(fs.readFileSync(sarifFile, "utf8"));
@@ -191,28 +207,6 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
// If not, use the naive method of combining the files.
return combineSarifFiles(sarifFiles, logger);
}
// Initialize CodeQL, either by using the config file from the 'init' step,
// or by initializing it here.
let codeQL;
let tempDir = actionsUtil.getTemporaryDirectory();
const config = await (0, config_utils_1.getConfig)(tempDir, logger);
if (config !== undefined) {
codeQL = await (0, codeql_1.getCodeQL)(config.codeQLCmd);
tempDir = config.tempDir;
}
else {
logger.info("Initializing CodeQL since the 'init' Action was not called before this step.");
const apiDetails = {
auth: actionsUtil.getRequiredInput("token"),
externalRepoAuth: actionsUtil.getOptionalInput("external-repository-token"),
url: (0, util_1.getRequiredEnvParam)("GITHUB_SERVER_URL"),
apiURL: (0, util_1.getRequiredEnvParam)("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(gitHubVersion.type);
const initCodeQLResult = await (0, init_1.initCodeQL)(undefined, // There is no tools input on the upload action
apiDetails, tempDir, gitHubVersion.type, codeQLDefaultVersionInfo, features, logger);
codeQL = initCodeQLResult.codeql;
}
if (!(await codeQL.supportsFeature(tools_features_1.ToolsFeature.SarifMergeRunsFromEqualCategory))) {
await throwIfCombineSarifFilesDisabled(sarifObjects, gitHubVersion);
logger.warning("The CodeQL CLI does not support merging SARIF files. Merging files in the action.");
@@ -222,6 +216,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
}
return combineSarifFiles(sarifFiles, logger);
}
const tempDir = actionsUtil.getTemporaryDirectory();
const baseTempDir = path.resolve(tempDir, "combined-sarif");
fs.mkdirSync(baseTempDir, { recursive: true });
const outputDirectory = fs.mkdtempSync(path.resolve(baseTempDir, "output-"));
@@ -456,14 +451,14 @@ exports.CodeQualityTarget = {
* 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, uploadTarget) {
async function uploadFiles(codeQL, inputSarifPath, checkoutPath, category, features, logger, uploadTarget) {
const sarifPaths = getSarifFilePaths(inputSarifPath, uploadTarget.sarifPredicate);
return uploadSpecifiedFiles(sarifPaths, checkoutPath, category, features, logger, uploadTarget);
return uploadSpecifiedFiles(codeQL, sarifPaths, checkoutPath, category, features, logger, uploadTarget);
}
/**
* Uploads the given array of SARIF files.
*/
async function uploadSpecifiedFiles(sarifPaths, checkoutPath, category, features, logger, uploadTarget = exports.CodeScanningTarget) {
async function uploadSpecifiedFiles(codeQL, sarifPaths, checkoutPath, category, _features, logger, uploadTarget = exports.CodeScanningTarget) {
logger.startGroup(`Uploading ${uploadTarget.name} results`);
logger.info(`Processing sarif files: ${JSON.stringify(sarifPaths)}`);
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
@@ -474,7 +469,11 @@ async function uploadSpecifiedFiles(sarifPaths, checkoutPath, category, features
const parsedSarif = readSarifFile(sarifPath);
validateSarifFileSchema(parsedSarif, sarifPath, logger);
}
sarif = await combineSarifFilesUsingCLI(sarifPaths, gitHubVersion, features, logger);
// CodeQL should always be initialised at this point if we have multiple sarif files.
if (codeQL === undefined) {
throw new Error(`Unexpectedly, CodeQL has not been initialised for the upload of multiple files.`);
}
sarif = await combineSarifFilesUsingCLI(codeQL, sarifPaths, gitHubVersion, logger);
}
else {
const sarifPath = sarifPaths[0];

File diff suppressed because one or more lines are too long

View File

@@ -54,6 +54,18 @@ async function sendSuccessStatusReport(startedAt, uploadStats, logger) {
await (0, status_report_1.sendStatusReport)(statusReport);
}
}
async function findSecuritySarifFiles(sarifPath) {
if (fs.lstatSync(sarifPath).isDirectory()) {
return upload_lib.findSarifFilesInDir(sarifPath, upload_lib.CodeScanningTarget.sarifPredicate);
}
return [sarifPath];
}
async function findQualitySarifFiles(sarifPath) {
if (fs.lstatSync(sarifPath).isDirectory()) {
return upload_lib.findSarifFilesInDir(sarifPath, upload_lib.CodeQualityTarget.sarifPredicate);
}
return [];
}
async function run() {
const startedAt = new Date();
const logger = (0, logging_1.getActionsLogger)();
@@ -72,16 +84,21 @@ async function run() {
const sarifPath = actionsUtil.getRequiredInput("sarif_file");
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
const category = actionsUtil.getOptionalInput("category");
const uploadResult = await upload_lib.uploadFiles(sarifPath, checkoutPath, category, features, logger, upload_lib.CodeScanningTarget);
const securitySarifFiles = await findSecuritySarifFiles(sarifPath);
const qualitySarifFiles = await findQualitySarifFiles(sarifPath);
// If we have more than one SARIF file for a given service, then we need to combine
// them using the CLI. To avoid initialising the CLI twice in one run, we do it here.
let codeql;
if (securitySarifFiles.length > 1 || qualitySarifFiles.length > 1) {
codeql = await upload_lib.initCodeQLForUpload(gitHubVersion, features, logger);
}
const uploadResult = await upload_lib.uploadSpecifiedFiles(codeql, securitySarifFiles, checkoutPath, category, features, logger, upload_lib.CodeScanningTarget);
core.setOutput("sarif-id", uploadResult.sarifID);
// If there are `.quality.sarif` files in `sarifPath`, then upload those to the code quality service.
// Code quality can currently only be enabled on top of security, so we'd currently always expect to
// have a directory for the results here.
if (fs.lstatSync(sarifPath).isDirectory()) {
const qualitySarifFiles = upload_lib.findSarifFilesInDir(sarifPath, upload_lib.CodeQualityTarget.sarifPredicate);
if (qualitySarifFiles.length !== 0) {
await upload_lib.uploadSpecifiedFiles(qualitySarifFiles, checkoutPath, actionsUtil.fixCodeQualityCategory(logger, category), features, logger, upload_lib.CodeQualityTarget);
}
if (qualitySarifFiles.length !== 0) {
await upload_lib.uploadSpecifiedFiles(codeql, qualitySarifFiles, checkoutPath, actionsUtil.fixCodeQualityCategory(logger, category), features, logger, upload_lib.CodeQualityTarget);
}
// We don't upload results in test mode, so don't wait for processing
if ((0, util_1.isInTestMode)()) {

View File

@@ -1 +1 @@
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAEzB,oDAAsC;AAEtC,4DAA8C;AAC9C,iDAAyE;AACzE,6CAAgD;AAChD,mDAA2C;AAC3C,uCAAqD;AACrD,6CAAgD;AAChD,mDAOyB;AACzB,yDAA2C;AAC3C,iCAQgB;AAMhB,KAAK,UAAU,uBAAuB,CACpC,SAAe,EACf,WAA0C,EAC1C,MAAc;IAEd,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,WAAW,EACtB,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAA4B;YAC5C,GAAG,gBAAgB;YACnB,GAAG,WAAW;SACf,CAAC;QACF,MAAM,IAAA,gCAAgB,EAAC,YAAY,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,IAAA,4BAAqB,EAAC,IAAA,+BAAgB,GAAE,CAAC,CAAC;IAE1C,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;IAC/C,IAAA,yBAAkB,EAAC,IAAA,+BAAgB,GAAE,EAAE,aAAa,CAAC,CAAC;IAEtD,6CAA6C;IAC7C,WAAW,CAAC,aAAa,EAAE,CAAC;IAE5B,MAAM,aAAa,GAAG,IAAA,6BAAgB,GAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,wBAAQ,CAC3B,aAAa,EACb,aAAa,EACb,IAAA,oCAAqB,GAAE,EACvB,MAAM,CACP,CAAC;IAEF,MAAM,wBAAwB,GAAG,MAAM,IAAA,sCAAsB,EAC3D,0BAAU,CAAC,WAAW,EACtB,UAAU,EACV,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,wBAAwB,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAA,gCAAgB,EAAC,wBAAwB,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,WAAW,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAE1D,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,WAAW,CAC/C,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAU,CAAC,kBAAkB,CAC9B,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QAEjD,qGAAqG;QACrG,oGAAoG;QACpG,yCAAyC;QACzC,IAAI,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1C,MAAM,iBAAiB,GAAG,UAAU,CAAC,mBAAmB,CACtD,SAAS,EACT,UAAU,CAAC,iBAAiB,CAAC,cAAc,CAC5C,CAAC;YAEF,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,MAAM,UAAU,CAAC,oBAAoB,CACnC,iBAAiB,EACjB,YAAY,EACZ,WAAW,CAAC,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,EACpD,QAAQ,EACR,MAAM,EACN,UAAU,CAAC,iBAAiB,CAC7B,CAAC;YACJ,CAAC;QACH,CAAC;QAED,qEAAqE;QACrE,IAAI,IAAA,mBAAY,GAAE,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,WAAW,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,KAAK,MAAM,EAAE,CAAC;YAC1E,MAAM,UAAU,CAAC,iBAAiB,CAChC,IAAA,6BAAgB,GAAE,EAClB,YAAY,CAAC,OAAO,EACpB,MAAM,CACP,CAAC;YACF,6FAA6F;YAC7F,kCAAkC;QACpC,CAAC;QACD,MAAM,uBAAuB,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GACT,IAAA,oCAAoB,EAAC,0BAAU,CAAC,WAAW,CAAC;YAC5C,cAAc,YAAY,UAAU,CAAC,uBAAuB;YAC1D,CAAC,CAAC,IAAI,yBAAkB,CAAC,cAAc,CAAC,OAAO,CAAC;YAChD,CAAC,CAAC,IAAA,gBAAS,EAAC,cAAc,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,qBAAqB,GAAG,MAAM,IAAA,sCAAsB,EACxD,0BAAU,CAAC,WAAW,EACtB,IAAA,gCAAgB,EAAC,KAAK,CAAC,EACvB,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,KAAK,CAAC,KAAK,CACZ,CAAC;QACF,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,IAAA,gCAAgB,EAAC,qBAAqB,CAAC,CAAC;QAChD,CAAC;QACD,OAAO;IACT,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,sCAAsC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAC/D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":"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"}

View File

@@ -344,6 +344,7 @@ async function run() {
const uploadInput = actionsUtil.getOptionalInput("upload");
if (runStats && actionsUtil.getUploadValue(uploadInput) === "always") {
uploadResult = await uploadLib.uploadFiles(
codeql,
outputDir,
actionsUtil.getRequiredInput("checkout_path"),
actionsUtil.getOptionalInput("category"),
@@ -355,6 +356,7 @@ async function run() {
if (config.augmentationProperties.qualityQueriesInput !== undefined) {
const qualityUploadResult = await uploadLib.uploadFiles(
codeql,
outputDir,
actionsUtil.getRequiredInput("checkout_path"),
actionsUtil.fixCodeQualityCategory(

View File

@@ -407,6 +407,7 @@ async function testFailedSarifUpload(
}
t.true(
uploadFiles.calledOnceWith(
sinon.match.any,
sinon.match.string,
sinon.match.string,
category,

View File

@@ -99,6 +99,7 @@ async function maybeUploadFailedSarif(
logger.info(`Uploading failed SARIF file ${sarifFile}`);
const uploadResult = await uploadLib.uploadFiles(
codeql,
sarifFile,
checkoutPath,
category,

View File

@@ -10,8 +10,7 @@ import * as jsonschema from "jsonschema";
import * as actionsUtil from "./actions-util";
import * as api from "./api-client";
import { getGitHubVersion, wrapApiConfigurationError } from "./api-client";
import { CodeQL, getCodeQL } from "./codeql";
import { getConfig } from "./config-utils";
import { CodeQL } from "./codeql";
import { readDiffRangesJsonFile } from "./diff-informed-analysis-utils";
import { EnvVar } from "./environment";
import { FeatureEnablement } from "./feature-flags";
@@ -182,14 +181,51 @@ async function shouldDisableCombineSarifFiles(
return true;
}
/**
* Minimally initialises CodeQL if needed to combine SARIF files and CodeQL
* wasn't already initialised before.
*/
export async function initCodeQLForUpload(
gitHubVersion: GitHubVersion,
features: FeatureEnablement,
logger: Logger,
): Promise<CodeQL> {
logger.info(
"Initializing CodeQL since the 'init' Action was not called before this step.",
);
const apiDetails = {
auth: actionsUtil.getRequiredInput("token"),
externalRepoAuth: actionsUtil.getOptionalInput("external-repository-token"),
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const initCodeQLResult = await initCodeQL(
undefined, // There is no tools input on the upload action
apiDetails,
actionsUtil.getTemporaryDirectory(),
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger,
);
return initCodeQLResult.codeql;
}
// Takes a list of paths to sarif files and combines them together using the
// CLI `github merge-results` command when all SARIF files are produced by
// CodeQL. Otherwise, it will fall back to combining the files in the action.
// Returns the contents of the combined sarif file.
async function combineSarifFilesUsingCLI(
codeQL: CodeQL,
sarifFiles: string[],
gitHubVersion: GitHubVersion,
features: FeatureEnablement,
logger: Logger,
): Promise<SarifFile> {
logger.info("Combining SARIF files using the CodeQL CLI");
@@ -228,46 +264,6 @@ async function combineSarifFilesUsingCLI(
return combineSarifFiles(sarifFiles, logger);
}
// Initialize CodeQL, either by using the config file from the 'init' step,
// or by initializing it here.
let codeQL: CodeQL;
let tempDir: string = actionsUtil.getTemporaryDirectory();
const config = await getConfig(tempDir, logger);
if (config !== undefined) {
codeQL = await getCodeQL(config.codeQLCmd);
tempDir = config.tempDir;
} else {
logger.info(
"Initializing CodeQL since the 'init' Action was not called before this step.",
);
const apiDetails = {
auth: actionsUtil.getRequiredInput("token"),
externalRepoAuth: actionsUtil.getOptionalInput(
"external-repository-token",
),
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
};
const codeQLDefaultVersionInfo = await features.getDefaultCliVersion(
gitHubVersion.type,
);
const initCodeQLResult = await initCodeQL(
undefined, // There is no tools input on the upload action
apiDetails,
tempDir,
gitHubVersion.type,
codeQLDefaultVersionInfo,
features,
logger,
);
codeQL = initCodeQLResult.codeql;
}
if (
!(await codeQL.supportsFeature(
ToolsFeature.SarifMergeRunsFromEqualCategory,
@@ -294,6 +290,7 @@ async function combineSarifFilesUsingCLI(
return combineSarifFiles(sarifFiles, logger);
}
const tempDir = actionsUtil.getTemporaryDirectory();
const baseTempDir = path.resolve(tempDir, "combined-sarif");
fs.mkdirSync(baseTempDir, { recursive: true });
const outputDirectory = fs.mkdtempSync(path.resolve(baseTempDir, "output-"));
@@ -647,6 +644,7 @@ export const CodeQualityTarget: UploadTarget = {
* to.
*/
export async function uploadFiles(
codeQL: CodeQL,
inputSarifPath: string,
checkoutPath: string,
category: string | undefined,
@@ -660,6 +658,7 @@ export async function uploadFiles(
);
return uploadSpecifiedFiles(
codeQL,
sarifPaths,
checkoutPath,
category,
@@ -673,10 +672,11 @@ export async function uploadFiles(
* Uploads the given array of SARIF files.
*/
export async function uploadSpecifiedFiles(
codeQL: CodeQL | undefined,
sarifPaths: string[],
checkoutPath: string,
category: string | undefined,
features: FeatureEnablement,
_features: FeatureEnablement,
logger: Logger,
uploadTarget: UploadTarget = CodeScanningTarget,
): Promise<UploadResult> {
@@ -694,10 +694,17 @@ export async function uploadSpecifiedFiles(
validateSarifFileSchema(parsedSarif, sarifPath, logger);
}
// CodeQL should always be initialised at this point if we have multiple sarif files.
if (codeQL === undefined) {
throw new Error(
`Unexpectedly, CodeQL has not been initialised for the upload of multiple files.`,
);
}
sarif = await combineSarifFilesUsingCLI(
codeQL,
sarifPaths,
gitHubVersion,
features,
logger,
);
} else {

View File

@@ -5,6 +5,7 @@ import * as core from "@actions/core";
import * as actionsUtil from "./actions-util";
import { getActionVersion, getTemporaryDirectory } from "./actions-util";
import { getGitHubVersion } from "./api-client";
import { CodeQL } from "./codeql";
import { Features } from "./feature-flags";
import { Logger, getActionsLogger } from "./logging";
import { getRepositoryNwo } from "./repository";
@@ -53,6 +54,28 @@ async function sendSuccessStatusReport(
}
}
async function findSecuritySarifFiles(sarifPath: string): Promise<string[]> {
if (fs.lstatSync(sarifPath).isDirectory()) {
return upload_lib.findSarifFilesInDir(
sarifPath,
upload_lib.CodeScanningTarget.sarifPredicate,
);
}
return [sarifPath];
}
async function findQualitySarifFiles(sarifPath: string): Promise<string[]> {
if (fs.lstatSync(sarifPath).isDirectory()) {
return upload_lib.findSarifFilesInDir(
sarifPath,
upload_lib.CodeQualityTarget.sarifPredicate,
);
}
return [];
}
async function run() {
const startedAt = new Date();
const logger = getActionsLogger();
@@ -89,8 +112,23 @@ async function run() {
const checkoutPath = actionsUtil.getRequiredInput("checkout_path");
const category = actionsUtil.getOptionalInput("category");
const uploadResult = await upload_lib.uploadFiles(
sarifPath,
const securitySarifFiles = await findSecuritySarifFiles(sarifPath);
const qualitySarifFiles = await findQualitySarifFiles(sarifPath);
// If we have more than one SARIF file for a given service, then we need to combine
// them using the CLI. To avoid initialising the CLI twice in one run, we do it here.
let codeql: CodeQL | undefined;
if (securitySarifFiles.length > 1 || qualitySarifFiles.length > 1) {
codeql = await upload_lib.initCodeQLForUpload(
gitHubVersion,
features,
logger,
);
}
const uploadResult = await upload_lib.uploadSpecifiedFiles(
codeql,
securitySarifFiles,
checkoutPath,
category,
features,
@@ -102,22 +140,16 @@ async function run() {
// If there are `.quality.sarif` files in `sarifPath`, then upload those to the code quality service.
// Code quality can currently only be enabled on top of security, so we'd currently always expect to
// have a directory for the results here.
if (fs.lstatSync(sarifPath).isDirectory()) {
const qualitySarifFiles = upload_lib.findSarifFilesInDir(
sarifPath,
upload_lib.CodeQualityTarget.sarifPredicate,
if (qualitySarifFiles.length !== 0) {
await upload_lib.uploadSpecifiedFiles(
codeql,
qualitySarifFiles,
checkoutPath,
actionsUtil.fixCodeQualityCategory(logger, category),
features,
logger,
upload_lib.CodeQualityTarget,
);
if (qualitySarifFiles.length !== 0) {
await upload_lib.uploadSpecifiedFiles(
qualitySarifFiles,
checkoutPath,
actionsUtil.fixCodeQualityCategory(logger, category),
features,
logger,
upload_lib.CodeQualityTarget,
);
}
}
// We don't upload results in test mode, so don't wait for processing