Skip to content

Commit ee49ac2

Browse files
committed
Add infrastructure to check for unapproved npm dependency licenses
A task and GitHub Actions workflow are provided here for checking the license types of npm-managed project dependencies. On every push and pull request that affects relevant files, the CI workflow will check: - If the dependency licenses cache is up to date - If any of the project's dependencies have an unapproved license type. Approval can be based on: - Universally allowed license type - Individual dependency
1 parent 1b78422 commit ee49ac2

File tree

5 files changed

+267
-0
lines changed

5 files changed

+267
-0
lines changed

Diff for: .github/CONTRIBUTING.md

+14
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ Thanks!
7474

7575
## Common Development Operations
7676

77+
### Dependency License Metadata
78+
79+
Metadata about the license types of all dependencies is cached in the repository. To update this cache, run the following command from the repository root folder:
80+
81+
```text
82+
task general:cache-dep-licenses
83+
```
84+
85+
The necessary **Licensed** tool can be installed by following [these instructions](https://github.com/github/licensed#as-an-executable).
86+
87+
Unfortunately, **Licensed** does not have Windows support.
88+
89+
An updated cache is also generated whenever the cache is found to be outdated by the "**Check Go Dependencies**" CI workflow and made available for download via the `dep-licenses-cache` [workflow artifact](https://docs.github.com/actions/managing-workflow-runs/downloading-workflow-artifacts).
90+
7791
### Running Checks
7892

7993
Checks and tests are set up to ensure the project content is functional and compliant with the established standards.

Diff for: .github/workflows/check-npm-dependencies-task.yml

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-npm-dependencies-task.md
2+
name: Check npm Dependencies
3+
4+
# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows
5+
on:
6+
create:
7+
push:
8+
paths:
9+
- ".github/workflows/check-npm-dependencies-task.ya?ml"
10+
- ".licenses/**"
11+
- ".licensed.json"
12+
- ".licensed.ya?ml"
13+
- "Taskfile.ya?ml"
14+
- "**/.gitmodules"
15+
- "**/.npmrc"
16+
- "**/package.json"
17+
- "**/package-lock.json"
18+
pull_request:
19+
paths:
20+
- ".github/workflows/check-npm-dependencies-task.ya?ml"
21+
- ".licenses/**"
22+
- ".licensed.json"
23+
- ".licensed.ya?ml"
24+
- "Taskfile.ya?ml"
25+
- "**/.gitmodules"
26+
- "**/.npmrc"
27+
- "**/package.json"
28+
- "**/package-lock.json"
29+
schedule:
30+
# Run periodically to catch breakage caused by external changes.
31+
- cron: "0 8 * * WED"
32+
workflow_dispatch:
33+
repository_dispatch:
34+
35+
jobs:
36+
run-determination:
37+
runs-on: ubuntu-latest
38+
permissions: {}
39+
outputs:
40+
result: ${{ steps.determination.outputs.result }}
41+
steps:
42+
- name: Determine if the rest of the workflow should run
43+
id: determination
44+
run: |
45+
RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x"
46+
# The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead.
47+
if [[
48+
"${{ github.event_name }}" != "create" ||
49+
"${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX
50+
]]; then
51+
# Run the other jobs.
52+
RESULT="true"
53+
else
54+
# There is no need to run the other jobs.
55+
RESULT="false"
56+
fi
57+
58+
echo "result=$RESULT" >> $GITHUB_OUTPUT
59+
60+
check-cache:
61+
needs: run-determination
62+
if: needs.run-determination.outputs.result == 'true'
63+
runs-on: ubuntu-latest
64+
permissions:
65+
contents: read
66+
67+
steps:
68+
- name: Checkout repository
69+
uses: actions/checkout@v4
70+
with:
71+
submodules: recursive
72+
73+
# This is required to allow jonabc/setup-licensed to install licensed via Ruby gem.
74+
- name: Install Ruby
75+
uses: ruby/setup-ruby@v1
76+
with:
77+
ruby-version: ruby # Install latest version
78+
79+
- name: Install licensed
80+
uses: jonabc/setup-licensed@v1
81+
with:
82+
github_token: ${{ secrets.GITHUB_TOKEN }}
83+
version: 3.x
84+
85+
- name: Setup Node.js
86+
uses: actions/setup-node@v4
87+
with:
88+
node-version-file: package.json
89+
90+
- name: Install Task
91+
uses: arduino/setup-task@v2
92+
with:
93+
repo-token: ${{ secrets.GITHUB_TOKEN }}
94+
version: 3.x
95+
96+
- name: Update dependencies license metadata cache
97+
run: task --silent general:cache-dep-licenses
98+
99+
- name: Check for outdated cache
100+
id: diff
101+
run: |
102+
git add .
103+
if ! git diff --cached --color --exit-code; then
104+
echo
105+
echo "::error::Dependency license metadata out of sync. See: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-go-dependencies-task.md#metadata-cache"
106+
exit 1
107+
fi
108+
109+
# Some might find it convenient to have CI generate the cache rather than setting up for it locally
110+
- name: Upload cache to workflow artifact
111+
if: failure() && steps.diff.outcome == 'failure'
112+
uses: actions/upload-artifact@v3
113+
with:
114+
if-no-files-found: error
115+
include-hidden-files: true
116+
name: dep-licenses-cache
117+
path: .licenses/
118+
119+
check-deps:
120+
needs: run-determination
121+
if: needs.run-determination.outputs.result == 'true'
122+
runs-on: ubuntu-latest
123+
permissions:
124+
contents: read
125+
126+
steps:
127+
- name: Checkout repository
128+
uses: actions/checkout@v4
129+
with:
130+
submodules: recursive
131+
132+
# This is required to allow jonabc/setup-licensed to install licensed via Ruby gem.
133+
- name: Install Ruby
134+
uses: ruby/setup-ruby@v1
135+
with:
136+
ruby-version: ruby # Install latest version
137+
138+
- name: Install licensed
139+
uses: jonabc/setup-licensed@v1
140+
with:
141+
github_token: ${{ secrets.GITHUB_TOKEN }}
142+
version: 3.x
143+
144+
- name: Setup Node.js
145+
uses: actions/setup-node@v4
146+
with:
147+
node-version-file: package.json
148+
149+
- name: Install Task
150+
uses: arduino/setup-task@v2
151+
with:
152+
repo-token: ${{ secrets.GITHUB_TOKEN }}
153+
version: 3.x
154+
155+
- name: Check for dependencies with unapproved licenses
156+
run: task --silent general:check-dep-licenses

Diff for: .licensed.yml

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# See: https://github.com/github/licensed/blob/master/docs/configuration.md
2+
3+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies/Apache-2.0/.licensed.yml
4+
allowed:
5+
# The following are based on https://www.apache.org/legal/resolved.html#category-a
6+
- apache-2.0
7+
- apache-1.1
8+
- php-3.01
9+
# "MX4J License" - no SPDX ID
10+
- bsd-2-clause
11+
- bsd-2-clause-netbsd # Deprecated ID for `bsd-2-clause`
12+
- bsd-2-clause-views
13+
- bsd-2-clause-freebsd # Deprecated ID for `bsd-2-clause-views`
14+
- bsd-3-clause
15+
- bsd-3-clause-clear
16+
# "DOM4J License" - no SPDX ID
17+
- postgresql
18+
# "Eclipse Distribution License 1.0" - no SPDX ID
19+
- mit
20+
- x11
21+
- isc
22+
- smlnj
23+
- standardml-nj # Deprecated ID for `smlnj`
24+
# "Cup Parser Generator" - no SPDX ID
25+
- icu
26+
- ncsa
27+
- w3c
28+
# "W3C Community Contributor License Agreement" - no SPDX ID
29+
- xnet
30+
- zlib
31+
# "FSF autoconf license" - no SPDX ID
32+
- afl-3.0
33+
# "Service+Component+Architecture+Specifications" - no SPDX ID
34+
# "OOXML XSD ECMA License"
35+
- ms-pl
36+
- cc-pddc
37+
- psf-2.0
38+
# "Python Imaging Library Software License"
39+
- apafml
40+
- bsl-1.0
41+
- ogl-uk-3.0
42+
- wtfpl
43+
- unicode-tou
44+
- zpl-2.0
45+
# "ACE license" - no SPDX ID
46+
- upl-1.0
47+
# "Open Grid Forum License" - no SPDX ID
48+
# 'Google "Additional IP Rights Grant (Patents)" file' - no SPDX ID
49+
- unlicense
50+
- hpnd
51+
- mulanpsl-2.0
52+
- cc0-1.0
53+
# The following are based on individual license text
54+
- lgpl-2.0-or-later
55+
- lgpl-2.0+ # Deprecated ID for `lgpl-2.0-or-later`
56+
- lgpl-2.1-only
57+
- lgpl-2.1 # Deprecated ID for `lgpl-2.1-only`
58+
- lgpl-2.1-or-later
59+
- lgpl-2.1+ # Deprecated ID for `lgpl-2.1-or-later`
60+
- lgpl-3.0-only
61+
- lgpl-3.0 # Deprecated ID for `lgpl-3.0-only`
62+
- lgpl-3.0-or-later
63+
- lgpl-3.0+ # Deprecated ID for `lgpl-3.0-or-later`

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![Tests Status](https://github.com/arduino/arduino-lint-action/actions/workflows/test-javascript-jest-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/test-javascript-jest-task.yml)
44
[![Integration Tests Status](https://github.com/arduino/arduino-lint-action/workflows/Integration%20Tests/badge.svg)](https://github.com/arduino/arduino-lint-action/actions?workflow=Integration+Tests)
55
[![Check License status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-license.yml)
6+
[![Check npm Dependencies status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-npm-dependencies-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-npm-dependencies-task.yml)
67
[![Check Packaging status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-packaging-ncc-typescript-npm.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-packaging-ncc-typescript-npm.yml)
78
[![Check Prettier Formatting status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-prettier-formatting-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-prettier-formatting-task.yml)
89
[![Check TypeScript Configuration status](https://github.com/arduino/arduino-lint-action/actions/workflows/check-tsconfig-task.yml/badge.svg)](https://github.com/arduino/arduino-lint-action/actions/workflows/check-tsconfig-task.yml)

Diff for: Taskfile.yml

+33
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,33 @@ tasks:
3636
- task: poetry:sync
3737
- task: ts:build
3838

39+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml
40+
general:cache-dep-licenses:
41+
desc: Cache dependency license metadata
42+
deps:
43+
- task: general:prepare-deps
44+
cmds:
45+
- |
46+
if ! which licensed &>/dev/null; then
47+
if [[ {{OS}} == "windows" ]]; then
48+
echo "Licensed does not have Windows support."
49+
echo "Please use Linux/macOS or download the dependencies cache from the GitHub Actions workflow artifact."
50+
else
51+
echo "licensed not found or not in PATH."
52+
echo "Please install: https://github.com/github/licensed#as-an-executable"
53+
fi
54+
exit 1
55+
fi
56+
- licensed cache
57+
58+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml
59+
general:check-dep-licenses:
60+
desc: Check for unapproved dependency licenses
61+
deps:
62+
- task: general:cache-dep-licenses
63+
cmds:
64+
- licensed status
65+
3966
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check-task/Taskfile.yml
4067
general:check-spelling:
4168
desc: Check for commonly misspelled words
@@ -64,6 +91,12 @@ tasks:
6491
cmds:
6592
- npx prettier --write .
6693

94+
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-dependencies-task/Taskfile.yml
95+
general:prepare-deps:
96+
desc: Prepare project dependencies for license check
97+
deps:
98+
- task: npm:install-deps
99+
67100
js:test:
68101
desc: |
69102
Test the project's JavaScript/TypeScript code.

0 commit comments

Comments
 (0)