Skip to content

Commit

Permalink
feat: parse SARIF files into objects
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin-de-Jong committed Aug 2, 2023
1 parent f9482e6 commit 5e5b65f
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 7 deletions.
4 changes: 4 additions & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ License: CC0-1.0
Files: package*.json
Copyright: 2023 Kevin de Jong <monkaii@hotmail.com>
License: CC0-1.0

Files: test/fixtures/example.sarif
Copyright: 2023 Kevin de Jong <monkaii@hotmail.com>
License: MIT
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dev-build-deploy/sarif-it",
"version": "0.0.0",
"version": "0.1.0",
"description": "Static Analysis Results Interchange Format Builder Library",
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down
30 changes: 30 additions & 0 deletions src/sarif/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
*/

import * as sarif from "sarif";
import * as fs from "fs";
import { Run } from "./run";
import { ISarif } from "../interfaces";
import { Tool } from "./tool";
import { Result } from "./result";

/** Static Analysis Results Format (SARIF) Version 2.1.0 */
export class Log extends ISarif<sarif.Log> {
Expand All @@ -24,4 +27,31 @@ export class Log extends ISarif<sarif.Log> {
this._data.runs.push(run.properties());
return this;
}

/**
* Creates a new SARIF log object from a file
*
* @param filePath The path to the SARIF file
* @returns A new SARIF log object
*/
static fromFile(filePath: string): Log {
const data = JSON.parse(fs.readFileSync(filePath, { encoding: "utf-8" }));
const log = new Log();

if (Object.keys(data).includes("runs") && Array.isArray(data.runs)) {
for (const sarifRun of data.runs) {
const tool = new Tool(sarifRun.tool.driver.name, sarifRun.tool.driver);
const run = new Run(tool);
if (Object.keys(sarifRun).includes("results") && Array.isArray(sarifRun.results)) {
for (const result of sarifRun.results) {
const res = new Result(result.message, result);
run.addResult(res);
}
}
log.addRun(run);
}
}

return log;
}
}
133 changes: 133 additions & 0 deletions test/fixtures/example.sarif
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
{
"$schema": "http://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "reuse-me",
"version": "0",
"organization": "dev-build-deploy",
"informationUri": "https://github.com/dev-build-deploy/reuse-me#README.md",
"rules": [
{
"id": "FL001",
"name": "MissingCopyrightInformation",
"shortDescription": {
"text": "Each Covered File MUST have Copyright associated with it.",
"markdown": "Each Covered File **MUST** have **[Copright](https://reuse.software/faq/#what-is-copyright)** associated with it."
}
},
{
"id": "FL002",
"name": "MissingLicenseInformation",
"shortDescription": {
"text": "Each Covered File MUST have License Information associated with it.",
"markdown": "Each Covered File **MUST** have **[Licensing Information](https://reuse.software/faq/#what-is-license)** associated with it."
}
},
{
"id": "FL003",
"name": "IncorrectLicenseFormat",
"shortDescription": {
"text": "The SPDX License Identifier ({0}) MUST be LicenseRef-[letters, numbers, \".\", or \"-\"] as defined by the SPDX Specification",
"markdown": "The SPDX License Identifier ({0}) **MUST** be `LicenseRef-`[`letters`, `numbers`, `.`, or `-`] as defined by the [SPDX Specification](https://spdx.github.io/spdx-spec/v2.3/)"
}
},
{
"id": "PR001",
"name": "MissingLicenseFile",
"shortDescription": {
"text": "The Project MUST include a License File for every license, but is missing {0}.",
"markdown": "The Project **MUST** include a License File for every license, but is missing `${license}`."
}
},
{
"id": "PR002",
"name": "IncorrectLicenseFile",
"shortDescription": {
"text": "The Project MUST NOT include License Files ({0}) for licenses under which none of the files in the Project are licensed.",
"markdown": "The Project **MUST NOT** include License Files (`{0}`) for licenses under which none of the files in the Project are licensed."
}
},
{
"id": "PR003",
"name": "DuplicateSpdxIdentifiers",
"shortDescription": {
"text": "The Project MUST NOT include duplicate SPDX identifiers ({0}).",
"markdown": "The Project **MUST NOT** include duplicate SPDX identifiers (`{0}`)."
}
}
]
}
},
"results": [
{
"message": {
"text": "The Project MUST include a License File for every license, but is missing MIT."
},
"level": "error",
"ruleId": "MissingLicense",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "reuse-me"
}
}
}
],
"occurrenceCount": 1
},
{
"message": {
"text": "Each Covered File MUST have Copyright associated with it."
},
"level": "error",
"ruleId": "MissingCopyrightInformation",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "./test.sarif"
}
}
},
{
"physicalLocation": {
"artifactLocation": {
"uri": "./src/config/tool.json"
}
}
}
],
"occurrenceCount": 2
},
{
"message": {
"text": "Each Covered File MUST have License Information associated with it."
},
"level": "error",
"ruleId": "MissingLicenseInformation",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "./test.sarif"
}
}
},
{
"physicalLocation": {
"artifactLocation": {
"uri": "./src/config/tool.json"
}
}
}
],
"occurrenceCount": 2
}
]
}
]
}
24 changes: 20 additions & 4 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import * as sarif from "../src";
import * as fs from "fs";

describe("Log", () => {
test("Default", () => {
Expand Down Expand Up @@ -50,7 +51,17 @@ describe("Log", () => {

test("Get Missing Property", () => {
const log = new sarif.Log();
expect(() => { log.get("does-not-exist") }).toThrowError("Property 'does-not-exist' does not exist.");
expect(() => {
log.get("does-not-exist");
}).toThrowError("Property 'does-not-exist' does not exist.");
});

test("From File", () => {
const log = sarif.Log.fromFile("test/fixtures/example.sarif");
expect(log).toBeInstanceOf(sarif.Log);
expect(log.properties()).toStrictEqual(
JSON.parse(fs.readFileSync("test/fixtures/example.sarif", { encoding: "utf-8" }))
);
});
});

Expand Down Expand Up @@ -349,7 +360,10 @@ describe("Tool", () => {

test("Add Rules", () => {
const tool = new sarif.Tool("sarif-it-test");
tool.addRule(new sarif.Rule("test-rule-a")).addRule(new sarif.Rule("test-rule-b")).addRule(new sarif.Rule("test-rule-a"));
tool
.addRule(new sarif.Rule("test-rule-a"))
.addRule(new sarif.Rule("test-rule-b"))
.addRule(new sarif.Rule("test-rule-a"));
expect(tool).toBeInstanceOf(sarif.Tool);
expect(tool.properties()).toStrictEqual({
driver: {
Expand All @@ -362,7 +376,7 @@ describe("Tool", () => {
id: "test-rule-a",
},
],
}
},
});
});

Expand All @@ -373,6 +387,8 @@ describe("Tool", () => {

test("Get Missing Property", () => {
const tool = new sarif.Tool("sarif-it-test");
expect(() => { tool.get("version") }).toThrowError("Property 'version' does not exist.");
expect(() => {
tool.get("version");
}).toThrowError("Property 'version' does not exist.");
});
});

0 comments on commit 5e5b65f

Please sign in to comment.