From f140be656aaaa66dcc77ed06f39263ea9d0bd117 Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Wed, 24 Jan 2024 19:58:40 +0100 Subject: [PATCH] SCP-65 SBOM Ingestion --- .github/workflows/test-action.yml | 2 + action.yml | 17 +++++- dist/index.js | 93 ++++++++++++++++++++++++++++--- scanoss-ignore.json | 7 +++ src/input.ts | 37 ++++++++++++ src/main.ts | 7 +-- vue.js | 56 +++++++++++++++++++ 7 files changed, 203 insertions(+), 16 deletions(-) create mode 100644 scanoss-ignore.json create mode 100644 src/input.ts create mode 100644 vue.js diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index 9d80735..1e6eed7 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -22,6 +22,8 @@ jobs: - name: Test Local Action id: test-action uses: ./ + with: + sbom-ignore: './scanoss-ignore.json' - name: Print output command run: echo "${{ steps.test-action.outputs.output-command }}" diff --git a/action.yml b/action.yml index d814f74..b9ab321 100644 --- a/action.yml +++ b/action.yml @@ -9,8 +9,21 @@ branding: # Define your inputs here. inputs: - scanner-parameters: - description: 'Parameters to run a scan' + output-path: + description: 'Output result file name' + required: false + default: 'result.json' + sbom-identify: + description: 'Scan and identify components in SBOM file' + required: false + sbom-ignore: + description: 'Ignore components specified in the SBOM file' + required: false + api-key: + description: 'SCANOSS API Key token (optional - not required for default OSSKB URL)' + required: false + api-url: + description: 'SCANOSS API URL (optional - default: https://osskb.org/api/scan/direct)' required: false # Define your outputs here. diff --git a/dist/index.js b/dist/index.js index aff839a..54630f6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3951,6 +3951,66 @@ function version(uuid) { var _default = version; exports["default"] = _default; +/***/ }), + +/***/ 747: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.commandBuilder = exports.readInputs = void 0; +const core = __importStar(__nccwpck_require__(186)); +function readInputs() { + return { + repoDir: process.env.GITHUB_WORKSPACE, + outputPath: core.getInput('output-path'), + sbomIdentify: core.getInput('sbom-identify'), + sbomIgnore: core.getInput('sbom-ignore'), + apiKey: core.getInput('api-key'), + apiUrl: core.getInput('api-url') + }; +} +exports.readInputs = readInputs; +function commandBuilder() { + const ap = readInputs(); + console.log(ap); + // prettier-ignore + const command = `docker run -v "${ap.repoDir}":"/scanoss" ghcr.io/scanoss/scanoss-py:v1.9.0 scan . ` + + `--output ${ap.outputPath} ` + + (ap.sbomIdentify ? `--identify ${ap.sbomIdentify} ` : '') + + (ap.sbomIgnore ? `--ignore ${ap.sbomIgnore} ` : '') + + (ap.apiUrl ? `--apiurl ${ap.apiUrl} ` : '') + + (ap.apiKey ? `--key ${ap.apiKey} ` : ''); + console.log(command); + return command; +} +exports.commandBuilder = commandBuilder; + + /***/ }), /***/ 399: @@ -3986,6 +4046,7 @@ exports.run = void 0; const core = __importStar(__nccwpck_require__(186)); const exec = __importStar(__nccwpck_require__(514)); const result_service_1 = __nccwpck_require__(414); +const input_1 = __nccwpck_require__(747); /** * The main function for the action. * @returns {Promise} Resolves when the action is complete. @@ -4006,7 +4067,7 @@ async function run() { }; options.silent = true; // run scan - await exec.exec(`docker run -v "${repoDir}":"/scanoss" ghcr.io/scanoss/scanoss-py:v1.9.0 scan . --output ${outputPath}`, [], options); + await exec.exec((0, input_1.commandBuilder)(), [], options); const scannerResults = await (0, result_service_1.readResult)(outputPath); const licenses = (0, result_service_1.getLicenses)(scannerResults); core.setOutput('licenses', licenses.toString()); @@ -4081,25 +4142,39 @@ async function readResult(filepath) { } exports.readResult = readResult; function getLicenses(results) { - const licenses = new Set(); + const licenses = new Array(); for (const component of Object.values(results)) { for (const c of component) { + if (c.id === result_interfaces_1.ComponentID.FILE || c.id === result_interfaces_1.ComponentID.SNIPPET) { + for (const l of c.licenses) { + licenses.push({ + spdxid: l.name, + copyleft: !l.copyleft ? null : l.copyleft === 'yes' ? true : false, + url: l?.url ? l.url : null + }); + } + } if (c.id === result_interfaces_1.ComponentID.DEPENDENCY) { const dependencies = c.dependencies; for (const d of dependencies) { for (const l of d.licenses) { - licenses.add(l.spdx_id); + if (!l.spdx_id) + continue; + licenses.push({ spdxid: l.spdx_id, copyleft: null, url: null }); } } } - if (c.id === result_interfaces_1.ComponentID.FILE || c.id === result_interfaces_1.ComponentID.SNIPPET) { - for (const l of c.licenses) { - licenses.add(l.name); - } - } } } - return Array.from(licenses); + const seenSpdxIds = new Set(); + const uniqueLicenses = licenses.filter(license => { + if (!seenSpdxIds.has(license.spdxid)) { + seenSpdxIds.add(license.spdxid); + return true; + } + return false; + }); + return uniqueLicenses; } exports.getLicenses = getLicenses; diff --git a/scanoss-ignore.json b/scanoss-ignore.json new file mode 100644 index 0000000..9edc209 --- /dev/null +++ b/scanoss-ignore.json @@ -0,0 +1,7 @@ +{ + "components": [ + { + "purl": "pkg:github/zhang14725804/notebook" + } + ] +} diff --git a/src/input.ts b/src/input.ts new file mode 100644 index 0000000..d19cd38 --- /dev/null +++ b/src/input.ts @@ -0,0 +1,37 @@ +import * as core from '@actions/core' + +export interface ActionParameters { + repoDir: string + outputPath: string + sbomIdentify: string + sbomIgnore: string + apiKey: string + apiUrl: string +} + +export function readInputs(): ActionParameters { + return { + repoDir: process.env.GITHUB_WORKSPACE as string, + outputPath: core.getInput('output-path'), + sbomIdentify: core.getInput('sbom-identify'), + sbomIgnore: core.getInput('sbom-ignore'), + apiKey: core.getInput('api-key'), + apiUrl: core.getInput('api-url') + } +} + +export function commandBuilder(): string { + const ap = readInputs() + console.log(ap) + // prettier-ignore + const command = + `docker run -v "${ap.repoDir}":"/scanoss" ghcr.io/scanoss/scanoss-py:v1.9.0 scan . ` + + `--output ${ap.outputPath} ` + + (ap.sbomIdentify ? `--identify ${ap.sbomIdentify} ` : '') + + (ap.sbomIgnore ? `--ignore ${ap.sbomIgnore} ` : '') + + (ap.apiUrl ? `--apiurl ${ap.apiUrl} ` : '') + + (ap.apiKey ? `--key ${ap.apiKey} ` : '') + + console.log(command) + return command +} diff --git a/src/main.ts b/src/main.ts index cf78508..9c771eb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import * as core from '@actions/core' import * as exec from '@actions/exec' import { getLicenses, readResult } from './services/result.service' +import { commandBuilder } from './input' /** * The main function for the action. @@ -24,11 +25,7 @@ export async function run(): Promise { options.silent = true // run scan - await exec.exec( - `docker run -v "${repoDir}":"/scanoss" ghcr.io/scanoss/scanoss-py:v1.9.0 scan . --output ${outputPath}`, - [], - options - ) + await exec.exec(commandBuilder(), [], options) const scannerResults = await readResult(outputPath) const licenses = getLicenses(scannerResults) diff --git a/vue.js b/vue.js new file mode 100644 index 0000000..f4443c5 --- /dev/null +++ b/vue.js @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file