Skip to content

Commit

Permalink
Add CI workflow to check for unapproved npm dependency licenses
Browse files Browse the repository at this point in the history
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
  • Loading branch information
per1234 committed Aug 16, 2022
1 parent 148baf5 commit aaef6dd
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 2 deletions.
140 changes: 140 additions & 0 deletions .github/workflows/check-npm-dependencies-task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-npm-dependencies-task.md
name: Check npm Dependencies

env:
# See: https://github.com/actions/setup-node/#readme
NODE_VERSION: 16.x

# See: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows
on:
create:
push:
paths:
- ".github/workflows/check-npm-dependencies-task.ya?ml"
- ".licenses/**"
- ".licensed.json"
- ".licensed.ya?ml"
- "Taskfile.ya?ml"
- "**/.gitmodules"
- "**/package.json"
- "**/package-lock.json"
pull_request:
paths:
- ".github/workflows/check-npm-dependencies-task.ya?ml"
- ".licenses/**"
- ".licensed.json"
- ".licensed.ya?ml"
- "Taskfile.ya?ml"
- "**/.gitmodules"
- "**/package.json"
- "**/package-lock.json"
schedule:
# Run periodically to catch breakage caused by external changes.
- cron: "0 8 * * WED"
workflow_dispatch:
repository_dispatch:

jobs:
run-determination:
runs-on: ubuntu-latest
outputs:
result: ${{ steps.determination.outputs.result }}
steps:
- name: Determine if the rest of the workflow should run
id: determination
run: |
RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x"
# The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead.
if [[
"${{ github.event_name }}" != "create" ||
"${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX
]]; then
# Run the other jobs.
RESULT="true"
else
# There is no need to run the other jobs.
RESULT="false"
fi
echo "::set-output name=result::$RESULT"
check-cache:
needs: run-determination
if: needs.run-determination.outputs.result == 'true'
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: recursive

- name: Install licensed
uses: jonabc/setup-licensed@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
version: 3.x

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install Task
uses: arduino/setup-task@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
version: 3.x

- name: Update dependencies license metadata cache
run: task --silent general:cache-dep-licenses

- name: Check for outdated cache
id: diff
run: |
git add .
if ! git diff --cached --color --exit-code; then
echo
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"
exit 1
fi
# Some might find it convenient to have CI generate the cache rather than setting up for it locally
- name: Upload cache to workflow artifact
if: failure() && steps.diff.outcome == 'failure'
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: dep-licenses-cache
path: .licenses/

check-deps:
needs: run-determination
if: needs.run-determination.outputs.result == 'true'
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: recursive

- name: Install licensed
uses: jonabc/setup-licensed@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
version: 3.x

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install Task
uses: arduino/setup-task@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
version: 3.x

- name: Check for dependencies with unapproved licenses
run: task --silent general:check-dep-licenses
87 changes: 87 additions & 0 deletions .licensed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# See: https://github.com/github/licensed/blob/master/docs/configuration.md
sources:
npm: true

shared_cache: true
cache_path: .licenses/

apps:
- source_path: ./

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies/GPL-3.0/.licensed.yml
allowed:
# The following are based on: https://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses
- gpl-1.0-or-later
- gpl-1.0+ # Deprecated ID for `gpl-1.0-or-later`
- gpl-2.0-or-later
- gpl-2.0+ # Deprecated ID for `gpl-2.0-or-later`
- gpl-3.0-only
- gpl-3.0 # Deprecated ID for `gpl-3.0-only`
- gpl-3.0-or-later
- gpl-3.0+ # Deprecated ID for `gpl-3.0-or-later`
- lgpl-2.0-or-later
- lgpl-2.0+ # Deprecated ID for `lgpl-2.0-or-later`
- lgpl-2.1-only
- lgpl-2.1 # Deprecated ID for `lgpl-2.1-only`
- lgpl-2.1-or-later
- lgpl-2.1+ # Deprecated ID for `lgpl-2.1-or-later`
- lgpl-3.0-only
- lgpl-3.0 # Deprecated ID for `lgpl-3.0-only`
- lgpl-3.0-or-later
- lgpl-3.0+ # Deprecated ID for `lgpl-3.0-or-later`
- fsfap
- apache-2.0
- artistic-2.0
- clartistic
- sleepycat
- bsl-1.0
- bsd-3-clause
- cecill-2.0
- bsd-3-clause-clear
# "Cryptix General License" - no SPDX ID (https://github.com/spdx/license-list-XML/issues/456)
- ecos-2.0
- ecl-2.0
- efl-2.0
- eudatagrid
- mit
- bsd-2-clause # Subsumed by `bsd-2-clause-views`
- bsd-2-clause-netbsd # Deprecated ID for `bsd-2-clause`
- bsd-2-clause-views # This is the version linked from https://www.gnu.org/licenses/license-list.html#FreeBSD
- bsd-2-clause-freebsd # Deprecated ID for `bsd-2-clause-views`
- ftl
- hpnd
- imatix
- imlib2
- ijg
# "Informal license" - this is a general class of license
- intel
- isc
- mpl-2.0
- ncsa
# "License of Netscape JavaScript" - no SPDX ID
- oldap-2.7
# "License of Perl 5 and below" - possibly `Artistic-1.0-Perl` ?
- cc0-1.0
- cc-pddc
- psf-2.0
- ruby
- sgi-b-2.0
- smlnj
- standardml-nj # Deprecated ID for `smlnj`
- unicode-dfs-2015
- upl-1.0
- unlicense
- vim
- w3c
- wtfpl
- lgpl-2.0-or-later with wxwindows-exception-3.1
- wxwindows # Deprecated ID for `lgpl-2.0-or-later with wxwindows-exception-3.1`
- x11
- xfree86-1.1
- zlib
- zpl-2.0
- zpl-2.1
# The following are based on individual license text
- eupl-1.2
- liliq-r-1.1
- liliq-rplus-1.1
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.licenses/
/dist/
/lib/
/node_modules/
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ Everything is now ready to make your contribution to the project, so commit it t

Thanks!

## Dependency license metadata

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:

```
task general:cache-dep-licenses
```

The necessary **Licensed** tool can be installed by following [these instructions](https://github.com/github/licensed#as-an-executable).

Unfortunately, **Licensed** does not have support for being used on the **Windows** operating system.

An updated cache is also generated whenever the cache is found to be outdated by the 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).

## Enable verbose logging for a pipeline

Additional log events with the prefix ::debug:: can be enabled by setting the secret `ACTIONS_STEP_DEBUG` to `true`.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[![Check Markdown status](https://github.com/arduino/setup-task/actions/workflows/check-markdown-task.yml/badge.svg)](https://github.com/arduino/setup-task/actions/workflows/check-markdown-task.yml)
[![Spell Check status](https://github.com/arduino/setup-task/actions/workflows/spell-check-task.yml/badge.svg)](https://github.com/arduino/setup-task/actions/workflows/spell-check-task.yml)
[![Check License status](https://github.com/arduino/setup-task/actions/workflows/check-license.yml/badge.svg)](https://github.com/arduino/setup-task/actions/workflows/check-license.yml)
[![Check npm Dependencies status](https://github.com/arduino/setup-task/actions/workflows/check-npm-dependencies-task.yml/badge.svg)](https://github.com/arduino/setup-task/actions/workflows/check-npm-dependencies-task.yml)

A [GitHub Actions](https://docs.github.com/en/actions) action that makes the [Task](https://taskfile.dev/#/) task runner / build tool available to use in your workflow.

Expand Down
42 changes: 40 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,32 @@ tasks:
# This is an "umbrella" task used to call any documentation generation processes the project has.
# It can be left empty if there are none.

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml
general:cache-dep-licenses:
desc: Cache dependency license metadata
deps:
- task: general:install-deps
cmds:
- |
if ! which licensed &>/dev/null; then
if [[ {{OS}} == "windows" ]]; then
echo "Licensed does not have Windows support."
echo "Please use Linux/macOS or download the dependencies cache from the GitHub Actions workflow artifact."
else
echo "licensed not found or not in PATH. Please install: https://github.com/github/licensed#as-an-executable"
fi
exit 1
fi
- licensed cache

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-dependencies-task/Taskfile.yml
general:check-dep-licenses:
desc: Check for unapproved dependency licenses
deps:
- task: general:cache-dep-licenses
cmds:
- licensed status

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/spell-check-task/Taskfile.yml
general:check-spelling:
desc: Check for commonly misspelled words
Expand All @@ -61,6 +87,12 @@ tasks:
cmds:
- npx prettier --write .

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-npm-dependencies-task/Taskfile.yml
general:install-deps:
desc: Install project dependencies
deps:
- task: npm:install-deps

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-markdown-task/Taskfile.yml
markdown:check-links:
desc: Check for broken links
Expand Down Expand Up @@ -118,6 +150,12 @@ tasks:
cmds:
- npx markdownlint-cli "**/*.md"

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/npm-task/Taskfile.yml
npm:install-deps:
desc: Install dependencies managed by npm
cmds:
- npm install

# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/poetry-task/Taskfile.yml
poetry:install-deps:
desc: Install dependencies managed by Poetry
Expand All @@ -141,8 +179,8 @@ tasks:

ts:install-deps:
desc: Install TypeScript dependencies
cmds:
- npm install
deps:
- task: npm:install-deps

ts:lint:
desc: Lint TypeScript code
Expand Down

0 comments on commit aaef6dd

Please sign in to comment.