-
Notifications
You must be signed in to change notification settings - Fork 110
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
Fix default values for fail-on-severity #451
Changes from all commits
97c9465
0041d7f
153f274
ff46a4b
2c065db
3f6a17c
50b9187
cebb5b1
9885d0c
654eb5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import {expect, test, beforeEach} from '@jest/globals' | ||
import {readConfig} from '../src/config' | ||
import * as Utils from '../src/utils' | ||
import {setInput, clearInputs} from './test-helpers' | ||
|
||
const externalConfig = `fail_on_severity: 'high' | ||
allow_licenses: ['GPL-2.0-only'] | ||
` | ||
const mockOctokit = { | ||
rest: { | ||
repos: { | ||
getContent: jest.fn().mockReturnValue({data: externalConfig}) | ||
} | ||
} | ||
} | ||
|
||
jest.mock('octokit', () => { | ||
return { | ||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class | ||
Octokit: class { | ||
constructor() { | ||
return mockOctokit | ||
} | ||
} | ||
} | ||
}) | ||
|
||
beforeAll(() => { | ||
jest.spyOn(Utils, 'isSPDXValid').mockReturnValue(true) | ||
}) | ||
|
||
beforeEach(() => { | ||
clearInputs() | ||
}) | ||
|
||
test('it reads an external config file', async () => { | ||
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml') | ||
|
||
const config = await readConfig() | ||
expect(config.fail_on_severity).toEqual('critical') | ||
expect(config.allow_licenses).toEqual(['BSD', 'GPL 2']) | ||
}) | ||
|
||
test('raises an error when the config file was not found', async () => { | ||
setInput('config-file', 'fixtures/i-dont-exist') | ||
await expect(readConfig()).rejects.toThrow(/Unable to fetch/) | ||
}) | ||
|
||
test('it parses options from both sources', async () => { | ||
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml') | ||
|
||
let config = await readConfig() | ||
expect(config.fail_on_severity).toEqual('critical') | ||
|
||
setInput('base-ref', 'a-custom-base-ref') | ||
config = await readConfig() | ||
expect(config.base_ref).toEqual('a-custom-base-ref') | ||
}) | ||
|
||
test('in case of conflicts, the inline config is the source of truth', async () => { | ||
setInput('fail-on-severity', 'low') | ||
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml') // this will set fail-on-severity to 'critical' | ||
|
||
const config = await readConfig() | ||
expect(config.fail_on_severity).toEqual('low') | ||
}) | ||
|
||
test('it uses the default values when loading external files', async () => { | ||
setInput('config-file', './__tests__/fixtures/no-licenses-config.yml') | ||
let config = await readConfig() | ||
expect(config.allow_licenses).toEqual(undefined) | ||
expect(config.deny_licenses).toEqual(undefined) | ||
|
||
setInput('config-file', './__tests__/fixtures/license-config-sample.yml') | ||
config = await readConfig() | ||
expect(config.fail_on_severity).toEqual('low') | ||
}) | ||
|
||
test('it accepts an external configuration filename', async () => { | ||
setInput('config-file', './__tests__/fixtures/no-licenses-config.yml') | ||
const config = await readConfig() | ||
expect(config.fail_on_severity).toEqual('critical') | ||
}) | ||
|
||
test('it raises an error when given an unknown severity in an external config file', async () => { | ||
setInput('config-file', './__tests__/fixtures/invalid-severity-config.yml') | ||
await expect(readConfig()).rejects.toThrow() | ||
}) | ||
|
||
test('it supports comma-separated lists', async () => { | ||
setInput( | ||
'config-file', | ||
'./__tests__/fixtures/inline-license-config-sample.yml' | ||
) | ||
const config = await readConfig() | ||
|
||
expect(config.allow_licenses).toEqual(['MIT', 'GPL-2.0-only']) | ||
}) | ||
|
||
test('it reads a config file hosted in another repo', async () => { | ||
setInput( | ||
'config-file', | ||
'future-funk/anyone-cualkiera/external-config.yml@main' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 I wonder if we should put this file into a static repo under the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are mocking the response to avoid HTTP calls: https://github.com/actions/dependency-review-action/pull/451/files/654eb5ca1c29dea80ae435b7e64ac77ec50eb2da#diff-82828d4b4ae35e47f69929a800f360461e236bea4371942e452bb901ea937c2dR9-R26 |
||
) | ||
setInput('external-repo-token', 'gh_viptoken') | ||
|
||
const config = await readConfig() | ||
|
||
expect(config.fail_on_severity).toEqual('high') | ||
expect(config.allow_licenses).toEqual(['GPL-2.0-only']) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
allow-licenses: MIT, GPL-2.0-only | ||
allow-licenses: "MIT, GPL-2.0-only" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
fail-on-severity: 'so many zombies' | ||
deny-licenses: | ||
fail_on_severity: 'so many zombies' | ||
deny_licenses: | ||
- MIT |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// GitHub Action inputs come in the form of environment variables | ||
// with an INPUT prefix (e.g. INPUT_FAIL-ON-SEVERITY) | ||
export function setInput(input: string, value: string): void { | ||
process.env[`INPUT_${input.toUpperCase()}`] = value | ||
} | ||
|
||
// We want a clean ENV before each test. We use `delete` | ||
// since we want `undefined` values and not empty strings. | ||
export function clearInputs(): void { | ||
const allowedOptions = [ | ||
'FAIL-ON-SEVERITY', | ||
'FAIL-ON-SCOPES', | ||
'ALLOW-LICENSES', | ||
'DENY-LICENSES', | ||
'ALLOW-GHSAS', | ||
'LICENSE-CHECK', | ||
'VULNERABILITY-CHECK', | ||
'CONFIG-FILE', | ||
'BASE-REF', | ||
'HEAD-REF', | ||
'COMMENT-SUMMARY-IN-PR' | ||
] | ||
|
||
// eslint-disable-next-line github/array-foreach | ||
allowedOptions.forEach(option => { | ||
delete process.env[`INPUT_${option.toUpperCase()}`] | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 I assume there's some known friction involved 👍 but I wonder could we relax the option name parsing to accept both formats? Feels like this will be tough for end users to remember
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, it's on the TODO. This PR only fixes the bug with defaults value, but going forward I think supporting both options by replacing
-
with_
when found is the way.