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

Move configuration file location #112

Merged
merged 26 commits into from Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1791775
temp commit
febuiles Jun 13, 2022
01fa67b
adding dist
febuiles Jun 14, 2022
24d7ef3
Use an empty config options type.
febuiles Jun 14, 2022
efecf6f
Remove the variables from env so they don't default to empty strings.
febuiles Jun 14, 2022
ef97470
Don't set the defaults in the test :/
febuiles Jun 14, 2022
cc31018
Updating dist.
febuiles Jun 14, 2022
e56fe29
Remove old config file.
febuiles Jun 14, 2022
b5b4910
Adding the config definition to action.yml
febuiles Jun 14, 2022
7278093
Clarify some of the error messages.
febuiles Jun 14, 2022
3eff3f5
let => const
febuiles Jun 14, 2022
76ad376
Adding more tests for the config file.
febuiles Jun 14, 2022
3355ec4
adding dist
febuiles Jun 14, 2022
c973154
Dashes instead of underscores.
febuiles Jun 14, 2022
b0e1f38
Linting YAML
febuiles Jun 14, 2022
f83a407
Use the correct name for allowlists.
febuiles Jun 14, 2022
fd6e756
Updating readConfig() to be more readable, get rid of typecasts.
febuiles Jun 14, 2022
2860b57
Update README.md
febuiles Jun 14, 2022
00be2ce
Typos.
febuiles Jun 14, 2022
0b87f02
Document how we test inputs
febuiles Jun 14, 2022
42e2bc1
Handle unknown licenses.
febuiles Jun 14, 2022
c6587b6
Updating README with instructions for unknown licenses.
febuiles Jun 14, 2022
54764c9
Update README.md
courtneycl Jun 14, 2022
871f406
adding doc for protected branches
courtneycl Jun 15, 2022
dfd5196
Update schemas.ts
courtneycl Jun 15, 2022
faa63c3
adding dist
febuiles Jun 15, 2022
f3f3519
Merge branch 'main' into move-config-file
febuiles Jun 15, 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
8 changes: 0 additions & 8 deletions .github/dependency-review.yml

This file was deleted.

93 changes: 89 additions & 4 deletions README.md
Expand Up @@ -2,7 +2,7 @@

This action scans your pull requests for dependency changes and will raise an error if any new dependencies have existing vulnerabilities. The action is supported by an [API endpoint](https://docs.github.com/en/rest/reference/dependency-graph#dependency-review) that diffs the dependencies between any two revisions.

The action is available for all public repositories, as well as private repositories that have Github Advanced Security licensed.
The action is available for all public repositories, as well as private repositories that have Github Advanced Security licensed.

<img width="854" alt="Screen Shot 2022-03-31 at 1 10 51 PM" src="https://user-images.githubusercontent.com/2161/161042286-b22d7dd3-13cb-458d-8744-ce70ed9bf562.png">

Expand All @@ -25,10 +25,95 @@ jobs:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v1
uses: actions/dependency-review-action@v2
```

Please keep in mind that you need a GitHub Advanced Security license if you're running this Action on private repos.
Please keep in mind that you need a GitHub Advanced Security license if you're running this action on private repos.

## 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:

```yaml
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
# Possible values: "critical", "high", "moderate", "low"
# fail-on-severity: critical
#
# You can only can only include one of these two options: `allow-licenses` and `deny-licences`
#
# 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
```

### Vulnerability Severity

By default the action will fail on any pull request that contains a
vulnerable dependency, regardless of the severity level. You can override this behavior by
using the `fail-on-severity` option, which will cause a failure on any pull requests that introduce vulnerabilities of the specified severity level or higher. The possible values are: `critical`, `high`, `moderate`, or `low`. The
action defaults to `low`.

This example will only fail on pull requests with `critical` and `high` vulnerabilities:

```yaml
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
fail-on-severity: high
```

### Licenses

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
your repository will accept. Alternatively, you can use `deny-licenses` to only
forbid a subset of licenses.

You can use the [Licenses
API](https://docs.github.com/en/rest/licenses) to see the full list of
supported licenses. Use the `spdx_id` field for every license you want
to filter. A couple of examples:

```yaml
# only allow MIT-licensed dependents
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
allow-licenses: MIT
```

```yaml
# Block Apache 1.1 and 2.0 licensed dependents
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
deny-licenses: Apache-1.1, Apache-2.0
```

**Important**

* The action will only accept one of the two parameters; an error will
be raised if you provide both.
* By default both parameters are empty (no license checking is
performed).
* 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
action won't fail**.

## Getting help

Expand All @@ -37,7 +122,7 @@ issue](https://github.com/actions/dependency-review-action/issues/new/choose).

## Contributing

We are grateful for any contributions made to this project.
We are grateful for any contributions made to this project.

Please read [CONTRIBUTING.MD](https://github.com/actions/dependency-review-action/blob/main/CONTRIBUTING.md) to get started.

Expand Down
56 changes: 39 additions & 17 deletions __tests__/config.test.ts
@@ -1,31 +1,53 @@
import {expect, test} from '@jest/globals'
import {readConfigFile} from '../src/config'
import {expect, test, beforeEach} from '@jest/globals'
import {readConfig} from '../src/config'

test('reads the 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'])
})
// GitHub Action inputs come in the form of environment variables
// with an INPUT prefix (e.g. INPUT_FAIL-ON-SEVERITY)
function setInput(input: string, value: string) {
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.
function clearInputs() {
delete process.env['INPUT_FAIL-ON-SEVERITY']
delete process.env['INPUT_ALLOW-LICENSES']
delete process.env['INPUT_DENY-LICENSES']
}

test('the default config path handles .yml and .yaml', async () => {
expect(true).toEqual(true)
beforeEach(() => {
clearInputs()
})

test('returns a default config when the config file was not found', async () => {
let options = readConfigFile('fixtures/i-dont-exist')
test('it defaults to low severity', async () => {
const options = readConfig()
expect(options.fail_on_severity).toEqual('low')
expect(options.allow_licenses).toEqual(undefined)
})

test('it reads config files with empty options', async () => {
let options = readConfigFile('./__tests__/fixtures/no-licenses-config.yml')
test('it reads custom configs', async () => {
setInput('fail-on-severity', 'critical')
setInput('allow-licenses', ' BSD, GPL 2')

const options = readConfig()
expect(options.fail_on_severity).toEqual('critical')
expect(options.allow_licenses).toEqual(['BSD', 'GPL 2'])
})

test('it defaults to empty allow/deny lists ', async () => {
const options = readConfig()

expect(options.allow_licenses).toEqual(undefined)
expect(options.deny_licenses).toEqual(undefined)
})

test('it raises an error if both an allow and denylist are specified', async () => {
expect(() =>
readConfigFile('./__tests__/fixtures/conflictive-config.yml')
).toThrow()
setInput('allow-licenses', 'MIT')
setInput('deny-licenses', 'BSD')

expect(() => readConfig()).toThrow()
})

test('it raises an error when given an unknown severity', async () => {
setInput('fail-on-severity', 'zombies')
expect(() => readConfig()).toThrow()
})
6 changes: 3 additions & 3 deletions __tests__/licenses.test.ts
Expand Up @@ -48,21 +48,21 @@ let rubyChange: Change = {

test('it fails if a license outside the allow list is found', async () => {
const changes: Changes = [npmChange, rubyChange]
const invalidChanges = getDeniedLicenseChanges(changes, {allow: ['BSD']})
const [invalidChanges, _] = getDeniedLicenseChanges(changes, {allow: ['BSD']})
expect(invalidChanges[0]).toBe(npmChange)
})

test('it fails if a license inside the deny list is found', async () => {
const changes: Changes = [npmChange, rubyChange]
const invalidChanges = getDeniedLicenseChanges(changes, {deny: ['BSD']})
const [invalidChanges] = getDeniedLicenseChanges(changes, {deny: ['BSD']})
expect(invalidChanges[0]).toBe(rubyChange)
})

// This is more of a "here's a behavior that might be surprising" than an actual
// thing we want in the system. Please remove this test after refactoring.
test('it fails all license checks when allow is provided an empty array', async () => {
const changes: Changes = [npmChange, rubyChange]
let invalidChanges = getDeniedLicenseChanges(changes, {
let [invalidChanges, _] = getDeniedLicenseChanges(changes, {
allow: [],
deny: ['BSD']
})
Expand Down
12 changes: 11 additions & 1 deletion action.yml
Expand Up @@ -3,9 +3,19 @@ description: 'Prevent the introduction of dependencies with known vulnerabilitie
author: 'GitHub'
inputs:
repo-token:
description: 'Token for the repository. Can be passed in using `{{ secrets.GITHUB_TOKEN }}`.'
description: Token for the repository. Can be passed in using `{{ secrets.GITHUB_TOKEN }}`.
required: false
default: ${{ github.token }}
fail-on-severity:
description: Don't block PRs below this severity. Possible values are `low`, `moderate`, `high`, `critical`.
required: false
default: 'low'
allow-licenses:
description: Comma-separated list of allowed licenses (e.g. "MIT, GPL 3.0, BSD 2 Clause")
required: false
deny-licenses:
description: Comma-separated list of forbidden licenses (e.g. "MIT, GPL 3.0, BSD 2 Clause")
required: false
runs:
using: 'node16'
main: 'dist/index.js'