Skip to content

Commit

Permalink
Merge pull request #228 from actions/external-config
Browse files Browse the repository at this point in the history
Add external configuration file
  • Loading branch information
febuiles committed Sep 22, 2022
2 parents e89f113 + 88502ba commit 29cdbbe
Show file tree
Hide file tree
Showing 12 changed files with 8,612 additions and 50 deletions.
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

0 comments on commit 29cdbbe

Please sign in to comment.