Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: SP-1343 Add configurable Copyleft license options to pipeline #68

Merged
merged 3 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,20 @@ For example workflow runs, check out our

### Action Input Parameters

| **Parameter** | **Description** | **Required** | **Default** |
|--------------------------|------------------------------------------------------------------------------------|--------------|-------------------------------------|
| output.filepath | Scan output file name. | Optional | `results.json` |
| sbom.enabled | Enable or disable scanning based on the SBOM file | Optional | `true` |
| sbom.filepath | Filepath of the SBOM file to be used for scanning | Optional | `sbom.json` |
| sbom.type | Type of SBOM operation: either 'identify' or 'ignore | Optional | `identify` |
| dependencies.enabled | Option to enable or disable scanning of dependencies. | Optional | `false` |
| policies | List of policies separated by commas, options available are: copyleft, undeclared. | Optional | - |
| policies.halt_on_failure | Halt check on policy failure. If set to false checks will not fail. | Optional | `true` |
| api.url | SCANOSS API URL | Optional | `https://osskb.org/api/scan/direct` |
| api.key | SCANOSS API Key | Optional | - |
| **Parameter** | **Description** | **Required** | **Default** |
|----------------------------|------------------------------------------------------------------------------------------------------|--------------|-------------------------------------|
| output.filepath | Scan output file name. | Optional | `results.json` |
| sbom.enabled | Enable or disable scanning based on the SBOM file | Optional | `true` |
| sbom.filepath | Filepath of the SBOM file to be used for scanning | Optional | `sbom.json` |
| sbom.type | Type of SBOM operation: either 'identify' or 'ignore | Optional | `identify` |
| dependencies.enabled | Option to enable or disable scanning of dependencies. | Optional | `false` |
| policies | List of policies separated by commas, options available are: copyleft, undeclared. | Optional | - |
| policies.halt_on_failure | Halt check on policy failure. If set to false checks will not fail. | Optional | `true` |
| api.url | SCANOSS API URL | Optional | `https://osskb.org/api/scan/direct` |
| api.key | SCANOSS API Key | Optional | - |
| licenses.copyleft.include | List of Copyleft licenses to append to the default list. Provide licenses as a comma-separated list. | Optional | - |
| licenses.copyleft.exclude | List of Copyleft licenses to remove from default list. Provide licenses as a comma-separated list. | Optional | - |
| licenses.copyleft.explicit | Explicit list of Copyleft licenses to consider. Provide licenses as a comma-separated list. | Optional | - |

### Action Output Parameters

Expand All @@ -78,7 +81,7 @@ the output into your custom workflow
The SCANOSS Code Scan Action includes two configurable policies:

1. Copyleft: This policy checks if any component or code snippet is associated with a copyleft license. If such a
license is detected, the pull request (PR) is rejected.
license is detected, the pull request (PR) is rejected. The default list of Copyleft licenses is defined in the following [file](https://github.com/scanoss/gha-code-scan/blob/main/src/utils/license.utils.ts).

2. Undeclared: This policy compares the components detected in the repository against those declared in an sbom.json
file (customizable through the sbom.filepath parameter). If there are undeclared components, the PR is rejected.
Expand Down
9 changes: 9 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ inputs:
description: 'Your GitHub token'
required: false
default: ${{ github.token }}
licenses.copyleft.include:
description: 'List of Copyleft licenses to append to the default list. Provide licenses as a comma-separated list.'
required: false
licenses.copyleft.exclude:
description: 'List of Copyleft licenses to remove from default list. Provide licenses as a comma-separated list.'
required: false
licenses.copyleft.explicit:
description: 'Explicit list of Copyleft licenses to consider. Provide licenses as a comma-separated list.'
required: false

outputs:
result-filepath:
Expand Down
67 changes: 57 additions & 10 deletions dist/index.js

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

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,7 +1,7 @@
{
"name": "scanoss-code-scan-action",
"description": "SCANOSS Code Scan Action",
"version": "0.1.7",
"version": "0.2.0",
"author": "SCANOSS",
"private": true,
"homepage": "https://github.com/scanoss/code-scan-action/",
Expand Down
3 changes: 3 additions & 0 deletions src/app.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ export const API_KEY = core.getInput('api.key');
export const API_URL = core.getInput('api.url');
export const OUTPUT_FILEPATH = core.getInput('output.filepath');
export const GITHUB_TOKEN = core.getInput('github.token');
export const COPYLEFT_LICENSE_INCLUDE = core.getInput('licenses.copyleft.include');
export const COPYLEFT_LICENSE_EXCLUDE = core.getInput('licenses.copyleft.exclude');
export const COPYLEFT_LICENSE_EXPLICIT = core.getInput('licenses.copyleft.explicit');
export const REPO_DIR = process.env.GITHUB_WORKSPACE as string;
18 changes: 10 additions & 8 deletions src/policies/copyleft-policy-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,16 @@ export class CopyleftPolicyCheck extends PolicyCheck {

components.forEach(component => {
component.licenses.forEach(license => {
const copyleftIcon = licenseUtil.isCopyLeft(license.spdxid?.trim().toLowerCase()) ? 'YES' : 'NO';
rows.push([
component.purl,
component.version,
license.spdxid,
`${licenseUtil.getOSADL(license?.spdxid) || ''}`,
copyleftIcon
]);
if (licenseUtil.isCopyLeft(license.spdxid?.trim().toLowerCase())) {
const copyleftIcon = licenseUtil.isCopyLeft(license.spdxid?.trim().toLowerCase()) ? 'YES' : 'NO';
rows.push([
component.purl,
component.version,
license.spdxid,
`${licenseUtil.getOSADL(license?.spdxid) || ''}`,
copyleftIcon
]);
}
});
});
return `### Copyleft licenses \n ${generateTable(headers, rows, centeredColumns)}`;
Expand Down
23 changes: 23 additions & 0 deletions src/utils/license.utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import * as inputs from '../app.input';
import * as core from '@actions/core';

export class LicenseUtil {
private BASE_OSADL_URL = 'https://spdx.org/licenses';
private HTML = 'html';
Expand Down Expand Up @@ -34,7 +37,27 @@ export class LicenseUtil {
private copyLeftLicenses = new Set<string>();

private init(): void {
if (inputs.COPYLEFT_LICENSE_EXPLICIT) {
const explicitCopyleftLicenses = inputs.COPYLEFT_LICENSE_EXPLICIT.split(',').map(pn => pn.trim().toLowerCase());
core.debug(`Explicit licenses: ${explicitCopyleftLicenses}`);
this.copyLeftLicenses = new Set<string>(explicitCopyleftLicenses);
return;
}

core.debug(`Explicit licenses not defined, setting default licenses...`);
this.copyLeftLicenses = this.defaultCopyleftLicenses;

if (inputs.COPYLEFT_LICENSE_INCLUDE) {
const includedCopyleftLicenses = inputs.COPYLEFT_LICENSE_INCLUDE.split(',').map(pn => pn.trim());
core.debug(`Included copyleft licenses: ${includedCopyleftLicenses}`);
includedCopyleftLicenses.forEach(l => this.copyLeftLicenses.add(l.toLowerCase()));
}

if (inputs.COPYLEFT_LICENSE_EXCLUDE) {
const excludedCopyleftLicenses = inputs.COPYLEFT_LICENSE_EXCLUDE.split(',').map(pn => pn.trim());
core.debug(`Excluded copyleft licenses: ${excludedCopyleftLicenses}`);
excludedCopyleftLicenses.forEach(l => this.copyLeftLicenses.delete(l.toLowerCase()));
}
}

isCopyLeft(spdxid: string): boolean {
Expand Down
Loading