Introduction
When developing software application we include NuGet packages which in turn has software licenses. This license describes how your company should comply when using this software. Keeping track of these licenses can be a challenge.
Let's take an example and look at the NuGet package ImageSharp. A common library used for handling images in .NET. In version 2.x, the license model was Apache-2.0. When bumping this package to 3.x a new license model is used that might require you company to pay for a commercial license.
Keeping track of these can be a daunting task and in this post we will be looking at a tool called dotnet-project-license and how it can help us with this.
dotnet-project-license
Lets start by installing dotnet-project-license:
dotnet tool install --global dotnet-project-licenses
When installed, we can run the --help command:
dotnet-project-licenses --help
This will provide a long list of different options. We will be using the following flags in this example:
- --input: The input, folder/.csproj/.sln or a json file containing a list of projects
- --json: Writes the licenses as and to a json file.
- --package-filters: A way to skip certain packages. We will skip some microsoft packages.
- --transient: Includes transient dependencies
- --unique: Unique licenses list by Id/Version
- --output-directory: Where to place the licenses.json file.
Lets start with a basic command:
dotnet-project-licenses --input [.sln] --json
A licenses.json file will be created. When inspecting this file we can see a JSON array with a license objects inside. For example:
[
{
"PackageName": "coverlet.collector",
"PackageVersion": "3.2.0",
"PackageUrl": "https://github.com/coverlet-coverage/coverlet",
"Copyright": "",
"Authors": ["tonerdo"],
"Description": "Coverlet is a cross platform code coverage library for .NET, with support for line, branch and method coverage.",
"LicenseUrl": "https://licenses.nuget.org/MIT",
"LicenseType": "MIT",
"Repository": {
"Type": "git",
"Url": "https://github.com/coverlet-coverage/coverlet.git",
"Commit": "e2c9d84a84a9d2d240ac15feb70f9198c6f8e173"
}
}
]
Some of the flags for dotnet-project-licenses require JSON files as input. Let's create a folder called /licenses that can contain all of these.
Next, let's create a file called packages-filter.json. This file will be used to filter away packages that we are not going to license check. It uses an array with strings inside to filter away certain packages:
["Microsoft.NET.Test.Sdk", ""]
The same approach is used for the following flags:
- --forbidden-license-types
- --allowed-license-types
- --projects-filter
- --manual-package-information
Now let's use the full command:
dotnet-project-licenses --input [.sln] --packages-filter ./licenses/packages-filter.json --unique --transient --json --output-directory ./licenses
We now have a licenses.json file contained within our ./licenses directory.
CI integration
To prevent the unnoticed inclusion of new licenses, we can add this file to our source code and validated it in our continuous integration process. This ensures that if any disparity arises between the licenses.json file and the one produced during the CI, the pipeline is halted and developer has to review the new licenses before proceeding.
Happy Coding!