Compare commits

...

63 Commits

Author SHA1 Message Date
Federico Builes 6e42c3395a Remove defaults from the recently added fields. 2022-11-11 15:19:46 +01:00
Federico Builes a3074cd699 Merge pull request #327 from actions/adding-extra-options
Updating action.yml to include `*-check` config options
2022-11-11 15:11:20 +01:00
Federico Builes 51a29d6960 Updating action.yml to include *-check config
options.
2022-11-11 14:56:07 +01:00
Federico Builes 235a221cf4 Merge pull request #324 from actions/readme-update
Update the README
2022-11-11 11:27:19 +01:00
Federico Builes 9b3a7f61dd Minor README tweaks. 2022-11-11 11:26:05 +01:00
Federico Builes a4761312ac Add pull_request to the list of events that don't need refs. 2022-11-11 11:23:46 +01:00
Federico Builes 28c7c8c314 Set the correct default for license-check in README. 2022-11-11 11:17:08 +01:00
Federico Builes 9da0fd4871 Merge pull request #325 from actions/dependabot/npm_and_yarn/eslint-plugin-jest-27.1.5
Bump eslint-plugin-jest from 27.1.4 to 27.1.5
2022-11-11 09:00:04 +01:00
Federico Builes fe45fd6645 Merge pull request #326 from actions/dependabot/npm_and_yarn/esbuild-register-3.4.1
Bump esbuild-register from 3.4.0 to 3.4.1
2022-11-11 08:59:46 +01:00
dependabot[bot] c41b9f9cfb Bump esbuild-register from 3.4.0 to 3.4.1
Bumps esbuild-register from 3.4.0 to 3.4.1.

---
updated-dependencies:
- dependency-name: esbuild-register
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-11 01:16:27 +00:00
dependabot[bot] 10c5aa9564 Bump eslint-plugin-jest from 27.1.4 to 27.1.5
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 27.1.4 to 27.1.5.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v27.1.4...v27.1.5)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-11 01:13:55 +00:00
Courtney Claessens 8e5000107a Update README.md 2022-11-10 20:01:11 -05:00
Courtney Claessens 89a074ec7e Update README.md 2022-11-10 19:59:21 -05:00
Courtney Claessens 8d7a4c48ad Update README.md 2022-11-10 19:55:22 -05:00
Courtney Claessens 2f59625b62 reorg the readme 2022-11-10 19:51:20 -05:00
Federico Builes 9e552623cc Merge pull request #323 from actions/dependabot/npm_and_yarn/esbuild-register-3.4.0
Bump esbuild-register from 3.3.3 to 3.4.0
2022-11-10 12:45:45 +01:00
Federico Builes 4108a15bd3 Merge pull request #306 from actions/external-repo-config
Read configuration from external repositories
2022-11-10 11:03:15 +01:00
Federico Builes 5ea8fbfb83 Update docs for config file paths. 2022-11-10 08:18:58 +01:00
Federico Builes c72eb06e71 Update README.md
Co-authored-by: Courtney Claessens <courtneycl@github.com>
2022-11-10 07:59:35 +01:00
Federico Builes aa409fa6cd Update README.md
Co-authored-by: Courtney Claessens <courtneycl@github.com>
2022-11-10 07:59:28 +01:00
Federico Builes 5aaa78ce3c Update README.md
Co-authored-by: Courtney Claessens <courtneycl@github.com>
2022-11-10 07:59:15 +01:00
dependabot[bot] 8d9ea3eb63 Bump esbuild-register from 3.3.3 to 3.4.0
Bumps esbuild-register from 3.3.3 to 3.4.0.

---
updated-dependencies:
- dependency-name: esbuild-register
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-10 01:11:37 +00:00
Federico Builes 59a4f4c4ba Fixing typo in README.md 2022-11-09 13:24:07 +01:00
Federico Builes bf8cfe8b38 Linting, adding dist files. 2022-11-09 13:22:33 +01:00
Federico Builes ae538ebe32 Linting and whitespace. Smol rename. 2022-11-09 13:17:12 +01:00
Federico Builes b4126ce983 Shuffle things around. 2022-11-09 13:16:53 +01:00
Federico Builes 418ae59d51 Replace TODO with instructions for getting PAT. 2022-11-08 17:51:31 +01:00
Federico Builes c38007a979 Don't abbreviate repo in docs.
In general let's try not to use abbreviations in public
documentation.
2022-11-08 17:45:23 +01:00
cnagadya ebe5527e72 Fix readme typo 2022-11-08 11:23:48 +00:00
cnagadya 1589654682 Add dist changes 2022-11-08 11:16:48 +00:00
cnagadya f0ff0b670a Rename config token > external-repo-token 2022-11-08 11:16:26 +00:00
cnagadya 336da03de2 Update empty allow-licenses tests 2022-11-08 11:15:36 +00:00
cnagadya 78565a954f Dont merge config lists
Co-authored-by: Henri Maurer<hmaurer@github.com>
Co-authored-by: Federico Builes<febuiles@github.com>
2022-11-08 10:52:30 +00:00
cnagadya 3c73a622ba Fix config-file tests 2022-11-08 09:53:36 +00:00
Federico Builes 7a42af0f2f Merge pull request #320 from actions/dependabot/npm_and_yarn/eslint-plugin-jest-27.1.4
Bump eslint-plugin-jest from 27.1.3 to 27.1.4
2022-11-08 10:40:36 +01:00
dependabot[bot] abfd4a1fc7 Bump eslint-plugin-jest from 27.1.3 to 27.1.4
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 27.1.3 to 27.1.4.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v27.1.3...v27.1.4)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 09:39:22 +00:00
Federico Builes 40e460b464 Merge pull request #316 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.42.1
Bump @typescript-eslint/parser from 5.42.0 to 5.42.1
2022-11-08 10:38:41 +01:00
dependabot[bot] 9f1bc9b354 Bump @typescript-eslint/parser from 5.42.0 to 5.42.1
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.42.0 to 5.42.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.42.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 09:38:34 +00:00
Federico Builes 774bd6c1d5 Merge pull request #318 from actions/dependabot/npm_and_yarn/eslint-plugin-github-4.4.1
Bump eslint-plugin-github from 4.4.0 to 4.4.1
2022-11-08 10:37:41 +01:00
Federico Builes f7686f8c21 Merge pull request #317 from actions/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.42.1
Bump @typescript-eslint/eslint-plugin from 5.42.0 to 5.42.1
2022-11-08 10:36:16 +01:00
dependabot[bot] 688e92b5e5 Bump eslint-plugin-github from 4.4.0 to 4.4.1
Bumps [eslint-plugin-github](https://github.com/github/eslint-plugin-github) from 4.4.0 to 4.4.1.
- [Release notes](https://github.com/github/eslint-plugin-github/releases)
- [Commits](https://github.com/github/eslint-plugin-github/compare/v4.4.0...v4.4.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-github
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 07:35:47 +00:00
Federico Builes 7ce779229f Merge pull request #319 from actions/dependabot/npm_and_yarn/eslint-8.27.0
Bump eslint from 8.26.0 to 8.27.0
2022-11-08 08:34:38 +01:00
dependabot[bot] 543eecb644 Bump eslint from 8.26.0 to 8.27.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.26.0 to 8.27.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.26.0...v8.27.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 01:17:47 +00:00
dependabot[bot] a7ec2eb771 Bump @typescript-eslint/eslint-plugin from 5.42.0 to 5.42.1
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.42.0 to 5.42.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.42.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 01:17:25 +00:00
cnagadya 13455c7175 Merge array config options 2022-11-07 17:57:05 +00:00
cnagadya 6d941b396a Fix inconsistencies due to zod defaults / partials mixup 2022-11-07 17:08:00 +00:00
cnagadya 49ed3f2876 Merge lists in configs instead of overwritting them 2022-11-07 12:33:54 +00:00
cnagadya b55cddb69d Use config-file for both remote and local config-files 2022-11-07 12:12:03 +00:00
cnagadya dcdeb7de77 Remove redundant skips
Co-authored-by: Federico Builes <febuiles@github.com>
2022-11-04 16:12:05 +00:00
cnagadya b4a2fbfa16 Complete functionality for handling remote config file 2022-11-04 14:51:41 +00:00
cnagadya 97e5a607ba Handle getContent response as is
Co-authored-by: Henri Maurer <hmaurer@github.com>
2022-11-04 10:08:00 +00:00
cnagadya 3b410dc4ad Load remote config file 2022-11-04 09:05:45 +00:00
Federico Builes 683cbc4872 Merge branch 'main' into external-repo-config 2022-11-01 08:11:26 +01:00
Federico Builes 2f696d8c7a Merge pull request #314 from actions/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-5.42.0
Bump @typescript-eslint/eslint-plugin from 5.41.0 to 5.42.0
2022-11-01 08:10:28 +01:00
dependabot[bot] 1a9033d563 Bump @typescript-eslint/eslint-plugin from 5.41.0 to 5.42.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.41.0 to 5.42.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.42.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-01 07:10:21 +00:00
Federico Builes ad6e320da1 Merge pull request #313 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.42.0
Bump @typescript-eslint/parser from 5.41.0 to 5.42.0
2022-11-01 08:09:22 +01:00
dependabot[bot] 3d86825394 Bump @typescript-eslint/parser from 5.41.0 to 5.42.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.41.0 to 5.42.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.42.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-01 01:49:12 +00:00
Federico Builes 10dc05ba09 Merge pull request #311 from ericcornelissen/308-disable-license-or-vuln
Add `license-check` and `vulnerability-check` inputs
2022-10-31 07:56:37 +01:00
Federico Builes 04f48dec81 Update __tests__/config.test.ts 2022-10-31 07:55:17 +01:00
Federico Builes bb5c0c7ca0 Merge pull request #312 from actions/dependabot/npm_and_yarn/types/node-16.18.3
Bump @types/node from 16.18.2 to 16.18.3
2022-10-31 06:42:09 +01:00
dependabot[bot] 2d7d700469 Bump @types/node from 16.18.2 to 16.18.3
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 16.18.2 to 16.18.3.
- [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-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-31 01:33:50 +00:00
Federico Builes 9760f87258 Fix config-file description in action.yml 2022-10-21 17:38:18 +02:00
Federico Builes 74c047086c Adding README and action.yml for external config files. 2022-10-21 17:34:20 +02:00
14 changed files with 687 additions and 641 deletions
+43 -205
View File
@@ -5,11 +5,11 @@ raise an error if any vulnerabilities or invalid licenses are being introduced.
The action is available for all public repositories, as well as private repositories that have GitHub Advanced Security licensed.
You can see the results on the job logs
You can see the results on the job logs:
<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">
or on the job summary
or on the job summary:
<img src="https://user-images.githubusercontent.com/7847935/182871416-50332bbb-b279-4621-a136-ca72a4314301.png">
@@ -33,7 +33,7 @@ jobs:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v2
uses: actions/dependency-review-action@v3
```
### GitHub Enterprise Server
@@ -59,163 +59,34 @@ jobs:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v2
uses: actions/dependency-review-action@v3
```
## Configuration
## Configuration options
Configure this action by either using an external configuration file,
or by inlining these options in your workflow file.
Configure this action by either inlining these options in your workflow file, or by using an external configuration file. All configuration options are optional.
## Configuration Options
| Option | Usage | Possible values | Default value |
|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|---------------|
| `fail-on-severity` | Defines the threshold for the level of severity. The action will fail on any pull requests that introduce vulnerabilities of the specified severity level or higher. | `low`, `moderate`, `high`, `critical` | `low` |
| `allow-licenses`* | Contains a list of allowed licenses. The action will fail on pull requests that introduce dependencies with licenses that do not match the list. | Any [SPDX-compliant identifier(s)](https://spdx.org/licenses/) | none |
| `deny-licenses`* | Contains a list of prohibited licenses. The action will fail on pull requests that introduce dependencies with licenses that match the list. | Any [SPDX-compliant identifier(s)](https://spdx.org/licenses/) | none |
| `fail-on-scopes`† | Contains a list of strings of the build environments you want to support. The action will fail on pull requests that introduce vulnerabilities in the scopes that match the list. |`runtime`, `development`, `unknown` | `runtime` |
| `allow-ghsas` | Contains a list of GitHub Advisory Database IDs that can be skipped during detection. | Any GHSAs from the [GitHub Advisory Database](https://github.com/advisories) | none |
| `license-check` | Enable or disable the license check performed by the action. | `true`, `false` | `true` |
| `vulnerability-check` | Enable or disable the vulnerability check performed by the action. | `true`, `false` | `true` |
| `base-ref`/`head-ref` | Provide custom git references for the git base/head when performing the comparison check. This is only used for event types other than `pull_request` and `pull_request_target`. | Any valid git ref(s) in your project | none |
### config-file
*not supported for use with GitHub Enterprise Server
A string representing the path to an external configuration file. By
default external configuration files are not used.
†will be supported with GitHub Enterprise Server 3.8
**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 that comply with the expressions in this list. See "[Licenses](https://github.com/actions/dependency-review-action#licenses)".
**Possible values**: A list of of [SPDX-compliant license identifiers](https://spdx.org/licenses/).
**Inline example**: `allow-licenses: BSD-3-Clause, LGPL-2.1 OR MIT OR BSD-3-Clause`
**YAML example**:
```yaml
allow-licenses:
- BSD-3-Clause
- LGPL-2.1
- MIT
- BSD-3-Clause
```
### 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 valid set of [SPDX licenses](https://spdx.org/licenses/).
**Inline example**: `deny-licenses: LGPL-2.0, GPL-2.0+ WITH Bison-exception-2.2`
**YAML example**:
```yaml
deny-licenses:
- LGPL-2.0
- GPL-2.0+ WITH Bison-exception-2.2
```
### allow-ghsas
Add a custom list of GitHub Advisory IDs that can be skipped during detection.
**Possible values**: Any valid advisory GHSA ids.
**Inline example**: `allow-ghsas: GHSA-abcd-1234-5679, GHSA-efgh-1234-5679`
**YAML example**:
```yaml
allow-ghsas:
- GHSA-abcd-1234-5679
- GHSA-efgh-1234-5679
```
### license-check/vulnerability-check
Disable the license checks or vulnerability checks performed by this Action.
You can't disable both checks.
**Possible values**: `true` or `false`
**Example**:
```yaml
license-check: true
vulnerability-check: false
```
### 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:
You can pass options to the Dependency Review GitHub Action using your workflow file.
#### Example
```yaml
name: 'Dependency Review'
@@ -229,7 +100,7 @@ jobs:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: Dependency Review
uses: actions/dependency-review-action@v2
uses: actions/dependency-review-action@v3
with:
fail-on-severity: moderate
@@ -237,71 +108,41 @@ jobs:
deny-licenses: LGPL-2.0, BSD-2-Clause
```
### Vulnerability Severity
### Configuration File
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`.
You can use an external configuration file to specify the settings for this action. It can be a local file or a file in an external repository. Refer to the following options for the specification.
This example will only fail on pull requests with `critical` and `high` vulnerabilities:
| Option | Usage | Possible values |
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| `config-file` | A path to a file in the current repository or an external repository. Use this syntax for external files: `OWNER/REPOSITORY/FILENAME@BRANCH` | **Local file**: `./.github/dependency-review-config.yml` <br> **External repo**: `github/octorepo/dependency-review-config.yml@main` |
| `external-repo-token` | Specifies a token for fetching the configuration file if the file resides in a private external repository. Create a token in [developer settings](https://github.com/settings/tokens). | Any token with `read` permissions to the repository hosting the config file. |
#### Example
Start by specifying that you will be using an external configuration file:
```yaml
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
fail-on-severity: high
config-file: './.github/dependency-review-config.yml'
```
### Dependency Scoping
By default the action will only fail on `runtime` dependencies that have vulnerabilities or unacceptable licenses, ignoring `development` dependencies. You can override this behavior with the `fail-on-scopes` option, which will allow you to list the specific dependency scopes you care about. The possible values are: `unknown`, `runtime`, and `development`. Note: Filtering by scope will not be supported on Enterprise Server just yet, as the REST API's introduction of `scope` will be released in an upcoming Enterprise Server version. We will treat all dependencies on Enterprise Server as having a `runtime` scope and thus will not be filtered away.
And then create the file in the path you just specified:
```yaml
- name: Dependency Review
uses: actions/dependency-review-action@v2
with:
fail-on-scopes: runtime, development
```
### 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. These options are not supported on Enterprise Server.
You can use the [Licenses
API](https://docs.github.com/en/rest/licenses) to see the full list of
supported licenses. Use [SPDX licenses](https://spdx.org/licenses/)
to filter the licenses. 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+
fail-on-severity: 'critical'
allow-licenses:
- 'GPL-3.0'
- 'BSD-3-Clause'
- 'MIT'
```
### Considerations
- Checking for licenses is not supported on Enterprise Server.
- 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**.
- The action will only accept one of the two `license` parameters; an error will be raised if you provide both.
- 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**.
## Blocking pull requests
@@ -309,14 +150,11 @@ The Dependency Review GitHub Action check will only block a pull request from be
## Getting help
If you have bug reports, questions or suggestions please [create a new
issue](https://github.com/actions/dependency-review-action/issues/new/choose).
If you have bug reports, questions or suggestions please [create a new issue](https://github.com/actions/dependency-review-action/issues/new/choose).
## Contributing
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.
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.
## License
+80 -71
View File
@@ -1,5 +1,5 @@
import {expect, test, beforeEach} from '@jest/globals'
import {readConfig, readConfigFile} from '../src/config'
import {readConfig} from '../src/config'
import {getRefs} from '../src/git-refs'
import * as Utils from '../src/utils'
@@ -39,43 +39,53 @@ beforeEach(() => {
})
test('it defaults to low severity', async () => {
const options = readConfig()
expect(options.fail_on_severity).toEqual('low')
const config = await readConfig()
expect(config.fail_on_severity).toEqual('low')
})
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'])
const config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
expect(config.allow_licenses).toEqual(['BSD', 'GPL 2'])
})
test('it defaults to empty allow/deny lists ', async () => {
const options = readConfig()
const config = await readConfig()
expect(options.allow_licenses).toEqual(undefined)
expect(options.deny_licenses).toEqual(undefined)
expect(config.allow_licenses).toEqual(undefined)
expect(config.deny_licenses).toEqual(undefined)
})
test('it raises an error if both an allow and denylist are specified', async () => {
setInput('allow-licenses', 'MIT')
setInput('deny-licenses', 'BSD')
expect(() => readConfig()).toThrow()
await expect(readConfig()).rejects.toThrow(
'You cannot specify both allow-licenses and deny-licenses'
)
})
test('it raises an error if an empty allow list is specified', async () => {
setInput('config-file', './__tests__/fixtures/config-empty-allow-sample.yml')
await expect(readConfig()).rejects.toThrow(
'You should provide at least one license in allow-licenses'
)
})
test('it raises an error when given an unknown severity', async () => {
setInput('fail-on-severity', 'zombies')
expect(() => readConfig()).toThrow()
await expect(readConfig()).rejects.toThrow(/received 'zombies'/)
})
test('it uses the given refs when the event is not a pull request', async () => {
setInput('base-ref', 'a-custom-base-ref')
setInput('head-ref', 'a-custom-head-ref')
const refs = getRefs(readConfig(), {
const refs = getRefs(await readConfig(), {
payload: {},
eventName: 'workflow_dispatch'
})
@@ -84,9 +94,9 @@ test('it uses the given refs when the event is not a pull request', async () =>
})
test('it raises an error when no refs are provided and the event is not a pull request', async () => {
const options = readConfig()
const config = await readConfig()
expect(() =>
getRefs(options, {
getRefs(config, {
payload: {},
eventName: 'workflow_dispatch'
})
@@ -94,133 +104,132 @@ test('it raises an error when no refs are provided and the event is not a pull r
})
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'])
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml')
const config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
expect(config.allow_licenses).toEqual(['BSD', 'GPL 2'])
})
test('raises an error when the the config file was not found', async () => {
expect(() => readConfigFile('fixtures/i-dont-exist')).toThrow()
setInput('config-file', 'fixtures/i-dont-exist')
await expect(readConfig()).rejects.toThrow(/Unable to fetch config file/)
})
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')
let config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
setInput('base-ref', 'a-custom-base-ref')
options = readConfig()
expect(options.base_ref).toEqual('a-custom-base-ref')
config = await readConfig()
expect(config.base_ref).toEqual('a-custom-base-ref')
})
test('in case of conflicts, the external config is the source of truth', async () => {
test('in case of conflicts, the inline config is the source of truth', async () => {
setInput('fail-on-severity', 'low')
setInput('config-file', './__tests__/fixtures/config-allow-sample.yml') // this will set fail-on-severity to 'critical'
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')
const config = await readConfig()
expect(config.fail_on_severity).toEqual('low')
})
test('it uses the default values when loading external files', async () => {
setInput('config-file', './__tests__/fixtures/no-licenses-config.yml')
let options = readConfig()
expect(options.allow_licenses).toEqual(undefined)
expect(options.deny_licenses).toEqual(undefined)
let config = await readConfig()
expect(config.allow_licenses).toEqual(undefined)
expect(config.deny_licenses).toEqual(undefined)
setInput('config-file', './__tests__/fixtures/license-config-sample.yml')
options = readConfig()
expect(options.fail_on_severity).toEqual('low')
config = await readConfig()
expect(config.fail_on_severity).toEqual('low')
})
test('it accepts an external configuration filename', async () => {
setInput('config-file', './__tests__/fixtures/no-licenses-config.yml')
const options = readConfig()
expect(options.fail_on_severity).toEqual('critical')
const config = await readConfig()
expect(config.fail_on_severity).toEqual('critical')
})
test('it raises an error when given an unknown severity in an external config file', async () => {
setInput('config-file', './__tests__/fixtures/invalid-severity-config.yml')
expect(() => readConfig()).toThrow()
await expect(readConfig()).rejects.toThrow()
})
test('it defaults to runtime scope', async () => {
const options = readConfig()
expect(options.fail_on_scopes).toEqual(['runtime'])
const config = await readConfig()
expect(config.fail_on_scopes).toEqual(['runtime'])
})
test('it parses custom scopes preference', async () => {
setInput('fail-on-scopes', 'runtime, development')
let options = readConfig()
expect(options.fail_on_scopes).toEqual(['runtime', 'development'])
let config = await readConfig()
expect(config.fail_on_scopes).toEqual(['runtime', 'development'])
clearInputs()
setInput('fail-on-scopes', 'development')
options = readConfig()
expect(options.fail_on_scopes).toEqual(['development'])
config = await readConfig()
expect(config.fail_on_scopes).toEqual(['development'])
})
test('it raises an error when given invalid scope', async () => {
setInput('fail-on-scopes', 'runtime, zombies')
expect(() => readConfig()).toThrow()
await expect(readConfig()).rejects.toThrow(/received 'zombies'/)
})
test('it defaults to an empty GHSA allowlist', async () => {
const options = readConfig()
expect(options.allow_ghsas).toEqual(undefined)
const config = await readConfig()
expect(config.allow_ghsas).toEqual([])
})
test('it successfully parses GHSA allowlist', async () => {
setInput('allow-ghsas', 'GHSA-abcd-1234-5679, GHSA-efgh-1234-5679')
const options = readConfig()
expect(options.allow_ghsas).toEqual([
const config = await readConfig()
expect(config.allow_ghsas).toEqual([
'GHSA-abcd-1234-5679',
'GHSA-efgh-1234-5679'
])
})
test('it defaults to checking licenses', async () => {
const options = readConfig()
expect(options.license_check).toBe(true)
const config = await readConfig()
expect(config.license_check).toBe(true)
})
test('it parses the license-check input', async () => {
setInput('license-check', 'false')
let options = readConfig()
expect(options.license_check).toEqual(false)
let config = await readConfig()
expect(config.license_check).toEqual(false)
clearInputs()
setInput('license-check', 'true')
options = readConfig()
expect(options.license_check).toEqual(true)
config = await readConfig()
expect(config.license_check).toEqual(true)
})
test('it defaults to checking vulnerabilities', async () => {
const options = readConfig()
expect(options.vulnerability_check).toBe(true)
const config = await readConfig()
expect(config.vulnerability_check).toBe(true)
})
test('it parses the vulnerability-check input', async () => {
setInput('vulnerability-check', 'false')
let options = readConfig()
expect(options.vulnerability_check).toEqual(false)
let config = await readConfig()
expect(config.vulnerability_check).toEqual(false)
clearInputs()
setInput('vulnerability-check', 'true')
options = readConfig()
expect(options.vulnerability_check).toEqual(true)
config = await readConfig()
expect(config.vulnerability_check).toEqual(true)
})
test('it is not impossible to disable both checks', async () => {
test('it is not possible to disable both checks', async () => {
setInput('license-check', 'false')
setInput('vulnerability-check', 'false')
expect(() => {
readConfig()
}).toThrow("Can't disable both license-check and vulnerability-check")
await expect(readConfig()).rejects.toThrow(
/Can't disable both license-check and vulnerability-check/
)
})
describe('licenses that are not valid SPDX licenses', () => {
@@ -230,15 +239,15 @@ describe('licenses that are not valid SPDX licenses', () => {
test('it raises an error for invalid licenses in allow-licenses', async () => {
setInput('allow-licenses', ' BSD, GPL 2')
expect(() => {
readConfig()
}).toThrow('Invalid license(s) in allow-licenses: BSD, GPL 2')
await expect(readConfig()).rejects.toThrow(
'Invalid license(s) in allow-licenses: BSD, GPL 2'
)
})
test('it raises an error for invalid licenses in deny-licenses', async () => {
setInput('deny-licenses', ' BSD, GPL 2')
expect(() => {
readConfig()
}).toThrow('Invalid license(s) in deny-licenses: BSD, GPL 2')
await expect(readConfig()).rejects.toThrow(
'Invalid license(s) in deny-licenses: BSD, GPL 2'
)
})
})
@@ -0,0 +1,2 @@
fail_on_severity: critical
allow_licenses: []
-11
View File
@@ -99,17 +99,6 @@ test('it adds license inside the deny list to forbidden changes', async () => {
expect(forbidden.length).toEqual(1)
})
// 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 adds all licenses to forbidden changes when allow is provided an empty array', async () => {
const changes: Changes = [npmChange, rubyChange]
let {forbidden} = await getInvalidLicenseChanges(changes, {
allow: [],
deny: ['BSD']
})
expect(forbidden.length).toBe(2)
})
test('it does not add license outside the allow list to forbidden changes if it is in removed changes', async () => {
const changes: Changes = [
{...npmChange, change_type: 'removed'},
+10 -1
View File
@@ -21,7 +21,7 @@ inputs:
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.
description: A path 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")
@@ -32,6 +32,15 @@ inputs:
allow-ghsas:
description: Comma-separated list of allowed Github Advisory IDs (e.g. "GHSA-abcd-1234-5679, GHSA-efgh-1234-5679")
required: false
external-repo-token:
description: A token for fetching external configuration file if it lives in another repository. It is required if the repository is private
required: false
license-check:
description: A boolean to determine if license checks should be performed
required: false
vulnerability-check:
description: A boolean to determine if vulnerability checks should be performed
required: false
runs:
using: 'node16'
main: 'dist/index.js'
Generated Vendored
+239 -119
View File
@@ -107,29 +107,6 @@ exports.getRefs = getRefs;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
@@ -144,9 +121,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getInvalidLicenseChanges = void 0;
const core = __importStar(__nccwpck_require__(2186));
const spdx_satisfies_1 = __importDefault(__nccwpck_require__(4424));
const octokit_1 = __nccwpck_require__(7467);
const utils_1 = __nccwpck_require__(918);
/**
* Loops through a list of changes, filtering and returning the
@@ -205,11 +180,11 @@ function getInvalidLicenseChanges(changes, licenses) {
exports.getInvalidLicenseChanges = getInvalidLicenseChanges;
const fetchGHLicense = (owner, repo) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
const octokit = new octokit_1.Octokit({
auth: core.getInput('repo-token', { required: true })
});
try {
const response = yield octokit.rest.licenses.getForRepo({ owner, repo });
const response = yield (0, utils_1.octokitClient)().rest.licenses.getForRepo({
owner,
repo
});
return (_b = (_a = response.data.license) === null || _a === void 0 ? void 0 : _a.spdx_id) !== null && _b !== void 0 ? _b : null;
}
catch (_) {
@@ -350,7 +325,7 @@ const utils_1 = __nccwpck_require__(918);
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const config = (0, config_1.readConfig)();
const config = yield (0, config_1.readConfig)();
const refs = (0, git_refs_1.getRefs)(config, github.context);
const changes = yield dependencyGraph.compare({
owner: github.context.repo.owner,
@@ -557,17 +532,36 @@ exports.ConfigurationOptionsSchema = z
.object({
fail_on_severity: exports.SeveritySchema,
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).default([]),
deny_licenses: z.array(z.string()).default([]),
allow_licenses: z.array(z.string()).optional(),
deny_licenses: z.array(z.string()).optional(),
allow_ghsas: z.array(z.string()).default([]),
license_check: z.boolean().default(true),
vulnerability_check: z.boolean().default(true),
config_file: z.string().optional().default('false'),
base_ref: z.string(),
head_ref: z.string()
config_file: z.string().optional(),
base_ref: z.string().optional(),
head_ref: z.string().optional()
})
.partial()
.refine(obj => !(obj.allow_licenses && obj.deny_licenses), 'Your workflow file has both an allow_licenses list and deny_licenses list, but you can only set one or the other.');
.superRefine((config, context) => {
if (config.allow_licenses && config.deny_licenses) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: 'You cannot specify both allow-licenses and deny-licenses'
});
}
if (config.allow_licenses && config.allow_licenses.length < 1) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: 'You should provide at least one license in allow-licenses'
});
}
if (config.license_check === false &&
config.vulnerability_check === false) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: "Can't disable both license-check and vulnerability-check"
});
}
});
exports.ChangesSchema = z.array(exports.ChangeSchema);
@@ -741,11 +735,36 @@ exports.addScannedDependencies = addScannedDependencies;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isSPDXValid = exports.renderUrl = exports.getManifestsSet = exports.groupDependenciesByManifest = void 0;
exports.octokitClient = exports.isSPDXValid = exports.renderUrl = exports.getManifestsSet = exports.groupDependenciesByManifest = void 0;
const core = __importStar(__nccwpck_require__(2186));
const octokit_1 = __nccwpck_require__(7467);
const spdx_expression_parse_1 = __importDefault(__nccwpck_require__(1620));
function groupDependenciesByManifest(changes) {
var _a;
@@ -783,6 +802,17 @@ function isSPDXValid(license) {
}
}
exports.isSPDXValid = isSPDXValid;
function octokitClient(token = 'repo-token', required = true) {
const opts = {};
// auth is only added if token is present. For remote config files in public
// repos the token is optional, so it could be undefined.
const auth = core.getInput(token, { required });
if (auth !== undefined) {
opts['auth'] = auth;
}
return new octokit_1.Octokit(opts);
}
exports.octokitClient = octokitClient;
/***/ }),
@@ -27397,11 +27427,20 @@ var __importStar = (this && this.__importStar) || function (mod) {
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.readConfigFile = exports.readInlineConfig = exports.readConfig = void 0;
exports.readConfig = void 0;
const fs = __importStar(__nccwpck_require__(7147));
const path_1 = __importDefault(__nccwpck_require__(1017));
const yaml_1 = __importDefault(__nccwpck_require__(4083));
@@ -27409,6 +27448,43 @@ const core = __importStar(__nccwpck_require__(2186));
const z = __importStar(__nccwpck_require__(3301));
const schemas_1 = __nccwpck_require__(1129);
const utils_1 = __nccwpck_require__(1314);
function readConfig() {
return __awaiter(this, void 0, void 0, function* () {
const inlineConfig = readInlineConfig();
const configFile = getOptionalInput('config-file');
if (configFile !== undefined) {
const externalConfig = yield readConfigFile(configFile);
return schemas_1.ConfigurationOptionsSchema.parse(Object.assign(Object.assign({}, externalConfig), inlineConfig));
}
return schemas_1.ConfigurationOptionsSchema.parse(inlineConfig);
});
}
exports.readConfig = readConfig;
function readInlineConfig() {
const fail_on_severity = getOptionalInput('fail-on-severity');
const fail_on_scopes = parseList(getOptionalInput('fail-on-scopes'));
const allow_licenses = parseList(getOptionalInput('allow-licenses'));
const deny_licenses = parseList(getOptionalInput('deny-licenses'));
const allow_ghsas = parseList(getOptionalInput('allow-ghsas'));
const license_check = getOptionalBoolean('license-check');
const vulnerability_check = getOptionalBoolean('vulnerability-check');
const base_ref = getOptionalInput('base-ref');
const head_ref = getOptionalInput('head-ref');
validateLicenses('allow-licenses', allow_licenses);
validateLicenses('deny-licenses', deny_licenses);
const keys = {
fail_on_severity,
fail_on_scopes,
allow_licenses,
deny_licenses,
allow_ghsas,
license_check,
vulnerability_check,
base_ref,
head_ref
};
return Object.fromEntries(Object.entries(keys).filter(([_, value]) => value !== undefined));
}
function getOptionalBoolean(name) {
const value = core.getInput(name);
return value.length > 0 ? core.getBooleanInput(name) : undefined;
@@ -27434,85 +27510,74 @@ function validateLicenses(key, licenses) {
throw new Error(`Invalid license(s) in ${key}: ${invalid_licenses.join(', ')}`);
}
}
function readConfig() {
const externalConfig = getOptionalInput('config-file');
if (externalConfig !== undefined) {
const config = readConfigFile(externalConfig);
// the reasoning behind reading the inline config when an external
// config file is provided is that we still want to allow users to
// pass inline options in the presence of an external config file.
const inlineConfig = readInlineConfig();
// the external config takes precedence
return Object.assign({}, inlineConfig, config);
}
else {
return readInlineConfig();
}
}
exports.readConfig = readConfig;
function readInlineConfig() {
const fail_on_severity = schemas_1.SeveritySchema.parse(getOptionalInput('fail-on-severity'));
const fail_on_scopes = z
.array(z.enum(schemas_1.SCOPES))
.default(['runtime'])
.parse(parseList(getOptionalInput('fail-on-scopes')));
const allow_licenses = parseList(getOptionalInput('allow-licenses'));
const deny_licenses = parseList(getOptionalInput('deny-licenses'));
if (allow_licenses !== undefined && deny_licenses !== undefined) {
throw new Error("Can't specify both allow_licenses and deny_licenses");
}
validateLicenses('allow-licenses', allow_licenses);
validateLicenses('deny-licenses', deny_licenses);
const allow_ghsas = parseList(getOptionalInput('allow-ghsas'));
const license_check = z
.boolean()
.default(true)
.parse(getOptionalBoolean('license-check'));
const vulnerability_check = z
.boolean()
.default(true)
.parse(getOptionalBoolean('vulnerability-check'));
if (license_check === false && vulnerability_check === false) {
throw new Error("Can't disable both license-check and vulnerability-check");
}
const base_ref = getOptionalInput('base-ref');
const head_ref = getOptionalInput('head-ref');
return {
fail_on_severity,
fail_on_scopes,
allow_licenses,
deny_licenses,
allow_ghsas,
license_check,
vulnerability_check,
base_ref,
head_ref
};
}
exports.readInlineConfig = readInlineConfig;
function readConfigFile(filePath) {
let data;
return __awaiter(this, void 0, void 0, function* () {
// match a remote config (e.g. 'owner/repo/filepath@someref')
const format = new RegExp('(?<owner>[^/]+)/(?<repo>[^/]+)/(?<path>[^@]+)@(?<ref>.*)');
let data;
const pieces = format.exec(filePath);
try {
if ((pieces === null || pieces === void 0 ? void 0 : pieces.groups) && pieces.length === 5) {
data = yield getRemoteConfig({
owner: pieces.groups.owner,
repo: pieces.groups.repo,
path: pieces.groups.path,
ref: pieces.groups.ref
});
}
else {
data = fs.readFileSync(path_1.default.resolve(filePath), 'utf-8');
}
return parseConfigFile(data);
}
catch (error) {
core.debug(error);
throw new Error('Unable to fetch config file');
}
});
}
function parseConfigFile(configData) {
try {
data = fs.readFileSync(path_1.default.resolve(filePath), 'utf-8');
const data = yaml_1.default.parse(configData);
for (const key of Object.keys(data)) {
if (key === 'allow-licenses' || key === 'deny-licenses') {
validateLicenses(key, data[key]);
}
// get rid of the ugly dashes from the actions conventions
if (key.includes('-')) {
data[key.replace(/-/g, '_')] = data[key];
delete data[key];
}
}
return data;
}
catch (error) {
throw error;
}
data = yaml_1.default.parse(data);
for (const key of Object.keys(data)) {
if (key === 'allow-licenses' || key === 'deny-licenses') {
validateLicenses(key, data[key]);
}
// get rid of the ugly dashes from the actions conventions
if (key.includes('-')) {
data[key.replace(/-/g, '_')] = data[key];
delete data[key];
}
}
const values = schemas_1.ConfigurationOptionsSchema.parse(data);
return values;
}
exports.readConfigFile = readConfigFile;
function getRemoteConfig(configOpts) {
return __awaiter(this, void 0, void 0, function* () {
try {
const { data } = yield (0, utils_1.octokitClient)('external-repo-token', false).rest.repos.getContent({
mediaType: {
format: 'raw'
},
owner: configOpts.owner,
repo: configOpts.repo,
path: configOpts.path,
ref: configOpts.ref
});
// When using mediaType.format = 'raw', the response.data is a string
// but this is not reflected in the return type of getContent, so we're
// casting the return value to a string.
return z.string().parse(data);
}
catch (error) {
core.debug(error);
throw new Error('Error fetching remote config file');
}
});
}
/***/ }),
@@ -27658,17 +27723,36 @@ exports.ConfigurationOptionsSchema = z
.object({
fail_on_severity: exports.SeveritySchema,
fail_on_scopes: z.array(z.enum(exports.SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).default([]),
deny_licenses: z.array(z.string()).default([]),
allow_licenses: z.array(z.string()).optional(),
deny_licenses: z.array(z.string()).optional(),
allow_ghsas: z.array(z.string()).default([]),
license_check: z.boolean().default(true),
vulnerability_check: z.boolean().default(true),
config_file: z.string().optional().default('false'),
base_ref: z.string(),
head_ref: z.string()
config_file: z.string().optional(),
base_ref: z.string().optional(),
head_ref: z.string().optional()
})
.partial()
.refine(obj => !(obj.allow_licenses && obj.deny_licenses), 'Your workflow file has both an allow_licenses list and deny_licenses list, but you can only set one or the other.');
.superRefine((config, context) => {
if (config.allow_licenses && config.deny_licenses) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: 'You cannot specify both allow-licenses and deny-licenses'
});
}
if (config.allow_licenses && config.allow_licenses.length < 1) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: 'You should provide at least one license in allow-licenses'
});
}
if (config.license_check === false &&
config.vulnerability_check === false) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: "Can't disable both license-check and vulnerability-check"
});
}
});
exports.ChangesSchema = z.array(exports.ChangeSchema);
@@ -27679,11 +27763,36 @@ exports.ChangesSchema = z.array(exports.ChangeSchema);
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isSPDXValid = exports.renderUrl = exports.getManifestsSet = exports.groupDependenciesByManifest = void 0;
exports.octokitClient = exports.isSPDXValid = exports.renderUrl = exports.getManifestsSet = exports.groupDependenciesByManifest = void 0;
const core = __importStar(__nccwpck_require__(2186));
const octokit_1 = __nccwpck_require__(7467);
const spdx_expression_parse_1 = __importDefault(__nccwpck_require__(1620));
function groupDependenciesByManifest(changes) {
var _a;
@@ -27721,6 +27830,17 @@ function isSPDXValid(license) {
}
}
exports.isSPDXValid = isSPDXValid;
function octokitClient(token = 'repo-token', required = true) {
const opts = {};
// auth is only added if token is present. For remote config files in public
// repos the token is optional, so it could be undefined.
const auth = core.getInput(token, { required });
if (auth !== undefined) {
opts['auth'] = auth;
}
return new octokit_1.Octokit(opts);
}
exports.octokitClient = octokitClient;
/***/ }),
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+137 -118
View File
@@ -24,16 +24,16 @@
},
"devDependencies": {
"@types/jest": "^27.5.2",
"@types/node": "^16.18.3",
"@types/spdx-expression-parse": "^3.0.2",
"@types/spdx-satisfies": "^0.1.0",
"@types/node": "^16.18.2",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@vercel/ncc": "^0.34.0",
"esbuild-register": "^3.3.3",
"eslint": "^8.26.0",
"eslint-plugin-github": "^4.4.0",
"eslint-plugin-jest": "^27.1.3",
"esbuild-register": "^3.4.1",
"eslint": "^8.27.0",
"eslint-plugin-github": "^4.4.1",
"eslint-plugin-jest": "^27.1.5",
"jest": "^27.5.1",
"js-yaml": "^4.1.0",
"nodemon": "^2.0.20",
@@ -1802,9 +1802,9 @@
"integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw=="
},
"node_modules/@types/node": {
"version": "16.18.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.2.tgz",
"integrity": "sha512-KIGQJyya+opDCFvDSZMNNS899ov5jlNdtN7PypgHWeb8e+5vWISdwTRo/ClsNVlmDihzOGqFyNBDamUs7TQQCA=="
"version": "16.18.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz",
"integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg=="
},
"node_modules/@types/prettier": {
"version": "2.7.1",
@@ -1852,16 +1852,17 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.41.0.tgz",
"integrity": "sha512-DXUS22Y57/LAFSg3x7Vi6RNAuLpTXwxB9S2nIA7msBb/Zt8p7XqMwdpdc1IU7CkOQUPgAqR5fWvxuKCbneKGmA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz",
"integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.41.0",
"@typescript-eslint/type-utils": "5.41.0",
"@typescript-eslint/utils": "5.41.0",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/type-utils": "5.42.1",
"@typescript-eslint/utils": "5.42.1",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
@@ -1884,14 +1885,14 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.41.0.tgz",
"integrity": "sha512-HQVfix4+RL5YRWZboMD1pUfFN8MpRH4laziWkkAzyO1fvNOY/uinZcvo3QiFJVS/siNHupV8E5+xSwQZrl6PZA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
"integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.41.0",
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/typescript-estree": "5.41.0",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/typescript-estree": "5.42.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1911,13 +1912,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.41.0.tgz",
"integrity": "sha512-xOxPJCnuktUkY2xoEZBKXO5DBCugFzjrVndKdUnyQr3+9aDWZReKq9MhaoVnbL+maVwWJu/N0SEtrtEUNb62QQ==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
"integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/visitor-keys": "5.41.0"
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/visitor-keys": "5.42.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1928,13 +1929,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.41.0.tgz",
"integrity": "sha512-L30HNvIG6A1Q0R58e4hu4h+fZqaO909UcnnPbwKiN6Rc3BUEx6ez2wgN7aC0cBfcAjZfwkzE+E2PQQ9nEuoqfA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz",
"integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "5.41.0",
"@typescript-eslint/utils": "5.41.0",
"@typescript-eslint/typescript-estree": "5.42.1",
"@typescript-eslint/utils": "5.42.1",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
@@ -1955,9 +1956,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.41.0.tgz",
"integrity": "sha512-5BejraMXMC+2UjefDvrH0Fo/eLwZRV6859SXRg+FgbhA0R0l6lDqDGAQYhKbXhPN2ofk2kY5sgGyLNL907UXpA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
"integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1968,13 +1969,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.41.0.tgz",
"integrity": "sha512-SlzFYRwFSvswzDSQ/zPkIWcHv8O5y42YUskko9c4ki+fV6HATsTODUPbRbcGDFYP86gaJL5xohUEytvyNNcXWg==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
"integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/visitor-keys": "5.41.0",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/visitor-keys": "5.42.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -1995,16 +1996,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.41.0.tgz",
"integrity": "sha512-QlvfwaN9jaMga9EBazQ+5DDx/4sAdqDkcs05AsQHMaopluVCUyu1bTRUVKzXbgjDlrRAQrYVoi/sXJ9fmG+KLQ==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz",
"integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12",
"@typescript-eslint/scope-manager": "5.41.0",
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/typescript-estree": "5.41.0",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/typescript-estree": "5.42.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0",
"semver": "^7.3.7"
@@ -2021,12 +2022,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.41.0.tgz",
"integrity": "sha512-vilqeHj267v8uzzakbm13HkPMl7cbYpKVjgFWZPIOHIJHZtinvypUhJ5xBXfWYg4eFKqztbMMpOgFpT9Gfx4fw==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
"integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/types": "5.42.1",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
@@ -3430,10 +3431,13 @@
}
},
"node_modules/esbuild-register": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.3.tgz",
"integrity": "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.4.1.tgz",
"integrity": "sha512-iCgs88/1wA5dIRx4i65eSjbkgrQQQJGpY6Z1eD2XPlzrSjbgNtfkw2/rfSMzJ4dTtlOD8EZTxrIA3fyYp0FsMA==",
"dev": true,
"dependencies": {
"debug": "^4.3.4"
},
"peerDependencies": {
"esbuild": ">=0.12 <1"
}
@@ -3610,9 +3614,9 @@
}
},
"node_modules/eslint": {
"version": "8.26.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz",
"integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==",
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz",
"integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==",
"dev": true,
"dependencies": {
"@eslint/eslintrc": "^1.3.3",
@@ -3778,9 +3782,9 @@
}
},
"node_modules/eslint-plugin-github": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.4.0.tgz",
"integrity": "sha512-jmVjy86WqVblKuvWnAQAEUMPZnAWbOUuV2hmAjQ54BvmukUW5PBml84NnyKe1QMt6k5a6JoIrbkLkyISTUDSxA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.4.1.tgz",
"integrity": "sha512-wpxUIPw+EK5bdUssB8W5Z9/tapZptfJuLkThwPY8p52v75MV/Fb1AkCrLGlYO0yi3mQGFoa3uE0NMzssVAFrUw==",
"dev": true,
"dependencies": {
"@github/browserslist-config": "^1.0.0",
@@ -3871,9 +3875,9 @@
"dev": true
},
"node_modules/eslint-plugin-jest": {
"version": "27.1.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.1.3.tgz",
"integrity": "sha512-7DrIfYRQPa7JQd1Le8G/BJsfYHVUKQdJQ/6vULSp/4NjKZmSMJ/605G2hhScEra++SiH68zPEjLnrO74nHrMLg==",
"version": "27.1.5",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.1.5.tgz",
"integrity": "sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "^5.10.0"
@@ -6277,6 +6281,12 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/natural-compare-lite": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -9592,9 +9602,9 @@
"integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw=="
},
"@types/node": {
"version": "16.18.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.2.tgz",
"integrity": "sha512-KIGQJyya+opDCFvDSZMNNS899ov5jlNdtN7PypgHWeb8e+5vWISdwTRo/ClsNVlmDihzOGqFyNBDamUs7TQQCA=="
"version": "16.18.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz",
"integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg=="
},
"@types/prettier": {
"version": "2.7.1",
@@ -9642,69 +9652,70 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.41.0.tgz",
"integrity": "sha512-DXUS22Y57/LAFSg3x7Vi6RNAuLpTXwxB9S2nIA7msBb/Zt8p7XqMwdpdc1IU7CkOQUPgAqR5fWvxuKCbneKGmA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz",
"integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.41.0",
"@typescript-eslint/type-utils": "5.41.0",
"@typescript-eslint/utils": "5.41.0",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/type-utils": "5.42.1",
"@typescript-eslint/utils": "5.42.1",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/parser": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.41.0.tgz",
"integrity": "sha512-HQVfix4+RL5YRWZboMD1pUfFN8MpRH4laziWkkAzyO1fvNOY/uinZcvo3QiFJVS/siNHupV8E5+xSwQZrl6PZA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
"integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.41.0",
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/typescript-estree": "5.41.0",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/typescript-estree": "5.42.1",
"debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.41.0.tgz",
"integrity": "sha512-xOxPJCnuktUkY2xoEZBKXO5DBCugFzjrVndKdUnyQr3+9aDWZReKq9MhaoVnbL+maVwWJu/N0SEtrtEUNb62QQ==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
"integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/visitor-keys": "5.41.0"
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/visitor-keys": "5.42.1"
}
},
"@typescript-eslint/type-utils": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.41.0.tgz",
"integrity": "sha512-L30HNvIG6A1Q0R58e4hu4h+fZqaO909UcnnPbwKiN6Rc3BUEx6ez2wgN7aC0cBfcAjZfwkzE+E2PQQ9nEuoqfA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz",
"integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==",
"dev": true,
"requires": {
"@typescript-eslint/typescript-estree": "5.41.0",
"@typescript-eslint/utils": "5.41.0",
"@typescript-eslint/typescript-estree": "5.42.1",
"@typescript-eslint/utils": "5.42.1",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/types": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.41.0.tgz",
"integrity": "sha512-5BejraMXMC+2UjefDvrH0Fo/eLwZRV6859SXRg+FgbhA0R0l6lDqDGAQYhKbXhPN2ofk2kY5sgGyLNL907UXpA==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
"integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.41.0.tgz",
"integrity": "sha512-SlzFYRwFSvswzDSQ/zPkIWcHv8O5y42YUskko9c4ki+fV6HATsTODUPbRbcGDFYP86gaJL5xohUEytvyNNcXWg==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
"integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/visitor-keys": "5.41.0",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/visitor-keys": "5.42.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -9713,28 +9724,28 @@
}
},
"@typescript-eslint/utils": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.41.0.tgz",
"integrity": "sha512-QlvfwaN9jaMga9EBazQ+5DDx/4sAdqDkcs05AsQHMaopluVCUyu1bTRUVKzXbgjDlrRAQrYVoi/sXJ9fmG+KLQ==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz",
"integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12",
"@typescript-eslint/scope-manager": "5.41.0",
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/typescript-estree": "5.41.0",
"@typescript-eslint/scope-manager": "5.42.1",
"@typescript-eslint/types": "5.42.1",
"@typescript-eslint/typescript-estree": "5.42.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0",
"semver": "^7.3.7"
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.41.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.41.0.tgz",
"integrity": "sha512-vilqeHj267v8uzzakbm13HkPMl7cbYpKVjgFWZPIOHIJHZtinvypUhJ5xBXfWYg4eFKqztbMMpOgFpT9Gfx4fw==",
"version": "5.42.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
"integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.41.0",
"@typescript-eslint/types": "5.42.1",
"eslint-visitor-keys": "^3.3.0"
}
},
@@ -10718,11 +10729,13 @@
"peer": true
},
"esbuild-register": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.3.tgz",
"integrity": "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.4.1.tgz",
"integrity": "sha512-iCgs88/1wA5dIRx4i65eSjbkgrQQQJGpY6Z1eD2XPlzrSjbgNtfkw2/rfSMzJ4dTtlOD8EZTxrIA3fyYp0FsMA==",
"dev": true,
"requires": {}
"requires": {
"debug": "^4.3.4"
}
},
"esbuild-sunos-64": {
"version": "0.15.12",
@@ -10829,9 +10842,9 @@
}
},
"eslint": {
"version": "8.26.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz",
"integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==",
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.27.0.tgz",
"integrity": "sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==",
"dev": true,
"requires": {
"@eslint/eslintrc": "^1.3.3",
@@ -10981,9 +10994,9 @@
}
},
"eslint-plugin-github": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.4.0.tgz",
"integrity": "sha512-jmVjy86WqVblKuvWnAQAEUMPZnAWbOUuV2hmAjQ54BvmukUW5PBml84NnyKe1QMt6k5a6JoIrbkLkyISTUDSxA==",
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.4.1.tgz",
"integrity": "sha512-wpxUIPw+EK5bdUssB8W5Z9/tapZptfJuLkThwPY8p52v75MV/Fb1AkCrLGlYO0yi3mQGFoa3uE0NMzssVAFrUw==",
"dev": true,
"requires": {
"@github/browserslist-config": "^1.0.0",
@@ -11059,9 +11072,9 @@
}
},
"eslint-plugin-jest": {
"version": "27.1.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.1.3.tgz",
"integrity": "sha512-7DrIfYRQPa7JQd1Le8G/BJsfYHVUKQdJQ/6vULSp/4NjKZmSMJ/605G2hhScEra++SiH68zPEjLnrO74nHrMLg==",
"version": "27.1.5",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.1.5.tgz",
"integrity": "sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "^5.10.0"
@@ -12841,6 +12854,12 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"natural-compare-lite": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+7 -7
View File
@@ -40,16 +40,16 @@
},
"devDependencies": {
"@types/jest": "^27.5.2",
"@types/node": "^16.18.2",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"@types/node": "^16.18.3",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@types/spdx-expression-parse": "^3.0.2",
"@types/spdx-satisfies": "^0.1.0",
"@vercel/ncc": "^0.34.0",
"esbuild-register": "^3.3.3",
"eslint": "^8.26.0",
"eslint-plugin-github": "^4.4.0",
"eslint-plugin-jest": "^27.1.3",
"esbuild-register": "^3.4.1",
"eslint": "^8.27.0",
"eslint-plugin-github": "^4.4.1",
"eslint-plugin-jest": "^27.1.5",
"jest": "^27.5.1",
"js-yaml": "^4.1.0",
"nodemon": "^2.0.20",
+118 -88
View File
@@ -3,15 +3,57 @@ import path from 'path'
import YAML from 'yaml'
import * as core from '@actions/core'
import * as z from 'zod'
import {
ConfigurationOptions,
ConfigurationOptionsSchema,
SeveritySchema,
SCOPES
} from './schemas'
import {isSPDXValid} from './utils'
import {ConfigurationOptions, ConfigurationOptionsSchema} from './schemas'
import {isSPDXValid, octokitClient} from './utils'
type licenseKey = 'allow-licenses' | 'deny-licenses'
type ConfigurationOptionsPartial = Partial<ConfigurationOptions>
export async function readConfig(): Promise<ConfigurationOptions> {
const inlineConfig = readInlineConfig()
const configFile = getOptionalInput('config-file')
if (configFile !== undefined) {
const externalConfig = await readConfigFile(configFile)
return ConfigurationOptionsSchema.parse({
...externalConfig,
...inlineConfig
})
}
return ConfigurationOptionsSchema.parse(inlineConfig)
}
function readInlineConfig(): ConfigurationOptionsPartial {
const fail_on_severity = getOptionalInput('fail-on-severity')
const fail_on_scopes = parseList(getOptionalInput('fail-on-scopes'))
const allow_licenses = parseList(getOptionalInput('allow-licenses'))
const deny_licenses = parseList(getOptionalInput('deny-licenses'))
const allow_ghsas = parseList(getOptionalInput('allow-ghsas'))
const license_check = getOptionalBoolean('license-check')
const vulnerability_check = getOptionalBoolean('vulnerability-check')
const base_ref = getOptionalInput('base-ref')
const head_ref = getOptionalInput('head-ref')
validateLicenses('allow-licenses', allow_licenses)
validateLicenses('deny-licenses', deny_licenses)
const keys = {
fail_on_severity,
fail_on_scopes,
allow_licenses,
deny_licenses,
allow_ghsas,
license_check,
vulnerability_check,
base_ref,
head_ref
}
return Object.fromEntries(
Object.entries(keys).filter(([_, value]) => value !== undefined)
)
}
function getOptionalBoolean(name: string): boolean | undefined {
const value = core.getInput(name)
@@ -32,7 +74,7 @@ function parseList(list: string | undefined): string[] | undefined {
}
function validateLicenses(
key: licenseKey,
key: 'allow-licenses' | 'deny-licenses',
licenses: string[] | undefined
): void {
if (licenses === undefined) {
@@ -47,89 +89,77 @@ function validateLicenses(
}
}
export function readConfig(): ConfigurationOptions {
const externalConfig = getOptionalInput('config-file')
if (externalConfig !== undefined) {
const config = readConfigFile(externalConfig)
// the reasoning behind reading the inline config when an external
// config file is provided is that we still want to allow users to
// pass inline options in the presence of an external config file.
const inlineConfig = readInlineConfig()
// the external config takes precedence
return Object.assign({}, inlineConfig, config)
} else {
return readInlineConfig()
}
}
export function readInlineConfig(): ConfigurationOptions {
const fail_on_severity = SeveritySchema.parse(
getOptionalInput('fail-on-severity')
async function readConfigFile(
filePath: string
): Promise<ConfigurationOptionsPartial> {
// match a remote config (e.g. 'owner/repo/filepath@someref')
const format = new RegExp(
'(?<owner>[^/]+)/(?<repo>[^/]+)/(?<path>[^@]+)@(?<ref>.*)'
)
const fail_on_scopes = z
.array(z.enum(SCOPES))
.default(['runtime'])
.parse(parseList(getOptionalInput('fail-on-scopes')))
const allow_licenses = parseList(getOptionalInput('allow-licenses'))
const deny_licenses = parseList(getOptionalInput('deny-licenses'))
if (allow_licenses !== undefined && deny_licenses !== undefined) {
throw new Error("Can't specify both allow_licenses and deny_licenses")
}
validateLicenses('allow-licenses', allow_licenses)
validateLicenses('deny-licenses', deny_licenses)
const allow_ghsas = parseList(getOptionalInput('allow-ghsas'))
const license_check = z
.boolean()
.default(true)
.parse(getOptionalBoolean('license-check'))
const vulnerability_check = z
.boolean()
.default(true)
.parse(getOptionalBoolean('vulnerability-check'))
if (license_check === false && vulnerability_check === false) {
throw new Error("Can't disable both license-check and vulnerability-check")
}
const base_ref = getOptionalInput('base-ref')
const head_ref = getOptionalInput('head-ref')
return {
fail_on_severity,
fail_on_scopes,
allow_licenses,
deny_licenses,
allow_ghsas,
license_check,
vulnerability_check,
base_ref,
head_ref
}
}
export function readConfigFile(filePath: string): ConfigurationOptions {
let data
let data: string
const pieces = format.exec(filePath)
try {
data = fs.readFileSync(path.resolve(filePath), 'utf-8')
} catch (error: unknown) {
if (pieces?.groups && pieces.length === 5) {
data = await getRemoteConfig({
owner: pieces.groups.owner,
repo: pieces.groups.repo,
path: pieces.groups.path,
ref: pieces.groups.ref
})
} else {
data = fs.readFileSync(path.resolve(filePath), 'utf-8')
}
return parseConfigFile(data)
} catch (error) {
core.debug(error as string)
throw new Error('Unable to fetch config file')
}
}
function parseConfigFile(configData: string): ConfigurationOptionsPartial {
try {
const data = YAML.parse(configData)
for (const key of Object.keys(data)) {
if (key === 'allow-licenses' || key === 'deny-licenses') {
validateLicenses(key, data[key])
}
// get rid of the ugly dashes from the actions conventions
if (key.includes('-')) {
data[key.replace(/-/g, '_')] = data[key]
delete data[key]
}
}
return data
} catch (error) {
throw error
}
data = YAML.parse(data)
for (const key of Object.keys(data)) {
if (key === 'allow-licenses' || key === 'deny-licenses') {
validateLicenses(key, data[key])
}
// get rid of the ugly dashes from the actions conventions
if (key.includes('-')) {
data[key.replace(/-/g, '_')] = data[key]
delete data[key]
}
}
const values = ConfigurationOptionsSchema.parse(data)
return values
}
async function getRemoteConfig(configOpts: {
[key: string]: string
}): Promise<string> {
try {
const {data} = await octokitClient(
'external-repo-token',
false
).rest.repos.getContent({
mediaType: {
format: 'raw'
},
owner: configOpts.owner,
repo: configOpts.repo,
path: configOpts.path,
ref: configOpts.ref
})
// When using mediaType.format = 'raw', the response.data is a string
// but this is not reflected in the return type of getContent, so we're
// casting the return value to a string.
return z.string().parse(data as unknown)
} catch (error) {
core.debug(error as string)
throw new Error('Error fetching remote config file')
}
}
+5 -8
View File
@@ -1,8 +1,6 @@
import * as core from '@actions/core'
import spdxSatisfies from 'spdx-satisfies'
import {Octokit} from 'octokit'
import {Change, Changes} from './schemas'
import {isSPDXValid} from './utils'
import {isSPDXValid, octokitClient} from './utils'
/**
* Loops through a list of changes, filtering and returning the
@@ -76,12 +74,11 @@ const fetchGHLicense = async (
owner: string,
repo: string
): Promise<string | null> => {
const octokit = new Octokit({
auth: core.getInput('repo-token', {required: true})
})
try {
const response = await octokit.rest.licenses.getForRepo({owner, repo})
const response = await octokitClient().rest.licenses.getForRepo({
owner,
repo
})
return response.data.license?.spdx_id ?? null
} catch (_) {
return null
+2 -2
View File
@@ -18,7 +18,7 @@ import {groupDependenciesByManifest} from './utils'
async function run(): Promise<void> {
try {
const config = readConfig()
const config = await readConfig()
const refs = getRefs(config, github.context)
const changes = await dependencyGraph.compare({
@@ -28,7 +28,7 @@ async function run(): Promise<void> {
headRef: refs.head
})
const minSeverity = config.fail_on_severity as Severity
const minSeverity = config.fail_on_severity
const scopedChanges = filterChangesByScopes(config.fail_on_scopes, changes)
const filteredChanges = filterAllowedAdvisories(
config.allow_ghsas,
+28 -10
View File
@@ -38,20 +38,38 @@ export const ConfigurationOptionsSchema = z
.object({
fail_on_severity: SeveritySchema,
fail_on_scopes: z.array(z.enum(SCOPES)).default(['runtime']),
allow_licenses: z.array(z.string()).default([]),
deny_licenses: z.array(z.string()).default([]),
allow_licenses: z.array(z.string()).optional(),
deny_licenses: z.array(z.string()).optional(),
allow_ghsas: z.array(z.string()).default([]),
license_check: z.boolean().default(true),
vulnerability_check: z.boolean().default(true),
config_file: z.string().optional().default('false'),
base_ref: z.string(),
head_ref: z.string()
config_file: z.string().optional(),
base_ref: z.string().optional(),
head_ref: z.string().optional()
})
.superRefine((config, context) => {
if (config.allow_licenses && config.deny_licenses) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: 'You cannot specify both allow-licenses and deny-licenses'
})
}
if (config.allow_licenses && config.allow_licenses.length < 1) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: 'You should provide at least one license in allow-licenses'
})
}
if (
config.license_check === false &&
config.vulnerability_check === false
) {
context.addIssue({
code: z.ZodIssueCode.custom,
message: "Can't disable both license-check and vulnerability-check"
})
}
})
.partial()
.refine(
obj => !(obj.allow_licenses && obj.deny_licenses),
'Your workflow file has both an allow_licenses list and deny_licenses list, but you can only set one or the other.'
)
export const ChangesSchema = z.array(ChangeSchema)
+15
View File
@@ -1,3 +1,5 @@
import * as core from '@actions/core'
import {Octokit} from 'octokit'
import spdxParse from 'spdx-expression-parse'
import {Changes} from './schemas'
@@ -38,3 +40,16 @@ export function isSPDXValid(license: string): boolean {
return false
}
}
export function octokitClient(token = 'repo-token', required = true): Octokit {
const opts: Record<string, unknown> = {}
// auth is only added if token is present. For remote config files in public
// repos the token is optional, so it could be undefined.
const auth = core.getInput(token, {required})
if (auth !== undefined) {
opts['auth'] = auth
}
return new Octokit(opts)
}