GitLab CI doesn’t just run your tests; it can be your first line of defense against license compliance nightmares.

Let’s see how it works with a practical example. Imagine a simple Node.js project. We want to ensure all its dependencies have licenses we’re comfortable with.

stages:
  - build
  - test
  - compliance

variables:
  NODE_IMAGE: node:18-alpine

build:
  stage: build
  image: $NODE_IMAGE
  script:
    - echo "Building the project..."
    - npm install
  artifacts:
    paths:
      - node_modules/

test:
  stage: test
  image: $NODE_IMAGE
  script:
    - echo "Running tests..."
    - npm test

license_compliance:
  stage: compliance
  image: docker:latest # Using a Docker image that has tools installed
  services:
    - docker:dind # Docker-in-Docker to run nested containers
  script:
    - apk add --no-cache git # Install git to clone the compliance tool
    - git clone https://github.com/license-checker/license-checker.git /tmp/license-checker
    - cd /tmp/license-checker
    - npm install
    - cd ../.. # Go back to the project root
    - npm run build # Ensure node_modules are available if not artifacted
    - node /tmp/license-checker/bin/license-checker --summary --start . --production --exclude "MIT,ISC,Apache-2.0"

This pipeline first builds and tests the application. The license_compliance stage is where the magic happens. We’re using license-checker, a popular Node.js tool, to scan our node_modules and report on licenses.

The core problem this solves is avoiding legal risk. Using open-source software without understanding its license can lead to intellectual property disputes, forced code disclosure, or even lawsuits. By automating this check in CI, you catch potential issues before they ever reach production.

Internally, license-checker works by traversing your node_modules directory, examining the package.json of each dependency, and cross-referencing the licenses field (or inferring from other fields if licenses is missing) against a known list of license types. It then flags any licenses that don’t match your predefined "allowed" list.

The key levers you control are the exclude flag in the license-checker command. Here, we’re excluding MIT, ISC, and Apache-2.0, which are generally permissive. You’d adjust this list based on your organization’s legal counsel’s guidance. You can also use --production to only check direct production dependencies, or remove it to check development dependencies as well.

A common misconception is that just checking for "MIT" or "Apache" is enough. However, many licenses have subtle variations or require specific attribution. Tools like FOSSA or Black Duck offer more advanced, commercial solutions that can parse the full license text and check for compliance with specific clauses, not just the license type.

The next hurdle you’ll face is integrating this into a larger compliance workflow, potentially involving manual review for borderline licenses or generating Software Bill of Materials (SBOMs).

Want structured learning?

Take the full Gitlab course →