Shifting Compliance Left with Licensed and GitHub Actions
Ensuring compliance with open source software licensing can be challenging for software engineering leaders, but there are great tools available in open source that can help you to get started.
Ensuring compliance with open source software licensing can be challenging for software engineering leaders, but there are great tools available in open source that can help you to get started.
In fact you can easily get started with Licensed and GitHub Actions.
What is Licensed?
Licensed is an open source tool put forward by the good folks at GitHub that will check automatically pull the licenses of many different languages and their dependencies in order to ensure that your organization stays compliant, only allowing software that utilizes the approved licenses by default, and requiring explicit approval to add new licenses, or dependencies without the already approved licenses.
How do I incorporate them into my CI/CD process?
Setup your GitHub Action for this to only run when it detects changes to the lock
files in order to prevent unnecessary runs. It can run on each push to the mainline, or just on pull requests as it's all very quick.
The code
First you need to set up your Licensed config. In this case I'll be setting up a Node.js example.
cache_path: "./.licenses"
sources:
npm: true
# the allowed licenses
allowed:
- mit
Your organization will likely want to expand this list, but that's between you and your leadership/legal folks.
# .github/workflows/ci_licensed.yml
name: Licensed CI
on:
pull_request:
paths:
- "**/*.lock"
- "**/*-lock.json"
branches:
- main
jobs:
licensed:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup node # setup your environment's appropriate language
uses: actions/setup-node@v1
with:
node-version: 14.17.2
- uses: jonabc/setup-licensed@v1
with:
version: '3.x'
- uses: actions/cache@v1 # restore the previous run's cached deps
with:
path: node_modules/
key: ${{ runner.os }}-licensed_deps-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-licensed_deps-${{ hashFiles('package-lock.json') }}
${{ runner.os }}-licensed_deps-
- run: npm install # install dependencies in local environment
- name: Check licenses
run: |
licensed cache
licensed status
And now you're off to the races.
For ease of use in CI I prefer to also commit the licensed cache path, as otherwise cache busting to mark particular license changes as reviewed can be a pain. Otherwise your organization may opt to cache the licensed directory using GitHub Actions cache.
Disclaimer
This is not a substitute for ensuring that you remain compliant with open source licenses through human review, but this can be a great tool to help alert on potential failures early in the process, and given how easy it is to implement is something that I highly recommend for all organizations.