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

Add external configuration file #228

Merged
merged 24 commits into from Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
71a0ed0
Updating the README to include instructions for both config file opti…
febuiles Sep 6, 2022
6dfe5fd
Force line-breaks.
febuiles Sep 6, 2022
7e2a489
Merge branch 'main' into external-config
febuiles Sep 16, 2022
8ef181b
Read a hardcoded config file.
febuiles Sep 16, 2022
0ba7166
Adding failing tests.
febuiles Sep 16, 2022
8bac022
Merge branch 'main' into external-config
febuiles Sep 19, 2022
b93fcee
Raise an error if the config file is not found.
febuiles Sep 19, 2022
07a7056
Update README to include config-file option.
febuiles Sep 19, 2022
bf0cb7f
Add a default config file.
febuiles Sep 19, 2022
a91c3ac
Split reading inline/external configuration options.
febuiles Sep 19, 2022
4b4ec08
Make sure we get rid of the ridiculous dashes in the names.
febuiles Sep 19, 2022
3c95902
Adding more tests for the config file.
febuiles Sep 19, 2022
1ef21ab
Leave a failing test for tomorrow!
febuiles Sep 19, 2022
aeb9ff5
adding dist
febuiles Sep 19, 2022
61f19e6
Let the users set the path for the config file.
febuiles Sep 20, 2022
8903613
Updating dist.
febuiles Sep 20, 2022
37dc328
Merge branch 'main' into external-config
febuiles Sep 20, 2022
eef7e39
Accept options from both sources, prioritize external config.
febuiles Sep 20, 2022
c4693c0
Raise errors for invalid values in the external config.
febuiles Sep 21, 2022
54cd9a7
Merge branch 'main' into external-config
febuiles Sep 21, 2022
38ee6e8
Improve scopes example in new docs.
febuiles Sep 21, 2022
4d3b8e5
Clarify code a bit.
febuiles Sep 21, 2022
ff7c97a
adding dist
febuiles Sep 21, 2022
88502ba
Update README.md
febuiles Sep 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/dependency-review-config.yml
@@ -0,0 +1 @@
fail-on-severity: low
149 changes: 123 additions & 26 deletions README.md
Expand Up @@ -64,9 +64,124 @@ jobs:

## Configuration

You can pass additional options to the Dependency Review
Action using your workflow file. Here's an example workflow with
all the possible configurations:
Configure this action by either using an external configuration file,
or by inlining these options in your workflow file.

### Options

#### config-file

A string representing the path to an external configuraton file. By
default external configuration files are not used.

**Possible values**: A string representing the absolute path to the
configuration file.

**Example**: `config-file: ./.github/dependency-review-config.yml`.

#### fail-on-severity

Configure the severity level for alerting. See "[Vulnerability Severity](https://github.com/actions/dependency-review-action#vulnerability-severity)".

**Possible values**: `critical`, `high`, `moderate`, `low`.

**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`

**Inline example**: `fail-on-scopes: development, runtime`

**YAML example**:
```yaml
# this prevents scanning development dependencies
fail-on-scopes:
- runtime
```

#### allow-licenses

Only allow the licenses in this list. See "[Licenses](https://github.com/actions/dependency-review-action#licenses)".

**Possible values**: Any `spdx_id` value(s) from
https://docs.github.com/en/rest/licenses.

**Inline example**: `allow-licenses: BSD-3-Clause, MIT`

**YAML example**:
```yaml
allow-licenses:
- BSD-3-Clause
- MIT
```

#### deny-licenses

Add a custom list of licenses you want to block. See
"[Licenses](https://github.com/actions/dependency-review-action#licenses)".

**Possible values**: Any `spdx_id` value(s) from
https://docs.github.com/en/rest/licenses.

**Inline example**: `deny-licenses: LGPL-2.0, BSD-2-Clause`

**YAML example**:
```yaml
deny-licenses:
- LGPL-2.0
- BSD-2-Clause
```

#### base-ref/head-ref

Provide custom git references for the git base/head when performing
the comparison. If you are using pull requests, or
`pull_request_target` events you do not need to worry about setting
this. The values need to be specified for all other event types.

**Possible values**: Any valid git ref(s) in your project.

**Example**:
```yaml
base-ref: 8bb8a58d6a4028b6c2e314d5caaf273f57644896
head-ref: 69af5638bf660cf218aad5709a4c100e42a2f37b
```

### Configuration File

You can use an external configuration file to specify the settings for
this Action.

Start by specifying that you will be using an external configuration
file:

```yaml
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
config-file: "./.github/dependency-review-config.yml"
```

And then create the file in the path you just specified. **All of these fields are
optional**:

```yaml
fail-on-severity: "critical"
allow-licenses:
- "GPL-3.0"
- "BSD-3-Clause"
- "MIT"
```

### Inline Configuration

You can pass options to the Dependency Review
Action using your workflow file. Here's an example of what the full
file would look like:

```yaml
name: 'Dependency Review'
Expand All @@ -82,29 +197,11 @@ jobs:
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
# Possible values: "critical", "high", "moderate", "low"
# fail-on-severity: critical
#
# Possible values in comma separated list: "unknown", "runtime", or "development"
# fail-on-scopes: runtime, development
#
# Possible values: Any available git ref
# base-ref: ${{ github.event.pull_request.base.ref }}
# head-ref: ${{ github.event.pull_request.head.ref }}
#
# You can only include one of these two options: `allow-licenses` and `deny-licenses`. These options are not supported on Enterprise Server.
#
# Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses
# allow-licenses: GPL-3.0, BSD-3-Clause, MIT
#
# Possible values: Any `spdx_id` value(s) from https://docs.github.com/en/rest/licenses
# deny-licenses: LGPL-2.0, BSD-2-Clause
```
fail-on-severity: moderate

When the workflow with this action is caused by a `pull_request` or `pull_request_target` event,
the `base-ref` and `head-ref` values have the defaults as shown above. If the workflow is caused by
any other event, the `base-ref` and `head-ref` options must be
explicitly set in the configuration file.
# Use comma-separated names to pass list arguments:
deny-licenses: LGPL-2.0, BSD-2-Clause
```

### Vulnerability Severity

Expand Down Expand Up @@ -161,7 +258,7 @@ to filter. A couple of examples:
deny-licenses: Apache-1.1, Apache-2.0
```

**Important**
### Considerations

- Checking for licenses is not supported on Enterprise Server.
- The action will only accept one of the two parameters; an error will
Expand Down
60 changes: 59 additions & 1 deletion __tests__/config.test.ts
@@ -1,5 +1,5 @@
import {expect, test, beforeEach} from '@jest/globals'
import {readConfig} from '../src/config'
import {readConfig, readConfigFile} from '../src/config'
import {getRefs} from '../src/git-refs'

// GitHub Action inputs come in the form of environment variables
Expand All @@ -16,6 +16,7 @@ function clearInputs() {
'FAIL-ON-SCOPES',
'ALLOW-LICENSES',
'DENY-LICENSES',
'CONFIG-FILE',
'BASE-REF',
'HEAD-REF'
]
Expand Down Expand Up @@ -84,10 +85,66 @@ test('it raises an error when no refs are provided and the event is not a pull r
).toThrow()
})

test('it reads an external config file', async () => {
let options = readConfigFile('./__tests__/fixtures/config-allow-sample.yml')
expect(options.fail_on_severity).toEqual('critical')
expect(options.allow_licenses).toEqual(['BSD', 'GPL 2'])
})

test('raises an error when the the config file was not found', async () => {
expect(() => readConfigFile('fixtures/i-dont-exist')).toThrow()
})

test('it parses options from both sources', async () => {
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml')

let options = readConfig()
expect(options.fail_on_severity).toEqual('critical')

setInput('base-ref', 'a-custom-base-ref')
options = readConfig()
expect(options.base_ref).toEqual('a-custom-base-ref')
})

test('in case of conflicts, the external config is the source of truth', async () => {
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml') // this will set fail-on-severity to 'critical'

let options = readConfig()
expect(options.fail_on_severity).toEqual('critical')

// this should not overwite the previous value
setInput('fail-on-severity', 'low')
options = readConfig()
expect(options.fail_on_severity).toEqual('critical')
})

test('it uses the default values when loading external files', async () => {
setInput('config-file', './__tests__/fixtures/no-licenses-config.yml')
let options = readConfig()
expect(options.allow_licenses).toEqual(undefined)
expect(options.deny_licenses).toEqual(undefined)

setInput('config-file', './__tests__/fixtures/license-config-sample.yml')
options = readConfig()
expect(options.fail_on_severity).toEqual('low')
})

test('it accepts an external configuration filename', async () => {
setInput('config-file', './__tests__/fixtures/no-licenses-config.yml')
const options = readConfig()
expect(options.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')
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()
Expand All @@ -98,6 +155,7 @@ test('it parses custom scopes preference', async () => {
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()
Expand Down
3 changes: 3 additions & 0 deletions __tests__/fixtures/invalid-severity-config.yml
@@ -0,0 +1,3 @@
fail-on-severity: 'so many zombies'
deny-licenses:
- MIT
1 change: 1 addition & 0 deletions __tests__/fixtures/license-config-sample.yml
@@ -0,0 +1 @@
allow_licenses: ['MIT', 'GPL 2']
3 changes: 3 additions & 0 deletions action.yml
Expand Up @@ -20,6 +20,9 @@ inputs:
head-ref:
description: The head 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
config-file:
description: A filepath to the configuration file for the action.
required: false
allow-licenses:
description: Comma-separated list of allowed licenses (e.g. "MIT, GPL 3.0, BSD 2 Clause")
required: false
Expand Down