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.