Compare commits

...

67 Commits

Author SHA1 Message Date
Eli Reisman 05042db2b6 update dist packaging 2024-09-16 12:42:52 -07:00
Eli Reisman 6aacbe0934 add a warning message if there is room in the summary prior to cutoff 2024-09-16 12:42:35 -07:00
Eli Reisman 293ccdb6e9 add truncation escape valve to new file summary to avoid overflow 2024-09-16 12:26:36 -07:00
Henri Maurer 83c7cc6aa7 Do not list changes dependencies in summary 2024-09-16 11:29:47 -07:00
Eli Reisman b3559aa82e Merge pull request #829 from actions/elireisman/sec-findings-update
Upgrade transitive micromatch library
2024-09-16 10:04:59 -07:00
Eli Reisman 8179e6abd6 upgrade micromatch within given dependent parent pkg bounds but past security vuln 2024-09-16 09:53:44 -07:00
Eli Reisman 526b7f2f9b Merge pull request #815 from actions/dependabot/npm_and_yarn/types/node-20.16.0
Bump @types/node from 20.11.28 to 20.16.0
2024-08-19 10:31:48 -07:00
dependabot[bot] e5cb30f678 Bump @types/node from 20.11.28 to 20.16.0
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.11.28 to 20.16.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 01:33:46 +00:00
Jon Janego 90820aba8c Merge pull request #793 from actions/jonjanego-patch-1
Update CONTRIBUTING.md
2024-07-12 16:13:55 -05:00
Jon Janego 7367319600 Merge pull request #794 from actions/jonjanego-patch-2
Create pull_request_template.md
2024-07-12 16:11:24 -05:00
Jon Janego affc3a4f15 Create pull_request_template.md 2024-07-12 16:07:23 -05:00
Jon Janego 07d3c7257a Update CONTRIBUTING.md
minor wording
2024-07-12 15:58:13 -05:00
Justin Holguín a2dda6f539 Merge pull request #766 from louis-bompart/main
fix: getRefs function to handle merge_group events
2024-07-12 12:55:37 -07:00
Louis Bompart 45dc50cabe fix: getRefs function to handle merge_group events 2024-07-12 14:22:20 +02:00
Justin Holguín 5a2ce3f5b9 Merge pull request #791 from actions/juxtin/update-version
Prepare even more for v4.3.4
2024-07-11 13:47:10 -07:00
Justin Holguín ac6a6adece Prepare even more for v4.3.4 2024-07-11 20:39:43 +00:00
Justin Holguín 3e2b91798f Merge pull request #790 from actions/juxtin/update-version
Prepare for v4.3.4 release
2024-07-11 13:38:12 -07:00
Justin Holguín d9ab9c8c45 Update version in package.json 2024-07-11 18:57:29 +00:00
Justin Holguín 8c152c7a0f Merge pull request #769 from actions/dependabot/npm_and_yarn/zod-3.23.8
Bump zod from 3.22.4 to 3.23.8
2024-07-10 10:50:09 -07:00
Justin Holguín 0085d30a6f Update dist 2024-07-10 17:47:42 +00:00
dependabot[bot] 08b5bf2921 Bump zod from 3.22.4 to 3.23.8
Bumps [zod](https://github.com/colinhacks/zod) from 3.22.4 to 3.23.8.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Changelog](https://github.com/colinhacks/zod/blob/master/CHANGELOG.md)
- [Commits](https://github.com/colinhacks/zod/compare/v3.22.4...v3.23.8)

---
updated-dependencies:
- dependency-name: zod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-10 17:43:18 +00:00
Justin Holguín 986fce9040 Merge pull request #784 from actions/dependabot/npm_and_yarn/got-14.4.1
Bump got from 14.2.0 to 14.4.1
2024-07-10 10:41:24 -07:00
Justin Holguín 28743f8570 Merge pull request #719 from actions/change-spdx-parser
Update SPDX Expression Parsing
2024-07-10 10:06:31 -07:00
Justin Holguín d6f34c3a26 Merge pull request #789 from actions/dependabot/npm_and_yarn/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3
2024-07-08 14:53:16 -07:00
dependabot[bot] 465867cec8 Bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 21:49:13 +00:00
Justin Holguín b4ae47ca2c Properly display test failures using jest 2024-06-10 23:07:07 +00:00
Eli Reisman d85edeb45d remove redundant declaration from TS types module registration 2024-06-10 10:11:00 -07:00
Eli Reisman f60d59372e npm run package 2024-06-10 09:52:17 -07:00
Eli Reisman ed624dba72 more SPDX unit tests to illustrate matching behavior 2024-06-10 09:51:01 -07:00
Eli Reisman bbed6f340a update licenses pkg and tests 2024-06-10 09:51:01 -07:00
Eli Reisman 2e4eaa490e complete test suite conversions; simplify fn name 2024-06-10 09:51:00 -07:00
Eli Reisman ecd706f525 register spdx lib as ES Module, start converting call sites to use new spdx pkg - TODO: update tests 2024-06-10 09:51:00 -07:00
Eli Reisman bc5b235cf6 move jest to dev dependencies 2024-06-10 09:51:00 -07:00
Eli Reisman 154c1500f3 add @onebeyond/spdx-license-satisfies to DR Action project 2024-06-10 09:51:00 -07:00
dependabot[bot] 2115d9eeea Bump got from 14.2.0 to 14.4.1
Bumps [got](https://github.com/sindresorhus/got) from 14.2.0 to 14.4.1.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v14.2.0...v14.4.1)

---
updated-dependencies:
- dependency-name: got
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 01:18:26 +00:00
Eli Reisman df5d74f5d3 Merge pull request #783 from actions/elireisman/all-changes-to-scorecard
Include all added dependencies in scorecard entries
2024-06-07 14:15:00 -07:00
Eli Reisman 1e5b2e69a2 npm run package 2024-06-07 10:00:47 -07:00
Eli Reisman e69288dbec only filter out removed changes from the original PR diff when adding scorecard entries in DR Action report 2024-06-07 10:00:37 -07:00
Eli Reisman 8285e75fb2 Merge pull request #782 from actions/dependabot/npm_and_yarn/undici-5.28.4
Bump undici from 5.28.3 to 5.28.4
2024-06-07 09:44:10 -07:00
Eli Reisman 2224c7c05a npm run package to update dist 2024-06-07 09:35:26 -07:00
dependabot[bot] c0630c2a88 Bump undici from 5.28.3 to 5.28.4
Bumps [undici](https://github.com/nodejs/undici) from 5.28.3 to 5.28.4.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v5.28.3...v5.28.4)

---
updated-dependencies:
- dependency-name: undici
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-06 18:28:02 +00:00
Eli Reisman 72eb03d02c Merge pull request #781 from actions/release-v4.3.3
Bump project version to 4.3.3 in prep for a release
2024-06-05 12:15:21 -07:00
Eli Reisman 137d8b42ce bump to version v4.3.3 2024-06-05 10:26:55 -07:00
Eli Reisman e6b618ed05 Merge pull request #767 from actions/max-comment-length
Fix the max comment length issue
2024-06-04 13:03:31 -07:00
Eli Reisman 3c42649204 fix ws for linter 2024-06-04 12:33:48 -07:00
Eli Reisman 8e6ea8d29b update packaging 2024-06-04 12:30:34 -07:00
Eli Reisman 1b3d2772d0 post-review: add PR comment full summary test case 2024-06-04 12:30:05 -07:00
Eli Reisman 220872c81a Update src/main.ts
Co-authored-by: Brandon Teng <bteng22@github.com>
2024-06-04 12:14:40 -07:00
Eli Reisman 087d0f81a5 repackage to update dist 2024-06-04 11:50:22 -07:00
Eli Reisman 4531204be7 whitespace 2024-06-04 11:50:21 -07:00
Eli Reisman df1ca890c5 appease linter 2024-06-04 11:50:21 -07:00
Eli Reisman 97c6dd59c3 run prettier to clear linter warnings 2024-06-04 11:50:21 -07:00
Eli Reisman 0bec1ca5b4 clean up list formatting for PR comment 2024-06-04 11:21:15 -07:00
Eli Reisman 5460632ba9 WIP: summary test 2024-06-04 11:21:15 -07:00
Eli Reisman f7aca4f481 refactor to dedup min summary generation 2024-06-04 11:21:14 -07:00
Eli Reisman 1988567896 re-apply set output for comment-content 2024-06-04 11:20:29 -07:00
Justin Hutchings 1e26117d02 Fix extra whitespace in list 2024-06-04 11:20:27 -07:00
Justin Hutchings b1e704b9d6 Fix bug where I replaced the comment in the wrong spot 2024-06-04 11:20:19 -07:00
Justin Hutchings 48fae2e703 Add min-comment to fix max-comment length issue 2024-06-04 11:20:10 -07:00
Jon Janego 8d625cd32e Merge pull request #777 from actions/jonjanego-issue-templates
Create issue templates
2024-06-04 11:41:12 -05:00
Jon Janego 3afc0d4eaa Merge pull request #778 from actions/jonjanego-contribution-updates
Updates to the contribution guidelines
2024-06-04 09:59:36 -05:00
Jon Janego bc8dee91fe Update CONTRIBUTING.md
being consistent about using forks, minor style updates
2024-06-04 09:58:59 -05:00
Jon Janego 0669e2939d Update CONTRIBUTING.md
Co-authored-by: Barry Gordon <896971+brrygrdn@users.noreply.github.com>
2024-06-04 09:45:14 -05:00
Jon Janego fd46ab736e Update CONTRIBUTING.md
fixing example code for consistency
2024-06-04 09:01:11 -05:00
Jon Janego 551e0b82bd Update CONTRIBUTING.md
fixing a sentence fragment
2024-06-04 08:59:20 -05:00
Jon Janego fbfa3f19c8 Update SECURITY.md
linking to the main bounty site instead of h1
2024-06-03 16:59:30 -05:00
Jon Janego 4c5eeccebb Update CONTRIBUTING.md
Adding some explanations about contribution standards and local development
2024-06-03 16:18:38 -05:00
27 changed files with 1854 additions and 614 deletions
@@ -0,0 +1,7 @@
## Purpose
_Describe the purpose of this pull request_
## Related Issues
_What issues does this PR close or relate to?_
+56 -38
View File
@@ -4,41 +4,52 @@
[pr]: https://github.com/actions/dependency-review-action/compare
[code-of-conduct]: CODE_OF_CONDUCT.md
Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
Hi there! We're thrilled that you'd like to contribute to this project.
Contributions to this project are
[released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license)
to the public under the [project's open source license](LICENSE).
Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE).
Please note that this project is released with a [Contributor Code of
Conduct][code-of-conduct]. By participating in this project you agree
to abide by its terms.
Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.
### How it works
## Bug reports and other issues
This Action makes an authenticated query to the Dependency Graph Diff
API endpoint (`GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}`)
to find out the set of added and removed dependencies for each manifest.
If you've encountered a problem, please let us know by [submitting an issue](https://github.com/actions/dependency-review-action/issues/new)!
### Bootstrapping the project
## Enhancements and feature requests
```
git clone https://github.com/actions/dependency-review-action.git
cd dependency-review-action
npm install
```
If you've got an idea for a new feature or a significant change to the code or its dependencies, please submit as [an issue](https://github.com/actions/dependency-review-action/issues/new) so that the community can see it, and we can discuss it there. We may not be able to respond to every single issue, but will make a best effort!
### Running the tests
If you'd like to make a contribution yourself, we ask that before significant effort is put into code changes, that we have agreement that the change aligns with our strategy for the action. Since this is a verified Action owned by GitHub we want to make sure that contributions are high quality, and that they maintain consistency with the rest of the action's behavior.
```
npm run test
```
1. Create an [issue discussing the idea](https://github.com/actions/dependency-review-action/issues/new), so that we can discuss it there.
2. If we agree to incorporate the idea into the action, please write-up a high level summary of the approach that you plan to take so we can review
_Note_: We don't have any useful tests yet, contributions are welcome!
## Stalebot
## Local Development
We have begun using a [Stalebot action](https://github.com/actions/stale) to help keep the Issues and Pull requests backlogs tidy. You can see the configuration [here](.github/workflows/stalebot.yml). If you'd like to keep an issue open after getting a stalebot warning, simply comment on it and it'll reset the clock.
## Development lifecycle
Ready to contribute to `dependency-review-action`? Here is some information to help you get started.
### High level overview of the action
This action makes an authenticated query to the [Dependency Review API](https://docs.github.com/en/rest/dependency-graph/dependency-review) endpoint (`GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}`) to find out the set of added and removed dependencies for each manifest.
The action then evaluates the differences between the pushes based on the the rules defined in the action configuration, and summarizes the differences and any violations of the rules you have defined as a comment in the pull request that triggered it and the action outputs.
### Local Development
Before you begin, you need to have [Node.js](https://nodejs.org/en/) installed, minimum version 18.
#### Bootstrapping the project
0. [Fork][fork] and clone the repository
1. Change to the working directory: `cd dependency-review-action`
2. Install the dependencies: `npm install`
3. Make sure the tests pass on your machine: `npm run test`
#### Manually testing for vulnerabilities
It is recommended to have atleast [Node 18](https://nodejs.org/en/) installed.
We have a script to scan a given PR for vulnerabilities, this will
help you test your local changes. Make sure to [grab a Personal Access Token (PAT)](https://github.com/settings/tokens) before proceeding (you'll need `repo` permissions for private repos):
@@ -53,7 +64,7 @@ $ GITHUB_TOKEN=<token> ./scripts/scan_pr <pr_url>
Like this:
```sh
$ GITHUB_TOKEN=my-secret-token ./scripts/scan_pr https://github.com/actions/dependency-review-action/pull/3
$ GITHUB_TOKEN=<token> ./scripts/scan_pr https://github.com/actions/dependency-review-action/pull/3
```
[Configuration options](README.md#configuration-options) can be set by
@@ -64,16 +75,20 @@ passing an external YAML [configuration file](README.md#configuration-file) to t
$ GITHUB_TOKEN=<token> ./scripts/scan_pr --config-file my_custom_config.yml <pr_url>
```
## Submitting a pull request
#### Running unit tests
0. [Fork][fork] and clone the repository
1. Configure and install the dependencies: `npm install`
2. Make sure the tests pass on your machine: `npm run test`
3. Create a new branch: `git checkout -b my-branch-name`
4. Make your change, add tests, and make sure the tests still pass
5. Make sure to build and package before pushing: `npm run build && npm run package`
6. Push to your fork and [submit a pull request][pr]
7. Pat your self on the back and wait for your pull request to be reviewed and merged.
```
npm run test
```
_Note_: We don't a very comprehensive test suite, so any contributions to the existing tests are welcome!
### Submitting a pull request
1. Create a new branch: `git checkout -b my-branch-name`
2. Make your change, add tests, and make sure the tests still pass
3. Make sure to build and package before pushing: `npm run build && npm run package`
4. Push to your fork and [submit a pull request][pr]
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
@@ -82,9 +97,14 @@ Here are a few things you can do that will increase the likelihood of your pull
- Write a [good commit message](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- Add examples of the usage to [examples.md](docs/examples.md)
- Link to a sample PR in a custom repository running your version of the Action.
- Please be responsive to any questions and feedback that you get from a maintainer of the repo!
## Cutting a new release
<details>
_Note: these instructions are for maintainers_
1. Update the version number in [package.json](https://github.com/actions/dependency-review-action/blob/main/package.json) and run `npm i` to update the lockfile.
1. Go to [Draft a new
release](https://github.com/actions/dependency-review-action/releases/new)
@@ -117,13 +137,11 @@ To do this just checkout `main`, force-create a new annotated tag, and push it:
git tag -fa v4 -m "Updating v4 to 4.0.1"
git push origin v4 --force
```
</details>
## Stalebot
We have begun using a [Stalebot action](https://github.com/actions/stale) to help keep the Issues and Pull requests backlogs tidy. You can see the configuration [here](.github/workflows/stalebot.yml). If you'd like to keep an issue open after getting a stalebot warning, simply comment on it and it'll reset the clock.
## Resources
- [Creating JavaScript GitHub actions](https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action)
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
- [GitHub Help](https://help.github.com)
+1 -1
View File
@@ -1,3 +1,3 @@
If you discover a security issue in this repo, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github)
If you discover a security issue in this repo, please submit it through the [GitHub Security Bug Bounty](https://bounty.github.com/)
Thanks for helping make GitHub Actions safe for everyone.
+53 -16
View File
@@ -1,13 +1,9 @@
import {expect, test, beforeEach} from '@jest/globals'
import {readConfig} from '../src/config'
import {getRefs} from '../src/git-refs'
import * as Utils from '../src/utils'
import * as spdx from '../src/spdx'
import {setInput, clearInputs} from './test-helpers'
beforeAll(() => {
jest.spyOn(Utils, 'isSPDXValid').mockReturnValue(true)
})
beforeEach(() => {
clearInputs()
})
@@ -19,11 +15,11 @@ test('it defaults to low severity', async () => {
test('it reads custom configs', async () => {
setInput('fail-on-severity', 'critical')
setInput('allow-licenses', ' BSD, GPL 2')
setInput('allow-licenses', 'ISC, GPL-2.0')
const config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
expect(config.allow_licenses).toEqual(['BSD', 'GPL 2'])
expect(config.allow_licenses).toEqual(['ISC', 'GPL-2.0'])
})
test('it defaults to false for warn-only', async () => {
@@ -40,7 +36,7 @@ test('it defaults to empty allow/deny lists ', async () => {
test('it raises an error if both an allow and denylist are specified', async () => {
setInput('allow-licenses', 'MIT')
setInput('deny-licenses', 'BSD')
setInput('deny-licenses', 'BSD-3-Clause')
await expect(readConfig()).rejects.toThrow(
'You cannot specify both allow-licenses and deny-licenses'
@@ -128,6 +124,51 @@ test('it raises an error when no refs are provided and the event is not a pull r
).toThrow()
})
const pullRequestLikeEvents = [
'pull_request',
'pull_request_target',
'merge_group'
]
test.each(pullRequestLikeEvents)(
'it uses the given refs even when the event is %s',
async eventName => {
setInput('base-ref', 'a-custom-base-ref')
setInput('head-ref', 'a-custom-head-ref')
const refs = getRefs(await readConfig(), {
payload: {
pull_request: {
number: 42,
base: {sha: 'pr-base-ref'},
head: {sha: 'pr-head-ref'}
}
},
eventName
})
expect(refs.base).toEqual('a-custom-base-ref')
expect(refs.head).toEqual('a-custom-head-ref')
}
)
test.each(pullRequestLikeEvents)(
'it uses the event refs when the event is %s and the no refs are input',
async eventName => {
const refs = getRefs(await readConfig(), {
payload: {
pull_request: {
number: 42,
base: {sha: 'pr-base-ref'},
head: {sha: 'pr-head-ref'}
}
},
eventName
})
expect(refs.base).toEqual('pr-base-ref')
expect(refs.head).toEqual('pr-head-ref')
}
)
test('it defaults to runtime scope', async () => {
const config = await readConfig()
expect(config.fail_on_scopes).toEqual(['runtime'])
@@ -204,21 +245,17 @@ test('it is not possible to disable both checks', async () => {
})
describe('licenses that are not valid SPDX licenses', () => {
beforeAll(() => {
jest.spyOn(Utils, 'isSPDXValid').mockReturnValue(false)
})
test('it raises an error for invalid licenses in allow-licenses', async () => {
setInput('allow-licenses', ' BSD, GPL 2')
setInput('allow-licenses', ' BSD-YOLO, GPL-2.0')
await expect(readConfig()).rejects.toThrow(
'Invalid license(s) in allow-licenses: BSD,GPL 2'
'Invalid license(s) in allow-licenses: BSD-YOLO'
)
})
test('it raises an error for invalid licenses in deny-licenses', async () => {
setInput('deny-licenses', ' BSD, GPL 2')
setInput('deny-licenses', ' GPL-2.0, BSD-YOLO, Apache-2.0, ToIll')
await expect(readConfig()).rejects.toThrow(
'Invalid license(s) in deny-licenses: BSD,GPL 2'
'Invalid license(s) in deny-licenses: BSD-YOLO, ToIll'
)
})
})
-5
View File
@@ -33,11 +33,6 @@ jest.mock('octokit', () => {
beforeEach(async () => {
jest.resetModules()
jest.doMock('spdx-satisfies', () => {
// mock spdx-satisfies return value
// true for BSD, false for all others
return jest.fn((license: string, _: string): boolean => license === 'BSD')
})
npmChange = createTestChange({ecosystem: 'npm'})
rubyChange = createTestChange({ecosystem: 'rubygems'})
+2 -6
View File
@@ -1,6 +1,6 @@
import {expect, test, beforeEach} from '@jest/globals'
import {readConfig} from '../src/config'
import * as Utils from '../src/utils'
import * as spdx from '../src/spdx'
import {setInput, clearInputs} from './test-helpers'
const externalConfig = `fail_on_severity: 'high'
@@ -25,10 +25,6 @@ jest.mock('octokit', () => {
}
})
beforeAll(() => {
jest.spyOn(Utils, 'isSPDXValid').mockReturnValue(true)
})
beforeEach(() => {
clearInputs()
})
@@ -38,7 +34,7 @@ test('it reads an external config file', async () => {
const config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
expect(config.allow_licenses).toEqual(['BSD', 'GPL 2'])
expect(config.allow_licenses).toEqual(['BSD-3-Clause', 'GPL-2.0'])
})
test('raises an error when the config file was not found', async () => {
+2 -2
View File
@@ -1,4 +1,4 @@
fail_on_severity: critical
allow_licenses:
- "BSD"
- "GPL 2"
- 'BSD-3-Clause'
- 'GPL-2.0'
@@ -1 +1 @@
allow-licenses: "MIT, GPL-2.0-only"
allow-licenses: 'MIT, GPL-2.0-only'
+29 -30
View File
@@ -1,7 +1,6 @@
import {expect, jest, test} from '@jest/globals'
import {Change, Changes} from '../src/schemas'
let getInvalidLicenseChanges: Function
import {getInvalidLicenseChanges} from '../src/licenses'
const npmChange: Change = {
manifest: 'package.json',
@@ -30,7 +29,7 @@ const rubyChange: Change = {
name: 'actionsomething',
version: '3.2.0',
package_url: 'pkg:gem/actionsomething@3.2.0',
license: 'BSD',
license: 'BSD-3-Clause',
source_repository_url: 'github.com/some-repo',
scope: 'runtime',
vulnerabilities: [
@@ -100,29 +99,32 @@ jest.mock('octokit', () => {
beforeEach(async () => {
jest.resetModules()
jest.doMock('spdx-satisfies', () => {
// mock spdx-satisfies return value
// true for BSD, false for all others
return jest.fn((license: string, _: string): boolean => license === 'BSD')
})
// eslint-disable-next-line @typescript-eslint/no-require-imports
;({getInvalidLicenseChanges} = require('../src/licenses'))
})
test('it adds license outside the allow list to forbidden changes', async () => {
const changes: Changes = [npmChange, rubyChange]
const changes: Changes = [
npmChange, // MIT license
rubyChange // BSD license
]
const {forbidden} = await getInvalidLicenseChanges(changes, {
allow: ['BSD']
allow: ['BSD-3-Clause']
})
expect(forbidden[0]).toBe(npmChange)
expect(forbidden.length).toEqual(1)
})
test('it adds license inside the deny list to forbidden changes', async () => {
const changes: Changes = [npmChange, rubyChange]
const changes: Changes = [
npmChange, // MIT license
rubyChange // BSD license
]
const {forbidden} = await getInvalidLicenseChanges(changes, {
deny: ['BSD']
deny: ['BSD-3-Clause']
})
expect(forbidden[0]).toBe(rubyChange)
expect(forbidden.length).toEqual(1)
})
@@ -133,7 +135,7 @@ test('it does not add license outside the allow list to forbidden changes if it
{...rubyChange, change_type: 'removed'}
]
const {forbidden} = await getInvalidLicenseChanges(changes, {
allow: ['BSD']
allow: ['BSD-3-Clause']
})
expect(forbidden).toStrictEqual([])
})
@@ -144,7 +146,7 @@ test('it does not add license inside the deny list to forbidden changes if it is
{...rubyChange, change_type: 'removed'}
]
const {forbidden} = await getInvalidLicenseChanges(changes, {
deny: ['BSD']
deny: ['BSD-3-Clause']
})
expect(forbidden).toStrictEqual([])
})
@@ -156,23 +158,18 @@ test('it adds license outside the allow list to forbidden changes if it is in bo
{...rubyChange, change_type: 'removed'}
]
const {forbidden} = await getInvalidLicenseChanges(changes, {
allow: ['BSD']
allow: ['BSD-3-Clause']
})
expect(forbidden).toStrictEqual([npmChange])
})
test('it adds all licenses to unresolved if it is unable to determine the validity', async () => {
jest.resetModules() // reset module set in before
jest.doMock('spdx-satisfies', () => {
return jest.fn((_first: string, _second: string) => {
throw new Error('Some Error')
})
})
// eslint-disable-next-line @typescript-eslint/no-require-imports
;({getInvalidLicenseChanges} = require('../src/licenses'))
const changes: Changes = [npmChange, rubyChange]
const changes: Changes = [
{...npmChange, license: 'Foo'},
{...rubyChange, license: 'Bar'}
]
const invalidLicenses = await getInvalidLicenseChanges(changes, {
allow: ['BSD']
allow: ['Apache-2.0']
})
expect(invalidLicenses.forbidden.length).toEqual(0)
expect(invalidLicenses.unlicensed.length).toEqual(0)
@@ -182,7 +179,7 @@ test('it adds all licenses to unresolved if it is unable to determine the validi
test('it does not filter out changes that are on the exclusions list', async () => {
const changes: Changes = [pipChange, npmChange, rubyChange]
const licensesConfig = {
allow: ['BSD'],
allow: ['BSD-3-Clause'],
licenseExclusions: ['pkg:pypi/package-1@1.1.1', 'pkg:npm/reeuhq@1.0.2']
}
const invalidLicenses = await getInvalidLicenseChanges(
@@ -198,7 +195,7 @@ test('it does not fail when the packages dont have a valid PURL', async () => {
const changes: Changes = [emptyPurlChange, npmChange, rubyChange]
const licensesConfig = {
allow: ['BSD'],
allow: ['BSD-3-Clause'],
licenseExclusions: ['pkg:pypi/package-1@1.1.1', 'pkg:npm/reeuhq@1.0.2']
}
@@ -212,16 +209,18 @@ test('it does not fail when the packages dont have a valid PURL', async () => {
test('it does filters out changes if they are not on the exclusions list', async () => {
const changes: Changes = [pipChange, npmChange, rubyChange]
const licensesConfig = {
allow: ['BSD'],
allow: ['BSD-3-Clause'],
licenseExclusions: [
'pkg:pypi/notmypackage-1@1.1.1',
'pkg:npm/alsonot@1.0.2'
]
}
const invalidLicenses = await getInvalidLicenseChanges(
changes,
licensesConfig
)
expect(invalidLicenses.forbidden.length).toEqual(2)
expect(invalidLicenses.forbidden[0]).toBe(pipChange)
expect(invalidLicenses.forbidden[1]).toBe(npmChange)
+257
View File
@@ -0,0 +1,257 @@
import {expect, test, describe} from '@jest/globals'
import * as spdx from '../src/spdx'
describe('satisfiesAny', () => {
const units = [
{
candidate: 'MIT',
licenses: ['MIT'],
expected: true
},
{
candidate: 'MIT OR Apache-2.0',
licenses: ['MIT', 'Apache-2.0'],
expected: true
},
{
candidate: '(MIT AND ISC) OR Apache-2.0',
licenses: ['MIT', 'Apache-2.0'],
expected: true
},
{
candidate: 'MIT AND Apache-2.0',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: 'MIT AND BSD-3-Clause',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
// missing params, case sensitivity, syntax problems,
// or unknown licenses will return 'false'
{
candidate: 'MIT OR',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: '',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: 'MIT OR (Apache-2.0 AND ISC)',
licenses: [],
expected: false
},
{
candidate: 'MIT AND (ISC',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: 'MIT OR ISC',
licenses: ['MiT'],
expected: false
}
]
for (const unit of units) {
const got: boolean = spdx.satisfiesAny(unit.candidate, unit.licenses)
test(`should return ${unit.expected} for ("${unit.candidate}", "${unit.licenses}")`, () => {
expect(got).toBe(unit.expected)
})
}
})
describe('satisfiesAll', () => {
const units = [
{
candidate: 'MIT',
licenses: ['MIT'],
expected: true
},
{
candidate: 'Apache-2.0',
licenses: ['MIT', 'ISC', 'Apache-2.0'],
expected: false
},
{
candidate: 'MIT AND Apache-2.0',
licenses: ['MIT', 'Apache-2.0'],
expected: true
},
{
candidate: '(MIT OR ISC) AND Apache-2.0',
licenses: ['MIT', 'Apache-2.0'],
expected: true
},
{
candidate: 'MIT OR BSD-3-Clause',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: 'BSD-3-Clause OR ISC',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: '(MIT AND ISC) OR Apache-2.0',
licenses: ['MIT', 'ISC'],
expected: true
},
// missing params, case sensitivity, syntax problems,
// or unknown licenses will return 'false'
{
candidate: 'MIT OR',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: '',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: 'MIT OR (Apache-2.0 AND ISC)',
licenses: [],
expected: false
},
{
candidate: 'MIT AND (ISC',
licenses: ['MIT', 'Apache-2.0'],
expected: false
},
{
candidate: 'MIT OR ISC',
licenses: ['MiT'],
expected: false
}
]
for (const unit of units) {
const got: boolean = spdx.satisfiesAll(unit.candidate, unit.licenses)
test(`should return ${unit.expected} for ("${unit.candidate}", "${unit.licenses}")`, () => {
expect(got).toBe(unit.expected)
})
}
})
describe('satisfies', () => {
const units = [
{
candidate: 'MIT',
constraint: 'MIT',
expected: true
},
{
candidate: 'Apache-2.0',
constraint: 'MIT',
expected: false
},
{
candidate: 'MIT OR Apache-2.0',
constraint: 'MIT',
expected: true
},
{
candidate: 'MIT OR Apache-2.0',
constraint: 'Apache-2.0',
expected: true
},
{
candidate: 'MIT OR Apache-2.0',
constraint: 'BSD-3-Clause',
expected: false
},
{
candidate: 'MIT OR Apache-2.0',
constraint: 'Apache-2.0 OR BSD-3-Clause',
expected: true
},
{
candidate: 'MIT AND Apache-2.0',
constraint: 'MIT AND Apache-2.0',
expected: true
},
{
candidate: 'MIT OR Apache-2.0',
constraint: 'MIT AND Apache-2.0',
expected: false
},
{
candidate: 'ISC OR (MIT AND Apache-2.0)',
constraint: 'MIT AND Apache-2.0',
expected: true
},
// missing params, case sensitivity, syntax problems,
// or unknown licenses will return 'false'
{
candidate: 'MIT',
constraint: 'MiT',
expected: false
},
{
candidate: 'MIT AND (ISC OR',
constraint: 'MIT',
expected: false
},
{
candidate: 'MIT OR ISC OR Apache-2.0',
constraint: '',
expected: false
},
{
candidate: '',
constraint: '(BSD-3-Clause AND ISC) OR MIT',
expected: false
}
]
for (const unit of units) {
const got: boolean = spdx.satisfies(unit.candidate, unit.constraint)
test(`should return ${unit.expected} for ("${unit.candidate}", "${unit.constraint}")`, () => {
expect(got).toBe(unit.expected)
})
}
})
describe('isValid', () => {
const units = [
{
candidate: 'MIT',
expected: true
},
{
candidate: 'MIT AND BSD-3-Clause',
expected: true
},
{
candidate: '(MIT AND ISC) OR BSD-3-Clause',
expected: true
},
{
candidate: 'NOASSERTION',
expected: false
},
{
candidate: 'Foobar',
expected: false
},
{
candidate: '',
expected: false
}
]
for (const unit of units) {
const got: boolean = spdx.isValid(unit.candidate)
test(`should return ${unit.expected} for ("${unit.candidate}")`, () => {
expect(got).toBe(unit.expected)
})
}
})
+42 -8
View File
@@ -1,5 +1,5 @@
import {expect, jest, test} from '@jest/globals'
import {Changes, ConfigurationOptions, Scorecard} from '../src/schemas'
import {Change, Changes, ConfigurationOptions, Scorecard} from '../src/schemas'
import * as summary from '../src/summary'
import * as core from '@actions/core'
import {createTestChange} from './fixtures/create-test-change'
@@ -109,6 +109,44 @@ test('prints headline as h1', () => {
expect(text).toContain('<h1>Dependency Review</h1>')
})
test('returns minimal summary formatted for posting as a PR comment', () => {
const OLD_ENV = process.env
let changes: Changes = [
createTestChange({name: 'lodash', version: '1.2.3'}),
createTestChange({name: 'colors', version: '2.3.4'}),
createTestChange({name: '@foo/bar', version: '*'})
]
process.env.GITHUB_SERVER_URL = 'https://github.com'
process.env.GITHUB_REPOSITORY = 'owner/repo'
process.env.GITHUB_RUN_ID = 'abc-123-xyz'
let minSummary: string = summary.addSummaryToSummary(
changes,
emptyInvalidLicenseChanges,
emptyChanges,
scorecard,
defaultConfig
)
process.env = OLD_ENV
// note: no Actions context values in unit test env
const expected = `
# Dependency Review
The following issues were found:
* ❌ 3 vulnerable package(s)
* ✅ 0 package(s) with incompatible licenses
* ✅ 0 package(s) with invalid SPDX license definitions
* ✅ 0 package(s) with unknown licenses.
[View full job summary](https://github.com/owner/repo/actions/runs/abc-123-xyz)
`.trim()
expect(minSummary).toEqual(expected)
})
test('only includes "No vulnerabilities or license issues found"-message if both are configured and nothing was found', () => {
summary.addSummaryToSummary(
emptyChanges,
@@ -158,14 +196,10 @@ test('groups dependencies with empty manifest paths together', () => {
emptyScorecard,
defaultConfig
)
summary.addScannedDependencies(changesWithEmptyManifests)
summary.addScannedFiles(changesWithEmptyManifests)
const text = core.summary.stringify()
expect(text).toContain('<summary>Unnamed Manifest</summary>')
expect(text).toContain('castore')
expect(text).toContain('connection')
expect(text).toContain('<summary>python/dist-info/METADATA</summary>')
expect(text).toContain('pygments')
expect(text).toContain('Unnamed Manifest')
expect(text).toContain('python/dist-info/METADATA')
})
test('does not include status section if nothing was found', () => {
Generated Vendored
+1038 -331
View File
File diff suppressed because it is too large Load Diff
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+25 -25
View File
@@ -514,6 +514,31 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@onebeyond/spdx-license-satisfies
MIT
The MIT License
Copyright (c) spdx-satisfies.js contributors
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
aggregate-error
MIT
MIT License
@@ -1621,31 +1646,6 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
spdx-satisfies
MIT
The MIT License
Copyright (c) spdx-satisfies.js contributors
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
tunnel
MIT
The MIT License (MIT)
+105 -49
View File
@@ -1,30 +1,31 @@
{
"name": "dependency-review-action",
"version": "4.3.2",
"version": "4.3.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dependency-review-action",
"version": "4.3.2",
"version": "4.3.4",
"license": "MIT",
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"@octokit/plugin-retry": "^6.0.1",
"@octokit/request-error": "^5.0.1",
"@types/jest": "^29.5.12",
"@onebeyond/spdx-license-satisfies": "^1.0.1",
"ansi-styles": "^6.2.1",
"got": "^14.2.0",
"got": "^14.4.1",
"jest": "^29.7.0",
"octokit": "^3.1.2",
"spdx-expression-parse": "^3.0.1",
"spdx-satisfies": "^5.0.1",
"ts-jest": "^29.1.2",
"yaml": "^2.3.4",
"zod": "^3.22.3"
"zod": "^3.23.8"
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^20",
"@types/spdx-expression-parse": "^3.0.4",
"@types/spdx-satisfies": "^0.1.1",
@@ -1922,6 +1923,16 @@
"resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.1.0.tgz",
"integrity": "sha512-y92CpG4kFFtBBjni8LHoV12IegJ+KFxLgKRengrVjKmGE5XMeCuGvlfRe75lTRrgXaG6XIWJlFpIDTlkoJsU8w=="
},
"node_modules/@onebeyond/spdx-license-satisfies": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@onebeyond/spdx-license-satisfies/-/spdx-license-satisfies-1.0.1.tgz",
"integrity": "sha512-C91zRfMMoWsuFMbzFh95pv7nDtzmGD+4TKbCHJTMgCO8IWPN3LyBVnDDnJd2pM5dokIGamSEIvYlf6HKLBDDPg==",
"dependencies": {
"spdx-compare": "^1.0.0",
"spdx-expression-parse": "^3.0.0",
"spdx-ranges": "^2.0.0"
}
},
"node_modules/@pkgr/core": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz",
@@ -1934,15 +1945,20 @@
"url": "https://opencollective.com/unts"
}
},
"node_modules/@sec-ant/readable-stream": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
"integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="
},
"node_modules/@sindresorhus/is": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.1.0.tgz",
"integrity": "sha512-BuvU07zq3tQ/2SIgBsEuxKYDyDjC0n7Zir52bpHy2xnBbW81+po43aLFPLbeV3HRAheFbGud1qgcqSYfhtHMAg==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.3.1.tgz",
"integrity": "sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==",
"engines": {
"node": ">=16"
},
@@ -2062,6 +2078,7 @@
"version": "29.5.12",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz",
"integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==",
"dev": true,
"dependencies": {
"expect": "^29.0.0",
"pretty-format": "^29.0.0"
@@ -2088,11 +2105,11 @@
}
},
"node_modules/@types/node": {
"version": "20.11.28",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz",
"integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==",
"version": "20.16.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.0.tgz",
"integrity": "sha512-vDxceJcoZhIVh67S568bm1UGZO0DX0hpplJZxzeXMKwIPLn190ec5RRxQ69BKhX44SUGIxxgMdDY557lGLKprQ==",
"dependencies": {
"undici-types": "~5.26.4"
"undici-types": "~6.19.2"
}
},
"node_modules/@types/semver": {
@@ -2799,11 +2816,11 @@
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dependencies": {
"fill-range": "^7.0.1"
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -2883,20 +2900,46 @@
}
},
"node_modules/cacheable-request": {
"version": "10.2.14",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz",
"integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==",
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-12.0.1.tgz",
"integrity": "sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==",
"dependencies": {
"@types/http-cache-semantics": "^4.0.2",
"get-stream": "^6.0.1",
"@types/http-cache-semantics": "^4.0.4",
"get-stream": "^9.0.1",
"http-cache-semantics": "^4.1.1",
"keyv": "^4.5.3",
"keyv": "^4.5.4",
"mimic-response": "^4.0.0",
"normalize-url": "^8.0.0",
"normalize-url": "^8.0.1",
"responselike": "^3.0.0"
},
"engines": {
"node": ">=14.16"
"node": ">=18"
}
},
"node_modules/cacheable-request/node_modules/get-stream": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
"integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
"dependencies": {
"@sec-ant/readable-stream": "^0.4.1",
"is-stream": "^4.0.1"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cacheable-request/node_modules/is-stream": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
"integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/call-bind": {
@@ -4473,9 +4516,9 @@
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -4749,21 +4792,22 @@
}
},
"node_modules/got": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/got/-/got-14.2.0.tgz",
"integrity": "sha512-dBq2KkHcQl3AwPoIWsLsQScCPpUgRulz1qZVthjPYKYOPmYfBnekR3vxecjZbm91Vc3JUGnV9mqFX7B+Fe2quw==",
"version": "14.4.1",
"resolved": "https://registry.npmjs.org/got/-/got-14.4.1.tgz",
"integrity": "sha512-IvDJbJBUeexX74xNQuMIVgCRRuNOm5wuK+OC3Dc2pnSoh1AOmgc7JVj7WC+cJ4u0aPcO9KZ2frTXcqK4W/5qTQ==",
"dependencies": {
"@sindresorhus/is": "^6.1.0",
"@sindresorhus/is": "^6.3.1",
"@szmarczak/http-timer": "^5.0.1",
"cacheable-lookup": "^7.0.0",
"cacheable-request": "^10.2.14",
"cacheable-request": "^12.0.1",
"decompress-response": "^6.0.0",
"form-data-encoder": "^4.0.2",
"get-stream": "^8.0.1",
"http2-wrapper": "^2.2.1",
"lowercase-keys": "^3.0.0",
"p-cancelable": "^4.0.1",
"responselike": "^3.0.0"
"responselike": "^3.0.0",
"type-fest": "^4.19.0"
},
"engines": {
"node": ">=20"
@@ -4783,6 +4827,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/got/node_modules/type-fest": {
"version": "4.20.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.0.tgz",
"integrity": "sha512-MBh+PHUHHisjXf4tlx0CFWoMdjx8zCMLJHOjnV1prABYZFHqtFOyauCIK2/7w4oIfwkF8iNhLtnJEfVY2vn3iw==",
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -6286,11 +6341,12 @@
}
},
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"license": "MIT",
"dependencies": {
"braces": "^3.0.2",
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
@@ -6429,9 +6485,9 @@
}
},
"node_modules/normalize-url": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz",
"integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz",
"integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==",
"engines": {
"node": ">=14.16"
},
@@ -7847,9 +7903,9 @@
"dev": true
},
"node_modules/undici": {
"version": "5.28.3",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz",
"integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==",
"version": "5.28.4",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
@@ -7858,9 +7914,9 @@
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
"version": "6.19.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.6.tgz",
"integrity": "sha512-e/vggGopEfTKSvj4ihnOLTsqhrKRN3LeO6qSN/GxohhuRv8qH9bNQ4B8W7e/vFL+0XTnmHPB4/kegunZGA4Org=="
},
"node_modules/universal-github-app-jwt": {
"version": "1.1.2",
@@ -8154,9 +8210,9 @@
}
},
"node_modules/zod": {
"version": "3.22.4",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz",
"integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==",
"version": "3.23.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
+5 -4
View File
@@ -1,6 +1,6 @@
{
"name": "dependency-review-action",
"version": "4.3.2",
"version": "4.3.4",
"private": true,
"description": "A GitHub Action for Dependency Review",
"main": "lib/main.js",
@@ -29,18 +29,19 @@
"@actions/github": "^6.0.0",
"@octokit/plugin-retry": "^6.0.1",
"@octokit/request-error": "^5.0.1",
"@types/jest": "^29.5.12",
"@onebeyond/spdx-license-satisfies": "^1.0.1",
"ansi-styles": "^6.2.1",
"got": "^14.2.0",
"got": "^14.4.1",
"jest": "^29.7.0",
"octokit": "^3.1.2",
"spdx-expression-parse": "^3.0.1",
"spdx-satisfies": "^5.0.1",
"ts-jest": "^29.1.2",
"yaml": "^2.3.4",
"zod": "^3.22.3"
"zod": "^3.23.8"
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^20",
"@types/spdx-expression-parse": "^3.0.4",
"@types/spdx-satisfies": "^0.1.1",
+1 -1
View File
@@ -143,7 +143,7 @@ async function createSummary(
...licenseIssues.unlicensed
]
summary.addScannedDependencies(allChanges)
summary.addScannedFiles(allChanges)
const text = core.summary.stringify()
await fs.promises.writeFile(path.resolve(tmpDir, fileName), text, {
+3 -5
View File
@@ -5,6 +5,8 @@ import * as retry from '@octokit/plugin-retry'
import {RequestError} from '@octokit/request-error'
import {ConfigurationOptions} from './schemas'
export const MAX_COMMENT_LENGTH = 65536
const retryingOctokit = githubUtils.GitHub.plugin(retry.retry)
const octo = new retryingOctokit(
githubUtils.getOctokitOptions(core.getInput('repo-token', {required: true}))
@@ -14,13 +16,9 @@ const octo = new retryingOctokit(
const COMMENT_MARKER = '<!-- dependency-review-pr-comment-marker -->'
export async function commentPr(
summary: typeof core.summary,
commentContent: string,
config: ConfigurationOptions
): Promise<void> {
const commentContent = summary.stringify()
core.setOutput('comment-content', commentContent)
if (
!(
config.comment_summary_in_pr === 'always' ||
+6 -3
View File
@@ -4,7 +4,8 @@ import YAML from 'yaml'
import * as core from '@actions/core'
import * as z from 'zod'
import {ConfigurationOptions, ConfigurationOptionsSchema} from './schemas'
import {isSPDXValid, octokitClient} from './utils'
import {octokitClient} from './utils'
import {isValid} from './spdx'
type ConfigurationOptionsPartial = Partial<ConfigurationOptions>
@@ -113,10 +114,12 @@ function validateLicenses(
return
}
const invalid_licenses = licenses.filter(license => !isSPDXValid(license))
const invalid_licenses = licenses.filter(license => !isValid(license))
if (invalid_licenses.length > 0) {
throw new Error(`Invalid license(s) in ${key}: ${invalid_licenses}`)
throw new Error(
`Invalid license(s) in ${key}: ${invalid_licenses.join(', ')}`
)
}
}
+5 -4
View File
@@ -11,7 +11,8 @@ export function getRefs(
// The base/head ref from the config take priority, if provided.
if (
context.eventName === 'pull_request' ||
context.eventName === 'pull_request_target'
context.eventName === 'pull_request_target' ||
context.eventName === 'merge_group'
) {
const pull_request = PullRequestSchema.parse(context.payload.pull_request)
base_ref = base_ref || pull_request.base.sha
@@ -22,19 +23,19 @@ export function getRefs(
throw new Error(
'Both a base ref and head ref must be provided, either via the `base_ref`/`head_ref` ' +
'config options, `base-ref`/`head-ref` workflow action options, or by running a ' +
'`pull_request`/`pull_request_target` workflow.'
'`pull_request`/`pull_request_target`/`merge_group` workflow.'
)
} else if (!base_ref) {
throw new Error(
'A base ref must be provided, either via the `base_ref` config option, ' +
'`base-ref` workflow action option, or by running a ' +
'`pull_request`/`pull_request_target` workflow.'
'`pull_request`/`pull_request_target`/`merge_group` workflow.'
)
} else if (!head_ref) {
throw new Error(
'A head ref must be provided, either via the `head_ref` config option, ' +
'`head-ref` workflow action option, or by running a ' +
'or by running a `pull_request`/`pull_request_target` workflow.'
'or by running a `pull_request`/`pull_request_target`/`merge_group` workflow.'
)
}
+17 -12
View File
@@ -1,7 +1,7 @@
import spdxSatisfies from 'spdx-satisfies'
import {Change, Changes} from './schemas'
import {isSPDXValid, octokitClient} from './utils'
import {octokitClient} from './utils'
import {parsePURL} from './purl'
import * as spdx from './spdx'
/**
* Loops through a list of changes, filtering and returning the
@@ -47,7 +47,7 @@ export async function getInvalidLicenseChanges(
const changeAsPackageURL = parsePURL(encodeURI(change.package_url))
// We want to find if the licenseExclussion list contains the PackageURL of the Change
// We want to find if the licenseExclusion list contains the PackageURL of the Change
// If it does, we want to filter it out and therefore return false
// If it doesn't, we want to keep it and therefore return true
if (
@@ -87,15 +87,19 @@ export async function getInvalidLicenseChanges(
} else if (validityCache.get(license) === undefined) {
try {
if (allow !== undefined) {
const found = allow.find(spdxExpression =>
spdxSatisfies(license, spdxExpression)
)
validityCache.set(license, found !== undefined)
if (spdx.isValid(license)) {
const found = spdx.satisfiesAny(license, allow)
validityCache.set(license, found)
} else {
invalidLicenseChanges.unresolved.push(change)
}
} else if (deny !== undefined) {
const found = deny.find(spdxExpression =>
spdxSatisfies(license, spdxExpression)
)
validityCache.set(license, found === undefined)
if (spdx.isValid(license)) {
const found = spdx.satisfiesAny(license, deny)
validityCache.set(license, !found)
} else {
invalidLicenseChanges.unresolved.push(change)
}
}
} catch (err) {
invalidLicenseChanges.unresolved.push(change)
@@ -161,10 +165,11 @@ const setGHLicenses = async (changes: Change[]): Promise<Change[]> => {
return Promise.all(updatedChanges)
}
// Currently Dependency Graph licenses are truncated to 255 characters
// This possibly makes them invalid spdx ids
const truncatedDGLicense = (license: string): boolean =>
license.length === 255 && !isSPDXValid(license)
license.length === 255 && !spdx.isValid(license)
async function groupChanges(
changes: Changes
+33 -6
View File
@@ -22,7 +22,7 @@ import * as summary from './summary'
import {getRefs} from './git-refs'
import {groupDependenciesByManifest} from './utils'
import {commentPr} from './comment-pr'
import {commentPr, MAX_COMMENT_LENGTH} from './comment-pr'
import {getDeniedChanges} from './deny'
async function delay(ms: number): Promise<void> {
@@ -125,9 +125,11 @@ async function run(): Promise<void> {
config.deny_groups
)
const scorecard = await getScorecardLevels(filteredChanges)
// generate informational scorecard entries for all added changes in the PR
const scorecardChanges = getScorecardChanges(changes)
const scorecard = await getScorecardLevels(scorecardChanges)
summary.addSummaryToSummary(
const minSummary = summary.addSummaryToSummary(
vulnerableChanges,
invalidLicenseChanges,
deniedChanges,
@@ -164,9 +166,23 @@ async function run(): Promise<void> {
}
core.setOutput('dependency-changes', JSON.stringify(changes))
summary.addScannedDependencies(changes)
summary.addScannedFiles(changes)
printScannedDependencies(changes)
await commentPr(core.summary, config)
// include full summary in output; Actions will truncate if oversized
let rendered = core.summary.stringify()
core.setOutput('comment-content', rendered)
// if the summary is oversized, replace with minimal version
if (rendered.length >= MAX_COMMENT_LENGTH) {
core.debug(
'The comment was too big for the GitHub API. Falling back on a minimum comment'
)
rendered = minSummary
}
// update the PR comment if needed with the right-sized summary
await commentPr(rendered, config)
} catch (error) {
if (error instanceof RequestError && error.status === 404) {
core.setFailed(
@@ -355,7 +371,7 @@ function printScannedDependencies(changes: Changes): void {
}
function printDeniedDependencies(
changes: Change[],
changes: Changes,
config: ConfigurationOptions
): void {
core.group('Denied', async () => {
@@ -370,6 +386,17 @@ function printDeniedDependencies(
})
}
function getScorecardChanges(changes: Changes): Changes {
const out: Changes = []
for (const change of changes) {
if (change.change_type === 'added') {
out.push(change)
}
}
return out
}
async function createScorecardWarnings(
scorecards: Scorecard,
config: ConfigurationOptions
+56
View File
@@ -0,0 +1,56 @@
import * as spdxlib from '@onebeyond/spdx-license-satisfies'
import parse from 'spdx-expression-parse'
/*
* NOTE: spdx-license-satisfies methods depend on spdx-expression-parse
* which throws errors in the presence of any syntax trouble, unknown
* license tokens, case sensitivity problems etc. to simplify handling
* you should pre-screen inputs to the satisfies* methods using isValid
*/
// accepts a pair of well-formed SPDX expressions. the
// candidate is tested against the constraint
export function satisfies(
candidateExpr: string,
constraintExpr: string
): boolean {
try {
return spdxlib.satisfies(candidateExpr, constraintExpr)
} catch (_) {
return false
}
}
// accepts an SPDX expression and a non-empty list of licenses (not expressions)
export function satisfiesAny(
candidateExpr: string,
licenses: string[]
): boolean {
try {
return spdxlib.satisfiesAny(candidateExpr, licenses)
} catch (_) {
return false
}
}
// accepts an SPDX expression and a non-empty list of licenses (not expressions)
export function satisfiesAll(
candidateExpr: string,
licenses: string[]
): boolean {
try {
return spdxlib.satisfiesAll(candidateExpr, licenses)
} catch (_) {
return false
}
}
// accepts any SPDX expression
export function isValid(spdxExpr: string): boolean {
try {
parse(spdxExpr)
return true
} catch (_) {
return false
}
}
+90 -55
View File
@@ -1,7 +1,7 @@
import * as core from '@actions/core'
import {ConfigurationOptions, Changes, Change, Scorecard} from './schemas'
import {SummaryTableRow} from '@actions/core/lib/summary'
import {InvalidLicenseChanges, InvalidLicenseChangeTypes} from './licenses'
import {Change, Changes, ConfigurationOptions, Scorecard} from './schemas'
import {groupDependenciesByManifest, getManifestsSet, renderUrl} from './utils'
const icons = {
@@ -10,17 +10,25 @@ const icons = {
warning: '⚠️'
}
const MAX_SCANNED_FILES_BYTES = 1048576
// generates the DR report summmary and caches it to the Action's core.summary.
// returns the DR summary string, ready to be posted as a PR comment if the
// final DR report is too large
export function addSummaryToSummary(
vulnerableChanges: Changes,
invalidLicenseChanges: InvalidLicenseChanges,
deniedChanges: Changes,
scorecard: Scorecard,
config: ConfigurationOptions
): void {
): string {
const out: string[] = []
const scorecardWarnings = countScorecardWarnings(scorecard, config)
const licenseIssues = countLicenseIssues(invalidLicenseChanges)
core.summary.addHeading('Dependency Review', 1)
out.push('# Dependency Review')
if (
vulnerableChanges.length === 0 &&
@@ -33,54 +41,69 @@ export function addSummaryToSummary(
config.license_check ? 'license issues' : '',
config.show_openssf_scorecard ? 'OpenSSF Scorecard issues' : ''
]
let msg = ''
if (issueTypes.filter(Boolean).length === 0) {
core.summary.addRaw(`${icons.check} No issues found.`)
msg = `${icons.check} No issues found.`
} else {
core.summary.addRaw(
`${icons.check} No ${issueTypes.filter(Boolean).join(' or ')} found.`
)
msg = `${icons.check} No ${issueTypes.filter(Boolean).join(' or ')} found.`
}
return
core.summary.addRaw(msg)
out.push(msg)
return out.join('\n')
}
core.summary
.addRaw('The following issues were found:')
.addList([
...(config.vulnerability_check
? [
`${checkOrFailIcon(vulnerableChanges.length)} ${
vulnerableChanges.length
} vulnerable package(s)`
]
: []),
...(config.license_check
? [
`${checkOrFailIcon(invalidLicenseChanges.forbidden.length)} ${
invalidLicenseChanges.forbidden.length
} package(s) with incompatible licenses`,
`${checkOrFailIcon(invalidLicenseChanges.unresolved.length)} ${
invalidLicenseChanges.unresolved.length
} package(s) with invalid SPDX license definitions`,
`${checkOrWarnIcon(invalidLicenseChanges.unlicensed.length)} ${
invalidLicenseChanges.unlicensed.length
} package(s) with unknown licenses.`
]
: []),
...(deniedChanges.length > 0
? [
`${checkOrFailIcon(deniedChanges.length)} ${
deniedChanges.length
} package(s) denied.`
]
: []),
...(config.show_openssf_scorecard && scorecardWarnings > 0
? [
`${checkOrWarnIcon(scorecardWarnings)} ${scorecardWarnings ? scorecardWarnings : 'No'} packages with OpenSSF Scorecard issues.`
]
: [])
])
.addRaw('See the Details below.')
const foundIssuesHeader = 'The following issues were found:'
core.summary.addRaw(foundIssuesHeader)
out.push(foundIssuesHeader)
const summaryList: string[] = [
...(config.vulnerability_check
? [
`${checkOrFailIcon(vulnerableChanges.length)} ${
vulnerableChanges.length
} vulnerable package(s)`
]
: []),
...(config.license_check
? [
`${checkOrFailIcon(invalidLicenseChanges.forbidden.length)} ${
invalidLicenseChanges.forbidden.length
} package(s) with incompatible licenses`,
`${checkOrFailIcon(invalidLicenseChanges.unresolved.length)} ${
invalidLicenseChanges.unresolved.length
} package(s) with invalid SPDX license definitions`,
`${checkOrWarnIcon(invalidLicenseChanges.unlicensed.length)} ${
invalidLicenseChanges.unlicensed.length
} package(s) with unknown licenses.`
]
: []),
...(deniedChanges.length > 0
? [
`${checkOrWarnIcon(deniedChanges.length)} ${
deniedChanges.length
} package(s) denied.`
]
: []),
...(config.show_openssf_scorecard && scorecardWarnings > 0
? [
`${checkOrWarnIcon(scorecardWarnings)} ${scorecardWarnings ? scorecardWarnings : 'No'} packages with OpenSSF Scorecard issues.`
]
: [])
]
core.summary.addList(summaryList)
for (const line of summaryList) {
out.push(`* ${line}`)
}
core.summary.addRaw('See the Details below.')
out.push(
`\n[View full job summary](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID})`
)
return out.join('\n')
}
function countScorecardWarnings(
@@ -242,21 +265,33 @@ function formatLicense(license: string | null): string {
return license
}
export function addScannedDependencies(changes: Changes): void {
const dependencies = groupDependenciesByManifest(changes)
const manifests = dependencies.keys()
export function addScannedFiles(changes: Changes): void {
const manifests = Array.from(
groupDependenciesByManifest(changes).keys()
).sort()
const summary = core.summary.addHeading('Scanned Manifest Files', 2)
let sf_size = 0
let trunc_at = -1
for (const manifest of manifests) {
const deps = dependencies.get(manifest)
if (deps) {
const dependencyNames = deps.map(
dependency => `<li>${dependency.name}@${dependency.version}</li>`
)
summary.addDetails(manifest, `<ul>${dependencyNames.join('')}</ul>`)
for (const [index, entry] of manifests.entries()) {
if (sf_size + entry.length >= MAX_SCANNED_FILES_BYTES) {
trunc_at = index
break
}
sf_size += entry.length
}
if (trunc_at >= 0) {
// truncate the manifests list if it will overflow the summary output
manifests.slice(0, trunc_at)
// if there's room between cutoff size and list size, add a warning
const size_diff = MAX_SCANNED_FILES_BYTES - sf_size
if (size_diff < 12) {
manifests.push('(truncated)')
}
}
core.summary.addHeading('Scanned Files', 2).addList(manifests)
}
function snapshotWarningRecommendation(
-10
View File
@@ -1,6 +1,5 @@
import * as core from '@actions/core'
import {Octokit} from 'octokit'
import spdxParse from 'spdx-expression-parse'
import {Changes} from './schemas'
export function groupDependenciesByManifest(
@@ -34,15 +33,6 @@ export function renderUrl(url: string | null, text: string): string {
}
}
export function isSPDXValid(license: string): boolean {
try {
spdxParse(license)
return true
} catch (_) {
return false
}
}
function isEnterprise(): boolean {
const serverUrl = new URL(
process.env['GITHUB_SERVER_URL'] ?? 'https://github.com'
+3 -1
View File
@@ -5,7 +5,9 @@
"outDir": "./lib" /* Redirect output structure to the directory. */,
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"typeRoots": [ "./node_modules/@types", "./types" ],
"types": [ "node", "jest", "spdx-license-satisfies" ]
},
"exclude": ["node_modules"]
}
+16
View File
@@ -0,0 +1,16 @@
declare module '@onebeyond/spdx-license-satisfies' {
export function satisfies(
candidateExpr: string,
constraintExpr: string
): boolean
export function satisfiesAny(
candidateExpr: string,
licenses: string[]
): boolean
export function satisfiesAll(
candidateExpr: string,
licenses: string[]
): boolean
}