mirror of
https://github.com/github/codeql-action.git
synced 2025-12-14 03:20:11 +08:00
Compare commits
21 Commits
v1.0.27
...
codeql-bun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0b507e521 | ||
|
|
d563b098d7 | ||
|
|
fca047627b | ||
|
|
28fe8e7028 | ||
|
|
8a4b243fbf | ||
|
|
19970ae6b5 | ||
|
|
ec1b16574e | ||
|
|
b31df3ff95 | ||
|
|
776db51d2e | ||
|
|
b886234637 | ||
|
|
9913c9bfa5 | ||
|
|
8de62beb50 | ||
|
|
b6fbccaba1 | ||
|
|
df0c306daf | ||
|
|
ab1f709732 | ||
|
|
8454e21c9c | ||
|
|
d85c3e58ec | ||
|
|
cbabe47a0b | ||
|
|
f8a48f464d | ||
|
|
f6f23f8671 | ||
|
|
c2a7379048 |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,10 +1,18 @@
|
|||||||
# CodeQL Action and CodeQL Runner Changelog
|
# CodeQL Action and CodeQL Runner Changelog
|
||||||
|
|
||||||
|
## [UNRELEASED]
|
||||||
|
|
||||||
|
No user facing changes.
|
||||||
|
|
||||||
|
## 1.0.28 - 18 Jan 2022
|
||||||
|
|
||||||
|
- Update default CodeQL bundle version to 2.7.5. [#866](https://github.com/github/codeql-action/pull/866)
|
||||||
|
- Fix a bug where SARIF files were failing upload due to an invalid test for unique categories. [#872](https://github.com/github/codeql-action/pull/872)
|
||||||
|
|
||||||
## 1.0.27 - 11 Jan 2022
|
## 1.0.27 - 11 Jan 2022
|
||||||
|
|
||||||
- The `analyze` and `upload-sarif` actions will now wait up to 2 minutes for processing to complete after they have uploaded the results so they can report any processing errors that occurred. This behavior can be disabled by setting the `wait-for-processing` action input to `"false"`.
|
- The `analyze` and `upload-sarif` actions will now wait up to 2 minutes for processing to complete after they have uploaded the results so they can report any processing errors that occurred. This behavior can be disabled by setting the `wait-for-processing` action input to `"false"`.
|
||||||
|
|
||||||
|
|
||||||
## 1.0.26 - 10 Dec 2021
|
## 1.0.26 - 10 Dec 2021
|
||||||
|
|
||||||
- Update default CodeQL bundle version to 2.7.3. [#842](https://github.com/github/codeql-action/pull/842)
|
- Update default CodeQL bundle version to 2.7.3. [#842](https://github.com/github/codeql-action/pull/842)
|
||||||
|
|||||||
4
lib/analysis-paths.js
generated
4
lib/analysis-paths.js
generated
@@ -37,11 +37,11 @@ function buildIncludeExcludeEnvVar(paths) {
|
|||||||
return paths.join("\n");
|
return paths.join("\n");
|
||||||
}
|
}
|
||||||
function printPathFiltersWarning(config, logger) {
|
function printPathFiltersWarning(config, logger) {
|
||||||
// Index include/exclude/filters only work in javascript and python.
|
// Index include/exclude/filters only work in javascript/python/ruby.
|
||||||
// If any other languages are detected/configured then show a warning.
|
// If any other languages are detected/configured then show a warning.
|
||||||
if ((config.paths.length !== 0 || config.pathsIgnore.length !== 0) &&
|
if ((config.paths.length !== 0 || config.pathsIgnore.length !== 0) &&
|
||||||
!config.languages.every(isInterpretedLanguage)) {
|
!config.languages.every(isInterpretedLanguage)) {
|
||||||
logger.warning('The "paths"/"paths-ignore" fields of the config only have effect for JavaScript and Python');
|
logger.warning('The "paths"/"paths-ignore" fields of the config only have effect for JavaScript, Python, and Ruby');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.printPathFiltersWarning = printPathFiltersWarning;
|
exports.printPathFiltersWarning = printPathFiltersWarning;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"analysis-paths.js","sourceRoot":"","sources":["../src/analysis-paths.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"analysis-paths.js","sourceRoot":"","sources":["../src/analysis-paths.ts"],"names":[],"mappings":"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"}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-20211208"
|
"bundleVersion": "codeql-bundle-20220112"
|
||||||
}
|
}
|
||||||
|
|||||||
5
lib/fingerprints.js
generated
5
lib/fingerprints.js
generated
@@ -226,9 +226,8 @@ function resolveUriToFile(location, artifacts, sourceRoot, logger) {
|
|||||||
exports.resolveUriToFile = resolveUriToFile;
|
exports.resolveUriToFile = resolveUriToFile;
|
||||||
// Compute fingerprints for results in the given sarif file
|
// Compute fingerprints for results in the given sarif file
|
||||||
// and return an updated sarif file contents.
|
// and return an updated sarif file contents.
|
||||||
async function addFingerprints(sarifContents, sourceRoot, logger) {
|
async function addFingerprints(sarif, sourceRoot, logger) {
|
||||||
var _a, _b, _c;
|
var _a, _b, _c;
|
||||||
const sarif = JSON.parse(sarifContents);
|
|
||||||
// Gather together results for the same file and construct
|
// Gather together results for the same file and construct
|
||||||
// callbacks to accept hashes for that file and update the location
|
// callbacks to accept hashes for that file and update the location
|
||||||
const callbacksByFile = {};
|
const callbacksByFile = {};
|
||||||
@@ -266,7 +265,7 @@ async function addFingerprints(sarifContents, sourceRoot, logger) {
|
|||||||
};
|
};
|
||||||
await hash(teeCallback, filepath);
|
await hash(teeCallback, filepath);
|
||||||
}
|
}
|
||||||
return JSON.stringify(sarif);
|
return sarif;
|
||||||
}
|
}
|
||||||
exports.addFingerprints = addFingerprints;
|
exports.addFingerprints = addFingerprints;
|
||||||
//# sourceMappingURL=fingerprints.js.map
|
//# sourceMappingURL=fingerprints.js.map
|
||||||
File diff suppressed because one or more lines are too long
22
lib/fingerprints.test.js
generated
22
lib/fingerprints.test.js
generated
@@ -169,30 +169,24 @@ function testResolveUriToFile(uri, index, artifactsURIs) {
|
|||||||
});
|
});
|
||||||
(0, ava_1.default)("addFingerprints", async (t) => {
|
(0, ava_1.default)("addFingerprints", async (t) => {
|
||||||
// Run an end-to-end test on a test file
|
// Run an end-to-end test on a test file
|
||||||
let input = fs
|
const input = JSON.parse(fs
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.input.sarif`)
|
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.input.sarif`)
|
||||||
.toString();
|
.toString());
|
||||||
let expected = fs
|
const expected = JSON.parse(fs
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.expected.sarif`)
|
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.expected.sarif`)
|
||||||
.toString();
|
.toString());
|
||||||
// The test files are stored prettified, but addFingerprints outputs condensed JSON
|
|
||||||
input = JSON.stringify(JSON.parse(input));
|
|
||||||
expected = JSON.stringify(JSON.parse(expected));
|
|
||||||
// The URIs in the SARIF files resolve to files in the testdata directory
|
// The URIs in the SARIF files resolve to files in the testdata directory
|
||||||
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
||||||
t.deepEqual(await fingerprints.addFingerprints(input, sourceRoot, (0, logging_1.getRunnerLogger)(true)), expected);
|
t.deepEqual(await fingerprints.addFingerprints(input, sourceRoot, (0, logging_1.getRunnerLogger)(true)), expected);
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("missingRegions", async (t) => {
|
(0, ava_1.default)("missingRegions", async (t) => {
|
||||||
// Run an end-to-end test on a test file
|
// Run an end-to-end test on a test file
|
||||||
let input = fs
|
const input = JSON.parse(fs
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.input.sarif`)
|
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.input.sarif`)
|
||||||
.toString();
|
.toString());
|
||||||
let expected = fs
|
const expected = JSON.parse(fs
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.expected.sarif`)
|
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.expected.sarif`)
|
||||||
.toString();
|
.toString());
|
||||||
// The test files are stored prettified, but addFingerprints outputs condensed JSON
|
|
||||||
input = JSON.stringify(JSON.parse(input));
|
|
||||||
expected = JSON.stringify(JSON.parse(expected));
|
|
||||||
// The URIs in the SARIF files resolve to files in the testdata directory
|
// The URIs in the SARIF files resolve to files in the testdata directory
|
||||||
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
||||||
t.deepEqual(await fingerprints.addFingerprints(input, sourceRoot, (0, logging_1.getRunnerLogger)(true)), expected);
|
t.deepEqual(await fingerprints.addFingerprints(input, sourceRoot, (0, logging_1.getRunnerLogger)(true)), expected);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
70
lib/upload-lib.js
generated
70
lib/upload-lib.js
generated
@@ -54,25 +54,24 @@ function combineSarifFiles(sarifFiles) {
|
|||||||
}
|
}
|
||||||
combinedSarif.runs.push(...sarifObject.runs);
|
combinedSarif.runs.push(...sarifObject.runs);
|
||||||
}
|
}
|
||||||
return JSON.stringify(combinedSarif);
|
return combinedSarif;
|
||||||
}
|
}
|
||||||
exports.combineSarifFiles = combineSarifFiles;
|
exports.combineSarifFiles = combineSarifFiles;
|
||||||
// Populates the run.automationDetails.id field using the analysis_key and environment
|
// Populates the run.automationDetails.id field using the analysis_key and environment
|
||||||
// and return an updated sarif file contents.
|
// and return an updated sarif file contents.
|
||||||
function populateRunAutomationDetails(sarifContents, category, analysis_key, environment) {
|
function populateRunAutomationDetails(sarif, category, analysis_key, environment) {
|
||||||
if (analysis_key === undefined) {
|
|
||||||
return sarifContents;
|
|
||||||
}
|
|
||||||
const automationID = getAutomationID(category, analysis_key, environment);
|
const automationID = getAutomationID(category, analysis_key, environment);
|
||||||
const sarif = JSON.parse(sarifContents);
|
if (automationID !== undefined) {
|
||||||
for (const run of sarif.runs || []) {
|
for (const run of sarif.runs || []) {
|
||||||
if (run.automationDetails === undefined) {
|
if (run.automationDetails === undefined) {
|
||||||
run.automationDetails = {
|
run.automationDetails = {
|
||||||
id: automationID,
|
id: automationID,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return sarif;
|
||||||
}
|
}
|
||||||
return JSON.stringify(sarif);
|
return sarif;
|
||||||
}
|
}
|
||||||
exports.populateRunAutomationDetails = populateRunAutomationDetails;
|
exports.populateRunAutomationDetails = populateRunAutomationDetails;
|
||||||
function getAutomationID(category, analysis_key, environment) {
|
function getAutomationID(category, analysis_key, environment) {
|
||||||
@@ -83,7 +82,11 @@ function getAutomationID(category, analysis_key, environment) {
|
|||||||
}
|
}
|
||||||
return automationID;
|
return automationID;
|
||||||
}
|
}
|
||||||
return actionsUtil.computeAutomationID(analysis_key, environment);
|
// analysis_key is undefined for the runner.
|
||||||
|
if (analysis_key !== undefined) {
|
||||||
|
return actionsUtil.computeAutomationID(analysis_key, environment);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
// Upload the given payload.
|
// Upload the given payload.
|
||||||
// If the request fails then this will retry a small number of times.
|
// If the request fails then this will retry a small number of times.
|
||||||
@@ -244,17 +247,18 @@ exports.buildPayload = buildPayload;
|
|||||||
async function uploadFiles(sarifFiles, repositoryNwo, commitOid, ref, analysisKey, category, analysisName, workflowRunID, sourceRoot, environment, gitHubVersion, apiDetails, logger) {
|
async function uploadFiles(sarifFiles, repositoryNwo, commitOid, ref, analysisKey, category, analysisName, workflowRunID, sourceRoot, environment, gitHubVersion, apiDetails, logger) {
|
||||||
logger.startGroup("Uploading results");
|
logger.startGroup("Uploading results");
|
||||||
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
||||||
validateUniqueCategory(category);
|
|
||||||
// Validate that the files we were asked to upload are all valid SARIF files
|
// Validate that the files we were asked to upload are all valid SARIF files
|
||||||
for (const file of sarifFiles) {
|
for (const file of sarifFiles) {
|
||||||
validateSarifFileSchema(file, logger);
|
validateSarifFileSchema(file, logger);
|
||||||
}
|
}
|
||||||
let sarifPayload = combineSarifFiles(sarifFiles);
|
let sarif = combineSarifFiles(sarifFiles);
|
||||||
sarifPayload = await fingerprints.addFingerprints(sarifPayload, sourceRoot, logger);
|
sarif = await fingerprints.addFingerprints(sarif, sourceRoot, logger);
|
||||||
sarifPayload = populateRunAutomationDetails(sarifPayload, category, analysisKey, environment);
|
sarif = populateRunAutomationDetails(sarif, category, analysisKey, environment);
|
||||||
|
const toolNames = util.getToolNames(sarif);
|
||||||
|
validateUniqueCategory(sarif);
|
||||||
|
const sarifPayload = JSON.stringify(sarif);
|
||||||
const zippedSarif = zlib_1.default.gzipSync(sarifPayload).toString("base64");
|
const zippedSarif = zlib_1.default.gzipSync(sarifPayload).toString("base64");
|
||||||
const checkoutURI = (0, file_url_1.default)(sourceRoot);
|
const checkoutURI = (0, file_url_1.default)(sourceRoot);
|
||||||
const toolNames = util.getToolNames(sarifPayload);
|
|
||||||
const payload = buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, workflowRunID, checkoutURI, environment, toolNames, gitHubVersion);
|
const payload = buildPayload(commitOid, ref, analysisKey, analysisName, zippedSarif, workflowRunID, checkoutURI, environment, toolNames, gitHubVersion);
|
||||||
// Log some useful debug info about the info
|
// Log some useful debug info about the info
|
||||||
const rawUploadSizeBytes = sarifPayload.length;
|
const rawUploadSizeBytes = sarifPayload.length;
|
||||||
@@ -325,16 +329,28 @@ async function waitForProcessing(repositoryNwo, sarifID, apiDetails, logger) {
|
|||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
}
|
}
|
||||||
exports.waitForProcessing = waitForProcessing;
|
exports.waitForProcessing = waitForProcessing;
|
||||||
function validateUniqueCategory(category) {
|
function validateUniqueCategory(sarif) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
// This check only works on actions as env vars don't persist between calls to the runner
|
||||||
if (util.isActions()) {
|
if (util.isActions()) {
|
||||||
// This check only works on actions as env vars don't persist between calls to the runner
|
// duplicate categories are allowed in the same sarif file
|
||||||
const sentinelEnvVar = `CODEQL_UPLOAD_SARIF${category ? `_${sanitize(category)}` : ""}`;
|
// but not across multiple sarif files
|
||||||
if (process.env[sentinelEnvVar]) {
|
const categories = {};
|
||||||
throw new Error("Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per category. " +
|
for (const run of sarif.runs) {
|
||||||
"Please specify a unique `category` to call this action multiple times. " +
|
const id = (_a = run === null || run === void 0 ? void 0 : run.automationDetails) === null || _a === void 0 ? void 0 : _a.id;
|
||||||
`Category: ${category ? category : "(none)"}`);
|
const tool = (_c = (_b = run.tool) === null || _b === void 0 ? void 0 : _b.driver) === null || _c === void 0 ? void 0 : _c.name;
|
||||||
|
const category = `${sanitize(id)}_${sanitize(tool)}`;
|
||||||
|
categories[category] = { id, tool };
|
||||||
|
}
|
||||||
|
for (const [category, { id, tool }] of Object.entries(categories)) {
|
||||||
|
const sentinelEnvVar = `CODEQL_UPLOAD_SARIF_${category}`;
|
||||||
|
if (process.env[sentinelEnvVar]) {
|
||||||
|
throw new Error("Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per tool/category. " +
|
||||||
|
"The easiest fix is to specify a unique value for the `category` input. " +
|
||||||
|
`Category: (${id ? id : "none"}) Tool: (${tool ? tool : "none"})`);
|
||||||
|
}
|
||||||
|
core.exportVariable(sentinelEnvVar, sentinelEnvVar);
|
||||||
}
|
}
|
||||||
core.exportVariable(sentinelEnvVar, sentinelEnvVar);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.validateUniqueCategory = validateUniqueCategory;
|
exports.validateUniqueCategory = validateUniqueCategory;
|
||||||
@@ -348,6 +364,6 @@ exports.validateUniqueCategory = validateUniqueCategory;
|
|||||||
* @param str the initial value to sanitize
|
* @param str the initial value to sanitize
|
||||||
*/
|
*/
|
||||||
function sanitize(str) {
|
function sanitize(str) {
|
||||||
return str.replace(/[^a-zA-Z0-9_]/g, "_");
|
return (str !== null && str !== void 0 ? str : "_").replace(/[^a-zA-Z0-9_]/g, "_").toLocaleUpperCase();
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=upload-lib.js.map
|
//# sourceMappingURL=upload-lib.js.map
|
||||||
File diff suppressed because one or more lines are too long
110
lib/upload-lib.test.js
generated
110
lib/upload-lib.test.js
generated
@@ -98,9 +98,13 @@ ava_1.default.beforeEach(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("populateRunAutomationDetails", (t) => {
|
(0, ava_1.default)("populateRunAutomationDetails", (t) => {
|
||||||
let sarif = '{"runs": [{}]}';
|
let sarif = {
|
||||||
|
runs: [{}],
|
||||||
|
};
|
||||||
const analysisKey = ".github/workflows/codeql-analysis.yml:analyze";
|
const analysisKey = ".github/workflows/codeql-analysis.yml:analyze";
|
||||||
let expectedSarif = '{"runs":[{"automationDetails":{"id":"language:javascript/os:linux/"}}]}';
|
let expectedSarif = {
|
||||||
|
runs: [{ automationDetails: { id: "language:javascript/os:linux/" } }],
|
||||||
|
};
|
||||||
// Category has priority over analysis_key/environment
|
// Category has priority over analysis_key/environment
|
||||||
let modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, "language:javascript/os:linux", analysisKey, '{"language": "other", "os": "other"}');
|
let modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, "language:javascript/os:linux", analysisKey, '{"language": "other", "os": "other"}');
|
||||||
t.deepEqual(modifiedSarif, expectedSarif);
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
@@ -108,25 +112,99 @@ ava_1.default.beforeEach(() => {
|
|||||||
modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, "language:javascript/os:linux/", analysisKey, "");
|
modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, "language:javascript/os:linux/", analysisKey, "");
|
||||||
t.deepEqual(modifiedSarif, expectedSarif);
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
// check that the automation details doesn't get overwritten
|
// check that the automation details doesn't get overwritten
|
||||||
sarif = '{"runs":[{"automationDetails":{"id":"my_id"}}]}';
|
sarif = { runs: [{ automationDetails: { id: "my_id" } }] };
|
||||||
expectedSarif = '{"runs":[{"automationDetails":{"id":"my_id"}}]}';
|
expectedSarif = { runs: [{ automationDetails: { id: "my_id" } }] };
|
||||||
|
modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, undefined, analysisKey, '{"os": "linux", "language": "javascript"}');
|
||||||
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
|
// check multiple runs
|
||||||
|
sarif = { runs: [{ automationDetails: { id: "my_id" } }, {}] };
|
||||||
|
expectedSarif = {
|
||||||
|
runs: [
|
||||||
|
{ automationDetails: { id: "my_id" } },
|
||||||
|
{
|
||||||
|
automationDetails: {
|
||||||
|
id: ".github/workflows/codeql-analysis.yml:analyze/language:javascript/os:linux/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, undefined, analysisKey, '{"os": "linux", "language": "javascript"}');
|
modifiedSarif = uploadLib.populateRunAutomationDetails(sarif, undefined, analysisKey, '{"os": "linux", "language": "javascript"}');
|
||||||
t.deepEqual(modifiedSarif, expectedSarif);
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("validateUniqueCategory", (t) => {
|
(0, ava_1.default)("validateUniqueCategory when empty", (t) => {
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory(undefined));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif()));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory(undefined));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif()));
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("abc"));
|
});
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc"));
|
(0, ava_1.default)("validateUniqueCategory for automation details id", (t) => {
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("def"));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc")));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("def"));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("AbC")));
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("def")));
|
||||||
// Our category sanitization is not perfect. Here are some examples
|
// Our category sanitization is not perfect. Here are some examples
|
||||||
// of where we see false clashes
|
// of where we see false clashes
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("abc/def"));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc/def")));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc@def"));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc@def")));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc_def"));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc_def")));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc def"));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc def")));
|
||||||
// this one is fine
|
// this one is fine
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("abc_ def"));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc_ def")));
|
||||||
});
|
});
|
||||||
|
(0, ava_1.default)("validateUniqueCategory for tool name", (t) => {
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "AbC")));
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "def")));
|
||||||
|
// Our category sanitization is not perfect. Here are some examples
|
||||||
|
// of where we see false clashes
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc/def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc@def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc_def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc def")));
|
||||||
|
// this one is fine
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc_ def")));
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("validateUniqueCategory for automation details id and tool name", (t) => {
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc", "abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc", "abc")));
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc_", "def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc_", "def")));
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("ghi", "_jkl")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("ghi", "_jkl")));
|
||||||
|
// Our category sanitization is not perfect. Here are some examples
|
||||||
|
// of where we see false clashes
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc", "_")));
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc", "def__")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc_def")));
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("mno_", "pqr")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("mno", "_pqr")));
|
||||||
|
});
|
||||||
|
(0, ava_1.default)("validateUniqueCategory for multiple runs", (t) => {
|
||||||
|
const sarif1 = createMockSarif("abc", "def");
|
||||||
|
const sarif2 = createMockSarif("ghi", "jkl");
|
||||||
|
// duplicate categories are allowed within the same sarif file
|
||||||
|
const multiSarif = { runs: [sarif1.runs[0], sarif1.runs[0], sarif2.runs[0]] };
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(multiSarif));
|
||||||
|
// should throw if there are duplicate categories in separate validations
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(sarif1));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(sarif2));
|
||||||
|
});
|
||||||
|
function createMockSarif(id, tool) {
|
||||||
|
return {
|
||||||
|
runs: [
|
||||||
|
{
|
||||||
|
automationDetails: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
tool: {
|
||||||
|
driver: {
|
||||||
|
name: tool,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
//# sourceMappingURL=upload-lib.test.js.map
|
//# sourceMappingURL=upload-lib.test.js.map
|
||||||
File diff suppressed because one or more lines are too long
3
lib/util.js
generated
3
lib/util.js
generated
@@ -72,8 +72,7 @@ exports.getExtraOptionsEnvParam = getExtraOptionsEnvParam;
|
|||||||
*
|
*
|
||||||
* Returns an array of unique string tool names.
|
* Returns an array of unique string tool names.
|
||||||
*/
|
*/
|
||||||
function getToolNames(sarifContents) {
|
function getToolNames(sarif) {
|
||||||
const sarif = JSON.parse(sarifContents);
|
|
||||||
const toolNames = {};
|
const toolNames = {};
|
||||||
for (const run of sarif.runs || []) {
|
for (const run of sarif.runs || []) {
|
||||||
const tool = run.tool || {};
|
const tool = run.tool || {};
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
2
lib/util.test.js
generated
2
lib/util.test.js
generated
@@ -35,7 +35,7 @@ const util = __importStar(require("./util"));
|
|||||||
(0, testing_utils_1.setupTests)(ava_1.default);
|
(0, testing_utils_1.setupTests)(ava_1.default);
|
||||||
(0, ava_1.default)("getToolNames", (t) => {
|
(0, ava_1.default)("getToolNames", (t) => {
|
||||||
const input = fs.readFileSync(`${__dirname}/../src/testdata/tool-names.sarif`, "utf8");
|
const input = fs.readFileSync(`${__dirname}/../src/testdata/tool-names.sarif`, "utf8");
|
||||||
const toolNames = util.getToolNames(input);
|
const toolNames = util.getToolNames(JSON.parse(input));
|
||||||
t.deepEqual(toolNames, ["CodeQL command-line toolchain", "ESLint"]);
|
t.deepEqual(toolNames, ["CodeQL command-line toolchain", "ESLint"]);
|
||||||
});
|
});
|
||||||
(0, ava_1.default)("getMemoryFlag() should return the correct --ram flag", (t) => {
|
(0, ava_1.default)("getMemoryFlag() should return the correct --ram flag", (t) => {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
2
node_modules/.package-lock.json
generated
vendored
2
node_modules/.package-lock.json
generated
vendored
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "^0.5.2",
|
"@actions/artifact": "^0.5.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "CodeQL action",
|
"description": "CodeQL action",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
2
runner/package-lock.json
generated
2
runner/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql-runner",
|
"name": "codeql-runner",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql-runner",
|
"name": "codeql-runner",
|
||||||
"version": "1.0.27",
|
"version": "1.0.29",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "CodeQL runner",
|
"description": "CodeQL runner",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ export function printPathFiltersWarning(
|
|||||||
config: configUtils.Config,
|
config: configUtils.Config,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
) {
|
) {
|
||||||
// Index include/exclude/filters only work in javascript and python.
|
// Index include/exclude/filters only work in javascript/python/ruby.
|
||||||
// If any other languages are detected/configured then show a warning.
|
// If any other languages are detected/configured then show a warning.
|
||||||
if (
|
if (
|
||||||
(config.paths.length !== 0 || config.pathsIgnore.length !== 0) &&
|
(config.paths.length !== 0 || config.pathsIgnore.length !== 0) &&
|
||||||
!config.languages.every(isInterpretedLanguage)
|
!config.languages.every(isInterpretedLanguage)
|
||||||
) {
|
) {
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'The "paths"/"paths-ignore" fields of the config only have effect for JavaScript and Python'
|
'The "paths"/"paths-ignore" fields of the config only have effect for JavaScript, Python, and Ruby'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"bundleVersion": "codeql-bundle-20211208"
|
"bundleVersion": "codeql-bundle-20220112"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,16 +189,18 @@ test("resolveUriToFile", (t) => {
|
|||||||
|
|
||||||
test("addFingerprints", async (t) => {
|
test("addFingerprints", async (t) => {
|
||||||
// Run an end-to-end test on a test file
|
// Run an end-to-end test on a test file
|
||||||
let input = fs
|
const input = JSON.parse(
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.input.sarif`)
|
fs
|
||||||
.toString();
|
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.input.sarif`)
|
||||||
let expected = fs
|
.toString()
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting.expected.sarif`)
|
);
|
||||||
.toString();
|
const expected = JSON.parse(
|
||||||
|
fs
|
||||||
// The test files are stored prettified, but addFingerprints outputs condensed JSON
|
.readFileSync(
|
||||||
input = JSON.stringify(JSON.parse(input));
|
`${__dirname}/../src/testdata/fingerprinting.expected.sarif`
|
||||||
expected = JSON.stringify(JSON.parse(expected));
|
)
|
||||||
|
.toString()
|
||||||
|
);
|
||||||
|
|
||||||
// The URIs in the SARIF files resolve to files in the testdata directory
|
// The URIs in the SARIF files resolve to files in the testdata directory
|
||||||
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
||||||
@@ -215,16 +217,18 @@ test("addFingerprints", async (t) => {
|
|||||||
|
|
||||||
test("missingRegions", async (t) => {
|
test("missingRegions", async (t) => {
|
||||||
// Run an end-to-end test on a test file
|
// Run an end-to-end test on a test file
|
||||||
let input = fs
|
const input = JSON.parse(
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.input.sarif`)
|
fs
|
||||||
.toString();
|
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.input.sarif`)
|
||||||
let expected = fs
|
.toString()
|
||||||
.readFileSync(`${__dirname}/../src/testdata/fingerprinting2.expected.sarif`)
|
);
|
||||||
.toString();
|
const expected = JSON.parse(
|
||||||
|
fs
|
||||||
// The test files are stored prettified, but addFingerprints outputs condensed JSON
|
.readFileSync(
|
||||||
input = JSON.stringify(JSON.parse(input));
|
`${__dirname}/../src/testdata/fingerprinting2.expected.sarif`
|
||||||
expected = JSON.stringify(JSON.parse(expected));
|
)
|
||||||
|
.toString()
|
||||||
|
);
|
||||||
|
|
||||||
// The URIs in the SARIF files resolve to files in the testdata directory
|
// The URIs in the SARIF files resolve to files in the testdata directory
|
||||||
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
const sourceRoot = path.normalize(`${__dirname}/../src/testdata`);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as fs from "fs";
|
|||||||
import Long from "long";
|
import Long from "long";
|
||||||
|
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
|
import { SarifFile, SarifResult } from "./util";
|
||||||
|
|
||||||
const tab = "\t".charCodeAt(0);
|
const tab = "\t".charCodeAt(0);
|
||||||
const space = " ".charCodeAt(0);
|
const space = " ".charCodeAt(0);
|
||||||
@@ -135,7 +136,7 @@ export async function hash(callback: hashCallback, filepath: string) {
|
|||||||
// Generate a hash callback function that updates the given result in-place
|
// Generate a hash callback function that updates the given result in-place
|
||||||
// when it receives a hash for the correct line number. Ignores hashes for other lines.
|
// when it receives a hash for the correct line number. Ignores hashes for other lines.
|
||||||
function locationUpdateCallback(
|
function locationUpdateCallback(
|
||||||
result: any,
|
result: SarifResult,
|
||||||
location: any,
|
location: any,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): hashCallback {
|
): hashCallback {
|
||||||
@@ -246,12 +247,10 @@ export function resolveUriToFile(
|
|||||||
// Compute fingerprints for results in the given sarif file
|
// Compute fingerprints for results in the given sarif file
|
||||||
// and return an updated sarif file contents.
|
// and return an updated sarif file contents.
|
||||||
export async function addFingerprints(
|
export async function addFingerprints(
|
||||||
sarifContents: string,
|
sarif: SarifFile,
|
||||||
sourceRoot: string,
|
sourceRoot: string,
|
||||||
logger: Logger
|
logger: Logger
|
||||||
): Promise<string> {
|
): Promise<SarifFile> {
|
||||||
const sarif = JSON.parse(sarifContents);
|
|
||||||
|
|
||||||
// Gather together results for the same file and construct
|
// Gather together results for the same file and construct
|
||||||
// callbacks to accept hashes for that file and update the location
|
// callbacks to accept hashes for that file and update the location
|
||||||
const callbacksByFile: { [filename: string]: hashCallback[] } = {};
|
const callbacksByFile: { [filename: string]: hashCallback[] } = {};
|
||||||
@@ -305,5 +304,5 @@ export async function addFingerprints(
|
|||||||
await hash(teeCallback, filepath);
|
await hash(teeCallback, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(sarif);
|
return sarif;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,11 +140,14 @@ test("finding SARIF files", async (t) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("populateRunAutomationDetails", (t) => {
|
test("populateRunAutomationDetails", (t) => {
|
||||||
let sarif = '{"runs": [{}]}';
|
let sarif = {
|
||||||
|
runs: [{}],
|
||||||
|
};
|
||||||
const analysisKey = ".github/workflows/codeql-analysis.yml:analyze";
|
const analysisKey = ".github/workflows/codeql-analysis.yml:analyze";
|
||||||
|
|
||||||
let expectedSarif =
|
let expectedSarif = {
|
||||||
'{"runs":[{"automationDetails":{"id":"language:javascript/os:linux/"}}]}';
|
runs: [{ automationDetails: { id: "language:javascript/os:linux/" } }],
|
||||||
|
};
|
||||||
|
|
||||||
// Category has priority over analysis_key/environment
|
// Category has priority over analysis_key/environment
|
||||||
let modifiedSarif = uploadLib.populateRunAutomationDetails(
|
let modifiedSarif = uploadLib.populateRunAutomationDetails(
|
||||||
@@ -165,8 +168,28 @@ test("populateRunAutomationDetails", (t) => {
|
|||||||
t.deepEqual(modifiedSarif, expectedSarif);
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
|
|
||||||
// check that the automation details doesn't get overwritten
|
// check that the automation details doesn't get overwritten
|
||||||
sarif = '{"runs":[{"automationDetails":{"id":"my_id"}}]}';
|
sarif = { runs: [{ automationDetails: { id: "my_id" } }] };
|
||||||
expectedSarif = '{"runs":[{"automationDetails":{"id":"my_id"}}]}';
|
expectedSarif = { runs: [{ automationDetails: { id: "my_id" } }] };
|
||||||
|
modifiedSarif = uploadLib.populateRunAutomationDetails(
|
||||||
|
sarif,
|
||||||
|
undefined,
|
||||||
|
analysisKey,
|
||||||
|
'{"os": "linux", "language": "javascript"}'
|
||||||
|
);
|
||||||
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
|
|
||||||
|
// check multiple runs
|
||||||
|
sarif = { runs: [{ automationDetails: { id: "my_id" } }, {}] };
|
||||||
|
expectedSarif = {
|
||||||
|
runs: [
|
||||||
|
{ automationDetails: { id: "my_id" } },
|
||||||
|
{
|
||||||
|
automationDetails: {
|
||||||
|
id: ".github/workflows/codeql-analysis.yml:analyze/language:javascript/os:linux/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
modifiedSarif = uploadLib.populateRunAutomationDetails(
|
modifiedSarif = uploadLib.populateRunAutomationDetails(
|
||||||
sarif,
|
sarif,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -176,23 +199,139 @@ test("populateRunAutomationDetails", (t) => {
|
|||||||
t.deepEqual(modifiedSarif, expectedSarif);
|
t.deepEqual(modifiedSarif, expectedSarif);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("validateUniqueCategory", (t) => {
|
test("validateUniqueCategory when empty", (t) => {
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory(undefined));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif()));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory(undefined));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif()));
|
||||||
|
});
|
||||||
|
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("abc"));
|
test("validateUniqueCategory for automation details id", (t) => {
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc"));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("AbC")));
|
||||||
|
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("def"));
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("def")));
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("def"));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("def")));
|
||||||
|
|
||||||
// Our category sanitization is not perfect. Here are some examples
|
// Our category sanitization is not perfect. Here are some examples
|
||||||
// of where we see false clashes
|
// of where we see false clashes
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("abc/def"));
|
t.notThrows(() =>
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc@def"));
|
uploadLib.validateUniqueCategory(createMockSarif("abc/def"))
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc_def"));
|
);
|
||||||
t.throws(() => uploadLib.validateUniqueCategory("abc def"));
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc@def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc_def")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc def")));
|
||||||
|
|
||||||
// this one is fine
|
// this one is fine
|
||||||
t.notThrows(() => uploadLib.validateUniqueCategory("abc_ def"));
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc_ def"))
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("validateUniqueCategory for tool name", (t) => {
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "AbC"))
|
||||||
|
);
|
||||||
|
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "def"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "def"))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Our category sanitization is not perfect. Here are some examples
|
||||||
|
// of where we see false clashes
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc/def"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc@def"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc_def"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif(undefined, "abc def"))
|
||||||
|
);
|
||||||
|
|
||||||
|
// this one is fine
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc_ def"))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("validateUniqueCategory for automation details id and tool name", (t) => {
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc", "abc"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc", "abc"))
|
||||||
|
);
|
||||||
|
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc_", "def"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc_", "def"))
|
||||||
|
);
|
||||||
|
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("ghi", "_jkl"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("ghi", "_jkl"))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Our category sanitization is not perfect. Here are some examples
|
||||||
|
// of where we see false clashes
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(createMockSarif("abc")));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc", "_")));
|
||||||
|
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("abc", "def__"))
|
||||||
|
);
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(createMockSarif("abc_def")));
|
||||||
|
|
||||||
|
t.notThrows(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("mno_", "pqr"))
|
||||||
|
);
|
||||||
|
t.throws(() =>
|
||||||
|
uploadLib.validateUniqueCategory(createMockSarif("mno", "_pqr"))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("validateUniqueCategory for multiple runs", (t) => {
|
||||||
|
const sarif1 = createMockSarif("abc", "def");
|
||||||
|
const sarif2 = createMockSarif("ghi", "jkl");
|
||||||
|
|
||||||
|
// duplicate categories are allowed within the same sarif file
|
||||||
|
const multiSarif = { runs: [sarif1.runs[0], sarif1.runs[0], sarif2.runs[0]] };
|
||||||
|
t.notThrows(() => uploadLib.validateUniqueCategory(multiSarif));
|
||||||
|
|
||||||
|
// should throw if there are duplicate categories in separate validations
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(sarif1));
|
||||||
|
t.throws(() => uploadLib.validateUniqueCategory(sarif2));
|
||||||
|
});
|
||||||
|
|
||||||
|
function createMockSarif(id?: string, tool?: string) {
|
||||||
|
return {
|
||||||
|
runs: [
|
||||||
|
{
|
||||||
|
automationDetails: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
tool: {
|
||||||
|
driver: {
|
||||||
|
name: tool,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,17 +14,20 @@ import { Logger } from "./logging";
|
|||||||
import { parseRepositoryNwo, RepositoryNwo } from "./repository";
|
import { parseRepositoryNwo, RepositoryNwo } from "./repository";
|
||||||
import * as sharedEnv from "./shared-environment";
|
import * as sharedEnv from "./shared-environment";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
import { SarifFile } from "./util";
|
||||||
|
|
||||||
// Takes a list of paths to sarif files and combines them together,
|
// Takes a list of paths to sarif files and combines them together,
|
||||||
// returning the contents of the combined sarif file.
|
// returning the contents of the combined sarif file.
|
||||||
export function combineSarifFiles(sarifFiles: string[]): string {
|
export function combineSarifFiles(sarifFiles: string[]): SarifFile {
|
||||||
const combinedSarif = {
|
const combinedSarif: SarifFile = {
|
||||||
version: null,
|
version: null,
|
||||||
runs: [] as any[],
|
runs: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const sarifFile of sarifFiles) {
|
for (const sarifFile of sarifFiles) {
|
||||||
const sarifObject = JSON.parse(fs.readFileSync(sarifFile, "utf8"));
|
const sarifObject = JSON.parse(
|
||||||
|
fs.readFileSync(sarifFile, "utf8")
|
||||||
|
) as SarifFile;
|
||||||
// Check SARIF version
|
// Check SARIF version
|
||||||
if (combinedSarif.version === null) {
|
if (combinedSarif.version === null) {
|
||||||
combinedSarif.version = sarifObject.version;
|
combinedSarif.version = sarifObject.version;
|
||||||
@@ -37,39 +40,37 @@ export function combineSarifFiles(sarifFiles: string[]): string {
|
|||||||
combinedSarif.runs.push(...sarifObject.runs);
|
combinedSarif.runs.push(...sarifObject.runs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(combinedSarif);
|
return combinedSarif;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populates the run.automationDetails.id field using the analysis_key and environment
|
// Populates the run.automationDetails.id field using the analysis_key and environment
|
||||||
// and return an updated sarif file contents.
|
// and return an updated sarif file contents.
|
||||||
export function populateRunAutomationDetails(
|
export function populateRunAutomationDetails(
|
||||||
sarifContents: string,
|
sarif: SarifFile,
|
||||||
category: string | undefined,
|
category: string | undefined,
|
||||||
analysis_key: string | undefined,
|
analysis_key: string | undefined,
|
||||||
environment: string | undefined
|
environment: string | undefined
|
||||||
): string {
|
): SarifFile {
|
||||||
if (analysis_key === undefined) {
|
|
||||||
return sarifContents;
|
|
||||||
}
|
|
||||||
const automationID = getAutomationID(category, analysis_key, environment);
|
const automationID = getAutomationID(category, analysis_key, environment);
|
||||||
|
|
||||||
const sarif = JSON.parse(sarifContents);
|
if (automationID !== undefined) {
|
||||||
for (const run of sarif.runs || []) {
|
for (const run of sarif.runs || []) {
|
||||||
if (run.automationDetails === undefined) {
|
if (run.automationDetails === undefined) {
|
||||||
run.automationDetails = {
|
run.automationDetails = {
|
||||||
id: automationID,
|
id: automationID,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return sarif;
|
||||||
}
|
}
|
||||||
|
return sarif;
|
||||||
return JSON.stringify(sarif);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAutomationID(
|
function getAutomationID(
|
||||||
category: string | undefined,
|
category: string | undefined,
|
||||||
analysis_key: string,
|
analysis_key: string | undefined,
|
||||||
environment: string | undefined
|
environment: string | undefined
|
||||||
): string {
|
): string | undefined {
|
||||||
if (category !== undefined) {
|
if (category !== undefined) {
|
||||||
let automationID = category;
|
let automationID = category;
|
||||||
if (!automationID.endsWith("/")) {
|
if (!automationID.endsWith("/")) {
|
||||||
@@ -78,7 +79,12 @@ function getAutomationID(
|
|||||||
return automationID;
|
return automationID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionsUtil.computeAutomationID(analysis_key, environment);
|
// analysis_key is undefined for the runner.
|
||||||
|
if (analysis_key !== undefined) {
|
||||||
|
return actionsUtil.computeAutomationID(analysis_key, environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload the given payload.
|
// Upload the given payload.
|
||||||
@@ -350,31 +356,28 @@ async function uploadFiles(
|
|||||||
logger.startGroup("Uploading results");
|
logger.startGroup("Uploading results");
|
||||||
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
|
||||||
|
|
||||||
validateUniqueCategory(category);
|
|
||||||
|
|
||||||
// Validate that the files we were asked to upload are all valid SARIF files
|
// Validate that the files we were asked to upload are all valid SARIF files
|
||||||
for (const file of sarifFiles) {
|
for (const file of sarifFiles) {
|
||||||
validateSarifFileSchema(file, logger);
|
validateSarifFileSchema(file, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sarifPayload = combineSarifFiles(sarifFiles);
|
let sarif = combineSarifFiles(sarifFiles);
|
||||||
sarifPayload = await fingerprints.addFingerprints(
|
sarif = await fingerprints.addFingerprints(sarif, sourceRoot, logger);
|
||||||
sarifPayload,
|
|
||||||
sourceRoot,
|
sarif = populateRunAutomationDetails(
|
||||||
logger
|
sarif,
|
||||||
);
|
|
||||||
sarifPayload = populateRunAutomationDetails(
|
|
||||||
sarifPayload,
|
|
||||||
category,
|
category,
|
||||||
analysisKey,
|
analysisKey,
|
||||||
environment
|
environment
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const toolNames = util.getToolNames(sarif);
|
||||||
|
|
||||||
|
validateUniqueCategory(sarif);
|
||||||
|
const sarifPayload = JSON.stringify(sarif);
|
||||||
const zippedSarif = zlib.gzipSync(sarifPayload).toString("base64");
|
const zippedSarif = zlib.gzipSync(sarifPayload).toString("base64");
|
||||||
const checkoutURI = fileUrl(sourceRoot);
|
const checkoutURI = fileUrl(sourceRoot);
|
||||||
|
|
||||||
const toolNames = util.getToolNames(sarifPayload);
|
|
||||||
|
|
||||||
const payload = buildPayload(
|
const payload = buildPayload(
|
||||||
commitOid,
|
commitOid,
|
||||||
ref,
|
ref,
|
||||||
@@ -479,20 +482,31 @@ export async function waitForProcessing(
|
|||||||
logger.endGroup();
|
logger.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateUniqueCategory(category: string | undefined) {
|
export function validateUniqueCategory(sarif: SarifFile): void {
|
||||||
|
// This check only works on actions as env vars don't persist between calls to the runner
|
||||||
if (util.isActions()) {
|
if (util.isActions()) {
|
||||||
// This check only works on actions as env vars don't persist between calls to the runner
|
// duplicate categories are allowed in the same sarif file
|
||||||
const sentinelEnvVar = `CODEQL_UPLOAD_SARIF${
|
// but not across multiple sarif files
|
||||||
category ? `_${sanitize(category)}` : ""
|
const categories = {} as Record<string, { id?: string; tool?: string }>;
|
||||||
}`;
|
|
||||||
if (process.env[sentinelEnvVar]) {
|
for (const run of sarif.runs) {
|
||||||
throw new Error(
|
const id = run?.automationDetails?.id;
|
||||||
"Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per category. " +
|
const tool = run.tool?.driver?.name;
|
||||||
"Please specify a unique `category` to call this action multiple times. " +
|
const category = `${sanitize(id)}_${sanitize(tool)}`;
|
||||||
`Category: ${category ? category : "(none)"}`
|
categories[category] = { id, tool };
|
||||||
);
|
}
|
||||||
|
|
||||||
|
for (const [category, { id, tool }] of Object.entries(categories)) {
|
||||||
|
const sentinelEnvVar = `CODEQL_UPLOAD_SARIF_${category}`;
|
||||||
|
if (process.env[sentinelEnvVar]) {
|
||||||
|
throw new Error(
|
||||||
|
"Aborting upload: only one run of the codeql/analyze or codeql/upload-sarif actions is allowed per job per tool/category. " +
|
||||||
|
"The easiest fix is to specify a unique value for the `category` input. " +
|
||||||
|
`Category: (${id ? id : "none"}) Tool: (${tool ? tool : "none"})`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
core.exportVariable(sentinelEnvVar, sentinelEnvVar);
|
||||||
}
|
}
|
||||||
core.exportVariable(sentinelEnvVar, sentinelEnvVar);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,6 +519,6 @@ export function validateUniqueCategory(category: string | undefined) {
|
|||||||
*
|
*
|
||||||
* @param str the initial value to sanitize
|
* @param str the initial value to sanitize
|
||||||
*/
|
*/
|
||||||
function sanitize(str: string) {
|
function sanitize(str?: string) {
|
||||||
return str.replace(/[^a-zA-Z0-9_]/g, "_");
|
return (str ?? "_").replace(/[^a-zA-Z0-9_]/g, "_").toLocaleUpperCase();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ test("getToolNames", (t) => {
|
|||||||
`${__dirname}/../src/testdata/tool-names.sarif`,
|
`${__dirname}/../src/testdata/tool-names.sarif`,
|
||||||
"utf8"
|
"utf8"
|
||||||
);
|
);
|
||||||
const toolNames = util.getToolNames(input);
|
const toolNames = util.getToolNames(JSON.parse(input));
|
||||||
t.deepEqual(toolNames, ["CodeQL command-line toolchain", "ESLint"]);
|
t.deepEqual(toolNames, ["CodeQL command-line toolchain", "ESLint"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
35
src/util.ts
35
src/util.ts
@@ -35,6 +35,38 @@ export const DEFAULT_DEBUG_ARTIFACT_NAME = "debug-artifacts";
|
|||||||
*/
|
*/
|
||||||
export const DEFAULT_DEBUG_DATABASE_NAME = "db";
|
export const DEFAULT_DEBUG_DATABASE_NAME = "db";
|
||||||
|
|
||||||
|
export interface SarifFile {
|
||||||
|
version?: string | null;
|
||||||
|
runs: Array<{
|
||||||
|
tool?: {
|
||||||
|
driver?: {
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
automationDetails?: {
|
||||||
|
id?: string;
|
||||||
|
};
|
||||||
|
artifacts?: string[];
|
||||||
|
results?: SarifResult[];
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SarifResult {
|
||||||
|
locations: Array<{
|
||||||
|
physicalLocation: {
|
||||||
|
artifactLocation: {
|
||||||
|
uri: string;
|
||||||
|
};
|
||||||
|
region?: {
|
||||||
|
startLine?: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
partialFingerprints: {
|
||||||
|
primaryLocationLineHash?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the extra options for the codeql commands.
|
* Get the extra options for the codeql commands.
|
||||||
*/
|
*/
|
||||||
@@ -59,8 +91,7 @@ export function getExtraOptionsEnvParam(): object {
|
|||||||
*
|
*
|
||||||
* Returns an array of unique string tool names.
|
* Returns an array of unique string tool names.
|
||||||
*/
|
*/
|
||||||
export function getToolNames(sarifContents: string): string[] {
|
export function getToolNames(sarif: SarifFile): string[] {
|
||||||
const sarif = JSON.parse(sarifContents);
|
|
||||||
const toolNames = {};
|
const toolNames = {};
|
||||||
|
|
||||||
for (const run of sarif.runs || []) {
|
for (const run of sarif.runs || []) {
|
||||||
|
|||||||
Reference in New Issue
Block a user