Merge branch 'main' into external-config

# Conflicts:
#	README.md
#	__tests__/config.test.ts
#	dist/index.js.map
#	src/config.ts
#	src/schemas.ts
This commit is contained in:
Federico Builes
2022-09-21 16:50:02 +02:00
14 changed files with 175 additions and 45 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ major version number (e.g. `v1`) in their workflows while
automatically getting all the automatically getting all the
minor/patch updates. minor/patch updates.
To do this just force-create a new annotated tag and push it: To do this just checkout `main`, force-create a new annotated tag, and push it:
``` ```
git tag -fa v2 -m "Updating v2 to 2.3.4" git tag -fa v2 -m "Updating v2 to 2.3.4"
git push origin v2 --force git push origin v2 --force
+26 -7
View File
@@ -38,7 +38,7 @@ jobs:
### GitHub Enterprise Server ### GitHub Enterprise Server
This action is available in GHES starting with version 3.6. Make sure This action is available in Enterprise Server starting with version 3.6. Make sure
[GitHub Advanced [GitHub Advanced
Security](https://docs.github.com/en/[email protected]/admin/code-security/managing-github-advanced-security-for-your-enterprise/enabling-github-advanced-security-for-your-enterprise) Security](https://docs.github.com/en/[email protected]/admin/code-security/managing-github-advanced-security-for-your-enterprise/enabling-github-advanced-security-for-your-enterprise)
and [GitHub and [GitHub
@@ -50,7 +50,6 @@ with the label of any of your runners (the default label
is `self-hosted`): is `self-hosted`):
```yaml ```yaml
# ... # ...
jobs: jobs:
@@ -88,6 +87,15 @@ Configure the severity level for alerting. See "[Vulnerability Severity](https:/
**Example**: `fail-on-severity: moderate`. **Example**: `fail-on-severity: moderate`.
#### fail-on-scopes
A list of strings representing the build environments you want to
support. The default value is `development, runtime`.
**Possible values**: `development`, `runtime`, `unknown`
**Example**: `fail-on-scopes: runtime # this excludes development dependency scanning`
#### allow-licenses #### allow-licenses
Only allow the licenses in this list. See "[Licenses](https://github.com/actions/dependency-review-action#licenses)". Only allow the licenses in this list. See "[Licenses](https://github.com/actions/dependency-review-action#licenses)".
@@ -204,12 +212,23 @@ This example will only fail on pull requests with `critical` and `high` vulnerab
fail-on-severity: high fail-on-severity: high
``` ```
### Dependency Scoping
By default the action will only fail on `runtime` dependencies that have vulnerabilities or unacceptable licenses, ignoring `development` dependencies. You can override this behavior with the `fail-on-scopes` option, which will allow you to list the specific dependency scopes you care about. The possible values are: `unknown`, `runtime`, and `development`. Note: Filtering by scope will not be supported on Enterprise Server just yet, as the REST API's introduction of `scope` will be released in an upcoming Enterprise Server version. We will treat all dependencies on Enterprise Server as having a `runtime` scope and thus will not be filtered away.
```yaml
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
fail-on-scopes: runtime, development
```
### Licenses ### Licenses
You can set the action to fail on pull requests based on the licenses of the dependencies You can set the action to fail on pull requests based on the licenses of the dependencies
they introduce. With `allow-licenses` you can define the list of licenses they introduce. With `allow-licenses` you can define the list of licenses
your repository will accept. Alternatively, you can use `deny-licenses` to only your repository will accept. Alternatively, you can use `deny-licenses` to only
forbid a subset of licenses. These options are not supported on GHES. forbid a subset of licenses. These options are not supported on Enterprise Server.
You can use the [Licenses You can use the [Licenses
API](https://docs.github.com/en/rest/licenses) to see the full list of API](https://docs.github.com/en/rest/licenses) to see the full list of
@@ -234,12 +253,12 @@ to filter. A couple of examples:
### Considerations ### Considerations
* Checking for licenses is not supported on GHES. - Checking for licenses is not supported on Enterprise Server.
* The action will only accept one of the two parameters; an error will - The action will only accept one of the two parameters; an error will
be raised if you provide both. be raised if you provide both.
* By default both parameters are empty (no license checking is - By default both parameters are empty (no license checking is
performed). performed).
* We don't have license information for all of your dependents. If we - We don't have license information for all of your dependents. If we
can't detect the license for a dependency **we will inform you, but the can't detect the license for a dependency **we will inform you, but the
action won't fail**. action won't fail**.
+22
View File
@@ -13,6 +13,7 @@ function setInput(input: string, value: string) {
function clearInputs() { function clearInputs() {
const allowedOptions = [ const allowedOptions = [
'FAIL-ON-SEVERITY', 'FAIL-ON-SEVERITY',
'FAIL-ON-SCOPES',
'ALLOW-LICENSES', 'ALLOW-LICENSES',
'DENY-LICENSES', 'DENY-LICENSES',
'CONFIG-FILE', 'CONFIG-FILE',
@@ -138,3 +139,24 @@ test('it raises an error when given an unknown severity in an external config fi
setInput('config-file', './__tests__/fixtures/invalid-severity-config.yml') setInput('config-file', './__tests__/fixtures/invalid-severity-config.yml')
expect(() => readConfig()).toThrow() expect(() => readConfig()).toThrow()
}) })
test('it defaults to runtime scope', async () => {
const options = readConfig()
expect(options.fail_on_scopes).toEqual(['runtime'])
})
test('it parses custom scopes preference', async () => {
setInput('fail-on-scopes', 'runtime, development')
let options = readConfig()
expect(options.fail_on_scopes).toEqual(['runtime', 'development'])
clearInputs()
setInput('fail-on-scopes', 'development')
options = readConfig()
expect(options.fail_on_scopes).toEqual(['development'])
})
test('it raises an error when given invalid scope', async () => {
setInput('fail-on-scopes', 'runtime, zombies')
expect(() => readConfig()).toThrow()
})
+16 -1
View File
@@ -1,6 +1,6 @@
import {expect, test} from '@jest/globals' import {expect, test} from '@jest/globals'
import {Change, Changes} from '../src/schemas' import {Change, Changes} from '../src/schemas'
import {filterChangesBySeverity} from '../src/filter' import {filterChangesBySeverity, filterChangesByScopes} from '../src/filter'
let npmChange: Change = { let npmChange: Change = {
manifest: 'package.json', manifest: 'package.json',
@@ -11,6 +11,7 @@ let npmChange: Change = {
package_url: 'pkg:npm/[email protected]', package_url: 'pkg:npm/[email protected]',
license: 'MIT', license: 'MIT',
source_repository_url: 'github.com/some-repo', source_repository_url: 'github.com/some-repo',
scope: 'runtime',
vulnerabilities: [ vulnerabilities: [
{ {
severity: 'critical', severity: 'critical',
@@ -30,6 +31,7 @@ let rubyChange: Change = {
package_url: 'pkg:gem/[email protected]', package_url: 'pkg:gem/[email protected]',
license: 'BSD', license: 'BSD',
source_repository_url: 'github.com/some-repo', source_repository_url: 'github.com/some-repo',
scope: 'development',
vulnerabilities: [ vulnerabilities: [
{ {
severity: 'moderate', severity: 'moderate',
@@ -57,3 +59,16 @@ test('it properly filters changes by severity', async () => {
result = filterChangesBySeverity('critical', changes) result = filterChangesBySeverity('critical', changes)
expect(changes).toEqual([npmChange, rubyChange]) expect(changes).toEqual([npmChange, rubyChange])
}) })
test('it properly filters changes by scope', async () => {
const changes = [npmChange, rubyChange]
let result = filterChangesByScopes(['runtime'], changes)
expect(result).toEqual([npmChange])
result = filterChangesByScopes(['development'], changes)
expect(result).toEqual([rubyChange])
result = filterChangesByScopes(['runtime', 'development'], changes)
expect(result).toEqual([npmChange, rubyChange])
})
+2
View File
@@ -11,6 +11,7 @@ let npmChange: Change = {
package_url: 'pkg:npm/[email protected]', package_url: 'pkg:npm/[email protected]',
license: 'MIT', license: 'MIT',
source_repository_url: 'github.com/some-repo', source_repository_url: 'github.com/some-repo',
scope: 'runtime',
vulnerabilities: [ vulnerabilities: [
{ {
severity: 'critical', severity: 'critical',
@@ -30,6 +31,7 @@ let rubyChange: Change = {
package_url: 'pkg:gem/[email protected]', package_url: 'pkg:gem/[email protected]',
license: 'BSD', license: 'BSD',
source_repository_url: 'github.com/some-repo', source_repository_url: 'github.com/some-repo',
scope: 'runtime',
vulnerabilities: [ vulnerabilities: [
{ {
severity: 'moderate', severity: 'moderate',
+4
View File
@@ -10,6 +10,10 @@ inputs:
description: Don't block PRs below this severity. Possible values are `low`, `moderate`, `high`, `critical`. description: Don't block PRs below this severity. Possible values are `low`, `moderate`, `high`, `critical`.
required: false required: false
default: 'low' default: 'low'
fail-on-scopes:
description: Dependency scopes to block PRs on. Comma-separated list. Possible values are 'unknown', 'runtime', and 'development' (e.g. "runtime, development")
required: false
default: 'runtime'
base-ref: base-ref:
description: The base git ref to be used for this check. Has a default value when the workflow event is `pull_request` or `pull_request_target`. Must be provided otherwise. description: The base git ref to be used for this check. Has a default value when the workflow event is `pull_request` or `pull_request_target`. Must be provided otherwise.
required: false required: false
Generated Vendored
+49 -19
View File
@@ -220,10 +220,12 @@ function run() {
allow: config.allow_licenses, allow: config.allow_licenses,
deny: config.deny_licenses deny: config.deny_licenses
}; };
const addedChanges = (0, filter_1.filterChangesBySeverity)(minSeverity, changes).filter(change => change.change_type === 'added' && const scopes = config.fail_on_scopes;
const scopedChanges = (0, filter_1.filterChangesByScopes)(scopes, changes);
const addedChanges = (0, filter_1.filterChangesBySeverity)(minSeverity, scopedChanges).filter(change => change.change_type === 'added' &&
change.vulnerabilities !== undefined && change.vulnerabilities !== undefined &&
change.vulnerabilities.length > 0); change.vulnerabilities.length > 0);
const [licenseErrors, unknownLicenses] = (0, licenses_1.getDeniedLicenseChanges)(changes, licenses); const [licenseErrors, unknownLicenses] = (0, licenses_1.getDeniedLicenseChanges)(scopedChanges, licenses);
summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses); summary.addSummaryToSummary(addedChanges, licenseErrors, unknownLicenses);
if (addedChanges.length > 0) { if (addedChanges.length > 0) {
for (const change of addedChanges) { for (const change of addedChanges) {
@@ -333,9 +335,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ChangesSchema = exports.ConfigurationOptionsSchema = exports.PullRequestSchema = exports.ChangeSchema = exports.SEVERITIES = void 0; exports.ChangesSchema = exports.ConfigurationOptionsSchema = exports.PullRequestSchema = exports.ChangeSchema = exports.SeveritySchema = exports.SCOPES = exports.SEVERITIES = void 0;
const z = __importStar(__nccwpck_require__(3301)); const z = __importStar(__nccwpck_require__(3301));
exports.SEVERITIES = ['critical', 'high', 'moderate', 'low']; exports.SEVERITIES = ['critical', 'high', 'moderate', 'low'];
exports.SCOPES = ['unknown', 'runtime', 'development'];
exports.SeveritySchema = z.enum(exports.SEVERITIES).default('low');
exports.ChangeSchema = z.object({ exports.ChangeSchema = z.object({
change_type: z.enum(['added', 'removed']), change_type: z.enum(['added', 'removed']),
manifest: z.string(), manifest: z.string(),
@@ -345,9 +349,10 @@ exports.ChangeSchema = z.object({
package_url: z.string(), package_url: z.string(),
license: z.string().nullable(), license: z.string().nullable(),
source_repository_url: z.string().nullable(), source_repository_url: z.string().nullable(),
scope: z.enum(exports.SCOPES).optional(),
vulnerabilities: z vulnerabilities: z
.array(z.object({ .array(z.object({
severity: z.enum(['critical', 'high', 'moderate', 'low']), severity: exports.SeveritySchema,
advisory_ghsa_id: z.string(), advisory_ghsa_id: z.string(),
advisory_summary: z.string(), advisory_summary: z.string(),
advisory_url: z.string() advisory_url: z.string()
@@ -362,7 +367,8 @@ exports.PullRequestSchema = z.object({
}); });
exports.ConfigurationOptionsSchema = z exports.ConfigurationOptionsSchema = z
.object({ .object({
fail_on_severity: z.enum(exports.SEVERITIES).default('low'), fail_on_severity: exports.SeveritySchema,
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).default([]), allow_licenses: z.array(z.string()).default([]),
deny_licenses: z.array(z.string()).default([]), deny_licenses: z.array(z.string()).default([]),
config_file: z.string().optional().default('false'), config_file: z.string().optional().default('false'),
@@ -14935,6 +14941,14 @@ function getOptionalInput(name) {
const value = core.getInput(name); const value = core.getInput(name);
return value.length > 0 ? value : undefined; return value.length > 0 ? value : undefined;
} }
function parseList(list) {
if (list === undefined) {
return list;
}
else {
return list.split(',').map(x => x.trim());
}
}
function readConfig() { function readConfig() {
const externalConfig = getOptionalInput('config-file'); const externalConfig = getOptionalInput('config-file');
if (externalConfig !== undefined) { if (externalConfig !== undefined) {
@@ -14948,10 +14962,11 @@ function readConfig() {
} }
exports.readConfig = readConfig; exports.readConfig = readConfig;
function readInlineConfig() { function readInlineConfig() {
const fail_on_severity = z const fail_on_severity = schemas_1.SeveritySchema.parse(getOptionalInput('fail-on-severity'));
.enum(schemas_1.SEVERITIES) const fail_on_scopes = z
.default('low') .array(z.enum(schemas_1.SCOPES))
.parse(getOptionalInput('fail-on-severity')); .default(['runtime'])
.parse(parseList(getOptionalInput('fail-on-scopes')));
const allow_licenses = getOptionalInput('allow-licenses'); const allow_licenses = getOptionalInput('allow-licenses');
const deny_licenses = getOptionalInput('deny-licenses'); const deny_licenses = getOptionalInput('deny-licenses');
if (allow_licenses !== undefined && deny_licenses !== undefined) { if (allow_licenses !== undefined && deny_licenses !== undefined) {
@@ -14961,8 +14976,9 @@ function readInlineConfig() {
const head_ref = getOptionalInput('head-ref'); const head_ref = getOptionalInput('head-ref');
return { return {
fail_on_severity, fail_on_severity,
allow_licenses: allow_licenses === null || allow_licenses === void 0 ? void 0 : allow_licenses.split(',').map(x => x.trim()), fail_on_scopes,
deny_licenses: deny_licenses === null || deny_licenses === void 0 ? void 0 : deny_licenses.split(',').map(x => x.trim()), allow_licenses: parseList(allow_licenses),
deny_licenses: parseList(deny_licenses),
base_ref, base_ref,
head_ref head_ref
}; };
@@ -14976,14 +14992,15 @@ function readConfigFile(filePath) {
catch (error) { catch (error) {
throw error; throw error;
} }
const values = yaml_1.default.parse(data); data = yaml_1.default.parse(data);
// get rid of the ugly dashes from the actions conventions // get rid of the ugly dashes from the actions conventions
for (const key of Object.keys(values)) { for (const key of Object.keys(data)) {
if (key.includes('-')) { if (key.includes('-')) {
values[key.replace(/-/g, '_')] = values[key]; data[key.replace(/-/g, '_')] = data[key];
delete values[key]; delete data[key];
} }
} }
const values = schemas_1.ConfigurationOptionsSchema.parse(data);
return values; return values;
} }
exports.readConfigFile = readConfigFile; exports.readConfigFile = readConfigFile;
@@ -14997,7 +15014,7 @@ exports.readConfigFile = readConfigFile;
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.filterChangesBySeverity = void 0; exports.filterChangesByScopes = exports.filterChangesBySeverity = void 0;
const schemas_1 = __nccwpck_require__(1129); const schemas_1 = __nccwpck_require__(1129);
function filterChangesBySeverity(severity, changes) { function filterChangesBySeverity(severity, changes) {
const severityIdx = schemas_1.SEVERITIES.indexOf(severity); const severityIdx = schemas_1.SEVERITIES.indexOf(severity);
@@ -15021,6 +15038,15 @@ function filterChangesBySeverity(severity, changes) {
return filteredChanges; return filteredChanges;
} }
exports.filterChangesBySeverity = filterChangesBySeverity; exports.filterChangesBySeverity = filterChangesBySeverity;
function filterChangesByScopes(scopes, changes) {
const filteredChanges = changes.filter(change => {
// if there is no scope on the change (Enterprise Server API for now), we will assume it is a runtime scope
const scope = change.scope || 'runtime';
return scopes.includes(scope);
});
return filteredChanges;
}
exports.filterChangesByScopes = filterChangesByScopes;
/***/ }), /***/ }),
@@ -15054,9 +15080,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ChangesSchema = exports.ConfigurationOptionsSchema = exports.PullRequestSchema = exports.ChangeSchema = exports.SEVERITIES = void 0; exports.ChangesSchema = exports.ConfigurationOptionsSchema = exports.PullRequestSchema = exports.ChangeSchema = exports.SeveritySchema = exports.SCOPES = exports.SEVERITIES = void 0;
const z = __importStar(__nccwpck_require__(3301)); const z = __importStar(__nccwpck_require__(3301));
exports.SEVERITIES = ['critical', 'high', 'moderate', 'low']; exports.SEVERITIES = ['critical', 'high', 'moderate', 'low'];
exports.SCOPES = ['unknown', 'runtime', 'development'];
exports.SeveritySchema = z.enum(exports.SEVERITIES).default('low');
exports.ChangeSchema = z.object({ exports.ChangeSchema = z.object({
change_type: z.enum(['added', 'removed']), change_type: z.enum(['added', 'removed']),
manifest: z.string(), manifest: z.string(),
@@ -15066,9 +15094,10 @@ exports.ChangeSchema = z.object({
package_url: z.string(), package_url: z.string(),
license: z.string().nullable(), license: z.string().nullable(),
source_repository_url: z.string().nullable(), source_repository_url: z.string().nullable(),
scope: z.enum(exports.SCOPES).optional(),
vulnerabilities: z vulnerabilities: z
.array(z.object({ .array(z.object({
severity: z.enum(['critical', 'high', 'moderate', 'low']), severity: exports.SeveritySchema,
advisory_ghsa_id: z.string(), advisory_ghsa_id: z.string(),
advisory_summary: z.string(), advisory_summary: z.string(),
advisory_url: z.string() advisory_url: z.string()
@@ -15083,7 +15112,8 @@ exports.PullRequestSchema = z.object({
}); });
exports.ConfigurationOptionsSchema = z exports.ConfigurationOptionsSchema = z
.object({ .object({
fail_on_severity: z.enum(exports.SEVERITIES).default('low'), fail_on_severity: exports.SeveritySchema,
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).default([]), allow_licenses: z.array(z.string()).default([]),
deny_licenses: z.array(z.string()).default([]), deny_licenses: z.array(z.string()).default([]),
config_file: z.string().optional().default('false'), config_file: z.string().optional().default('false'),
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "dependency-review-action", "name": "dependency-review-action",
"version": "2.1.0", "version": "2.2.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "dependency-review-action", "name": "dependency-review-action",
"version": "2.1.0", "version": "2.2.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.9.1", "@actions/core": "^1.9.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "dependency-review-action", "name": "dependency-review-action",
"version": "2.1.0", "version": "2.2.0",
"private": true, "private": true,
"description": "A GitHub Action for Dependency Review", "description": "A GitHub Action for Dependency Review",
"main": "lib/main.js", "main": "lib/main.js",
+19 -3
View File
@@ -6,7 +6,8 @@ import * as z from 'zod'
import { import {
ConfigurationOptions, ConfigurationOptions,
ConfigurationOptionsSchema, ConfigurationOptionsSchema,
SeveritySchema SeveritySchema,
SCOPES
} from './schemas' } from './schemas'
function getOptionalInput(name: string): string | undefined { function getOptionalInput(name: string): string | undefined {
@@ -14,6 +15,14 @@ function getOptionalInput(name: string): string | undefined {
return value.length > 0 ? value : undefined return value.length > 0 ? value : undefined
} }
function parseList(list: string | undefined): string[] | undefined {
if (list === undefined) {
return list
} else {
return list.split(',').map(x => x.trim())
}
}
export function readConfig(): ConfigurationOptions { export function readConfig(): ConfigurationOptions {
const externalConfig = getOptionalInput('config-file') const externalConfig = getOptionalInput('config-file')
if (externalConfig !== undefined) { if (externalConfig !== undefined) {
@@ -29,6 +38,12 @@ export function readInlineConfig(): ConfigurationOptions {
const fail_on_severity = SeveritySchema.parse( const fail_on_severity = SeveritySchema.parse(
getOptionalInput('fail-on-severity') getOptionalInput('fail-on-severity')
) )
const fail_on_scopes = z
.array(z.enum(SCOPES))
.default(['runtime'])
.parse(parseList(getOptionalInput('fail-on-scopes')))
const allow_licenses = getOptionalInput('allow-licenses') const allow_licenses = getOptionalInput('allow-licenses')
const deny_licenses = getOptionalInput('deny-licenses') const deny_licenses = getOptionalInput('deny-licenses')
@@ -41,8 +56,9 @@ export function readInlineConfig(): ConfigurationOptions {
return { return {
fail_on_severity, fail_on_severity,
allow_licenses: allow_licenses?.split(',').map(x => x.trim()), fail_on_scopes,
deny_licenses: deny_licenses?.split(',').map(x => x.trim()), allow_licenses: parseList(allow_licenses),
deny_licenses: parseList(deny_licenses),
base_ref, base_ref,
head_ref head_ref
} }
+14 -1
View File
@@ -1,4 +1,4 @@
import {Changes, Severity, SEVERITIES} from './schemas' import {Changes, Severity, SEVERITIES, Scope} from './schemas'
export function filterChangesBySeverity( export function filterChangesBySeverity(
severity: Severity, severity: Severity,
@@ -33,3 +33,16 @@ export function filterChangesBySeverity(
) )
return filteredChanges return filteredChanges
} }
export function filterChangesByScopes(
scopes: Scope[],
changes: Changes
): Changes {
const filteredChanges = changes.filter(change => {
// if there is no scope on the change (Enterprise Server API for now), we will assume it is a runtime scope
const scope = change.scope || 'runtime'
return scopes.includes(scope)
})
return filteredChanges
}
+8 -4
View File
@@ -3,9 +3,9 @@ import * as dependencyGraph from './dependency-graph'
import * as github from '@actions/github' import * as github from '@actions/github'
import styles from 'ansi-styles' import styles from 'ansi-styles'
import {RequestError} from '@octokit/request-error' import {RequestError} from '@octokit/request-error'
import {Change, Severity} from './schemas' import {Change, Severity, Scope} from './schemas'
import {readConfig} from '../src/config' import {readConfig} from '../src/config'
import {filterChangesBySeverity} from '../src/filter' import {filterChangesBySeverity, filterChangesByScopes} from '../src/filter'
import {getDeniedLicenseChanges} from './licenses' import {getDeniedLicenseChanges} from './licenses'
import * as summary from './summary' import * as summary from './summary'
import {getRefs} from './git-refs' import {getRefs} from './git-refs'
@@ -30,9 +30,13 @@ async function run(): Promise<void> {
deny: config.deny_licenses deny: config.deny_licenses
} }
const scopes = config.fail_on_scopes
const scopedChanges = filterChangesByScopes(scopes as Scope[], changes)
const addedChanges = filterChangesBySeverity( const addedChanges = filterChangesBySeverity(
minSeverity as Severity, minSeverity as Severity,
changes scopedChanges
).filter( ).filter(
change => change =>
change.change_type === 'added' && change.change_type === 'added' &&
@@ -41,7 +45,7 @@ async function run(): Promise<void> {
) )
const [licenseErrors, unknownLicenses] = getDeniedLicenseChanges( const [licenseErrors, unknownLicenses] = getDeniedLicenseChanges(
changes, scopedChanges,
licenses licenses
) )
+6 -1
View File
@@ -1,6 +1,8 @@
import * as z from 'zod' import * as z from 'zod'
export const SEVERITIES = ['critical', 'high', 'moderate', 'low'] as const export const SEVERITIES = ['critical', 'high', 'moderate', 'low'] as const
export const SCOPES = ['unknown', 'runtime', 'development'] as const
export const SeveritySchema = z.enum(SEVERITIES).default('low') export const SeveritySchema = z.enum(SEVERITIES).default('low')
export const ChangeSchema = z.object({ export const ChangeSchema = z.object({
@@ -12,6 +14,7 @@ export const ChangeSchema = z.object({
package_url: z.string(), package_url: z.string(),
license: z.string().nullable(), license: z.string().nullable(),
source_repository_url: z.string().nullable(), source_repository_url: z.string().nullable(),
scope: z.enum(SCOPES).optional(),
vulnerabilities: z vulnerabilities: z
.array( .array(
z.object({ z.object({
@@ -34,6 +37,7 @@ export const PullRequestSchema = z.object({
export const ConfigurationOptionsSchema = z export const ConfigurationOptionsSchema = z
.object({ .object({
fail_on_severity: SeveritySchema, fail_on_severity: SeveritySchema,
fail_on_scopes: z.array(z.enum(SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).default([]), allow_licenses: z.array(z.string()).default([]),
deny_licenses: z.array(z.string()).default([]), deny_licenses: z.array(z.string()).default([]),
config_file: z.string().optional().default('false'), config_file: z.string().optional().default('false'),
@@ -51,4 +55,5 @@ export const ChangesSchema = z.array(ChangeSchema)
export type Change = z.infer<typeof ChangeSchema> export type Change = z.infer<typeof ChangeSchema>
export type Changes = z.infer<typeof ChangesSchema> export type Changes = z.infer<typeof ChangesSchema>
export type ConfigurationOptions = z.infer<typeof ConfigurationOptionsSchema> export type ConfigurationOptions = z.infer<typeof ConfigurationOptionsSchema>
export type Severity = typeof SEVERITIES[number] export type Severity = z.infer<typeof SeveritySchema>
export type Scope = typeof SCOPES[number]