← Recipes

阅读中文版本

Gate Releases on a Dependency License Allowlist

Inventory production dependency licenses, fail on copyleft licenses outside policy, and keep the report with every release.

~20 minlicensingcomplianceci

Task

Know which licenses ship inside the product and stop a GPL or AGPL dependency from entering a distributed build.

When to use this

A contributor adds a convenience package under AGPL-3.0. It ships in the container, and legal review discovers the obligation only during due diligence.

Prerequisites

  • Node.js 20 or newer for license-checker-rseidelsohn
  • A production-only dependency tree
  • A written license allowlist approved by legal

Steps

1. Generate a production-only license inventory as JSON.

npx license-checker-rseidelsohn --production --json --out licenses.json

Expected output: licenses.json lists every production package with its license and repository URL.

2. Fail the build on disallowed licenses and print a summary.

npx license-checker-rseidelsohn --production --failOn 'GPL-3.0;AGPL-3.0;SSPL-1.0' --summary

Expected output: Exit code 1 and a summary naming each package and the license that triggered the failure.

3. Handle a reviewed exception by package and version, not by disabling a license rule.

npx license-checker-rseidelsohn --production --excludePackages '[email protected]' --failOn 'GPL-3.0;AGPL-3.0' --summary

Expected output: The exception is explicit in the command, scoped to one version, and visible in code review.

4. Archive the report with the release and diff it against the previous release.

diff <(jq -S 'keys' licenses-previous.json) <(jq -S 'keys' licenses.json)

Expected output: New or removed packages appear as diff lines in the release checklist.

Troubleshooting

Problem

A package reports an unknown or missing license

Solution

Some packages declare the license only in a README; add a manual entry citing the upstream license text and re-check it on upgrade.

Problem

Development dependencies fail the build

Solution

Use --production so only distributed code is checked; dev-only tooling does not create distribution obligations.

Limitations

  • Scanners read declared metadata, not the full license text of bundled or vendored code.
  • License obligations are legal questions; treat the allowlist as engineering policy, not legal advice.

Licenses are part of the artifact

A container image distributes every package inside it, and some licenses attach obligations to distribution. A GPL library linked into a shipped binary can require source disclosure; an AGPL service can require offering source to network users. These are not hypothetical review findings, they are commitments the product makes the moment it ships. The only reliable way to keep the commitment intentional is to inventory licenses in CI, where every dependency change is visible before release.

Check what ships

Run the check against the production dependency tree, not the development tree. The dev tree is larger, contains tools that are never distributed, and produces failures nobody can act on. license-checker-rseidelsohn walks the installed tree, reads each package’s declared license, and can fail on a semicolon-separated denylist. Keep the denylist in a file that legal reviews, and let the package-level exception be the only escape hatch.

npx license-checker-rseidelsohn --production \
  --failOn 'GPL-3.0;AGPL-3.0;SSPL-1.0' --summary

Keep the inventory

Attach licenses.json to every release and diff it against the previous one. A diff that lists a new package is easy to review, while a scanner that only fails on a denylist misses the package whose license changed between versions. Exceptions should name a package and version, carry an expiry date, and be removed when the dependency is upgraded, because a blanket exception quietly becomes policy. When a package has no declared license, treat it as unlicensed until proven otherwise, not as permissive.