Skip to content

ForNeVeR/dotnet-licenses

Repository files navigation

dotnet-licenses Status Zero NuGet package

dotnet-licenses is a tool to automate following the requirements and inventorying the lists of the open-source licenses used by the projects that chose to publish artifacts covered by external licenses alongside their own files.

The general approach is inspired by REUSE, but adopted for binary packages.

Different software licenses have different requirements, but most of them require you to bring the copyright information together with any form of distribution.

dotnet-licenses will help you to verify that some license covers every file in your package, and will help the package consumers to determine exactly what file is covered by what.

Installation

Install as a dotnet tool: either

$ dotnet tool install --global FVNever.DotNetLicenses

for global installation or

$ dotnet new tool-manifest
$ dotnet tool install FVNever.DotNetLicenses

for local solution-wide installation.

Usage

After installation, the tool will be available in shell as dotnet licenses.

The following arguments are supported:

  • [print-metadata] <config-file-path> — prints the list of the metadata provided by the configured sources;
  • generate-lock <config-file-path> — generates the license lock file based on the configuration;
  • verify <config-file-path> — verifies the license lock file against the package contents;
  • download-licenses <config-file-path> — downloads the licenses of the entries specified in the lock file.

The command's exit code is 0 if the tool ran successfully and non-zero if there were any issues, including warnings.

Read about the configuration file expected to be found by the <config-file-path> in the section below.

Configuration

Looking to set up the tool for your new project? Check the core concepts documentation article first.

The configuration file format is TOML. The format:

metadata_sources = [# required
    { type = "nuget", include = "path/to/project1.sln/csproj" },
    { type = "license", spdx = "MIT", copyright = "My Copyright", files_covered = "*" },
    { type = "license", spdx = ["MIT"], copyright = ["My Other Copyright"], files_covered = [
        # You can also include lists into this field.
        "*.txt",
        "*.css"
    ], patterns_covered = [
        { type = "msbuild", include = "path/to/project2.csproj" },
        { type = "nuget" }
    ] },
    { type = "reuse", root = ".", exclude = [".idea/"], files_covered = "README.md" },
]
metadata_overrides = [# optional
    { id = "package1", version = "1.0.0", spdx = "MIT", copyright = "Copyright" },
    { id = "package2", version = "2.0.0", spdx = "GPL-3.0", copyright = "Copyright" }
]
lock_file = "path/to/lock-file.toml" # required for generate-lock command
license_storage_path = "path/to/licenses" # required for download-licenses command
packaged_files = [# required for generate-lock
    { type = "directory", path = "bin", ignore = [
        { type = "preset", name = "licenses" }
    ] },
    { type = "zip", path = "bin/*.zip" }
]

Any file paths in the configuration file may be either absolute or relative. Relative paths will be resolved relatively to the configuration file's parent directory.

The metadata_sources parameter (required) is a list of paths to the projects to analyze.

Currently supported metadata sources types are listed below.

  1. type = "nuget", include = "<path/to/project/or/solution>" to extract metadata from NuGet packages used by the designated project or all projects in solution.

    Note that the project must be restored for this to work with transitive dependencies.

  2. type = "license" to provide metadata for the licenses that are not covered by NuGet packages. The id attribute is mandatory and should be unique across all metadata sources. The spdx and copyright attributes are mandatory, and may be either text values or arrays. files_covered (optional) may be a glob mask or a path, applied to the base directory of each declared package, to mark the files covered by the license.

    files_covered may be a single glob or a list of globs, applied relative to the package root of the containing package.

    patterns_covered (optional) is a specification of the file patterns covered by a particular source. The supported patterns are listed below, in the Coverage Patterns Specification section.

  3. type = "reuse" to provide licenses read according to the REUSE specification v 3.0. Attributes:

    • root (required) is the root directory of the REUSE-compliant project,

    • excludes (optional) is a list of paths to exclude from the analysis. For example, you may want to ignore the IDE-generated files or test resources if they have different license. Any path is excluded as a subtree.

    • files_covered (optional) — either a glob or an array of globs. This is optional, and files that are included into the current directory and covered by the REUSE specification are automatically considered as covered in any case. So, this collection should only contain the generated/built files, and not the files that are copied as-is from the REUSE-covered set of files.

      Any file that's copied as-is is considered to be covered by the exact license according to its REUSE specification. Any additional file from files_covered is considered to be covered by the combination of all the licenses in the source (except the excluded files).

    • patterns_covered (optional) is a specification of the file patterns covered by a particular source. Currently supported patterns are listed below, in the Coverage Patterns Specification section.

    Item with type = "reuse" should point to a set of licenses exactly covering the sources from which the covered packaged files are built.

The metadata_overrides parameter (optional) should contain a set of license overrides for incorrectly marked packages in NuGet. Every record contains string fields id, version, spdx, and copyright. All fields are mandatory.

The lock_file parameter (optional) is the path to the license lock file that will be produced or verified by the corresponding commands. This parameter is mandatory for the generate-lock command.

The license_storage_path parameter (optional) is the path to the directory where the tool will download the licenses of the packages used by the lock file. This parameter is mandatory for the download-licenses command.

The packaged_files parameter (optional) describes the list of the files you want to check for their license contents. It is a list of the entries having the following structure:

  • type (required) should be either directory (to point to the root of the file hierarchy that will be processed recursively) or zip, to point to a zip archive that the tool will analyze,
  • path (required) is a path on disk; for zip archives, we support glob patterns,
  • ignore (optional) is a list of ignore specifications, see below. By default, it will be one preset named licenses.

The packaged_files parameter is mandatory for the generate-lock command.

Coverage Patterns Specification

Each cover pattern specification (patterns_covered) is one of the following.

  1. MSBuild coverage pattern:

    { type = "msbuild", include = "path/to/project.csproj/sln" }
    

    where

    • type is always msbuild,
    • include is the path to the project or solution file to cover.

    This pattern will consider the following project outputs, generated by the Release configuration of the project:

    • $(TargetDir)\$(TargetFileName).
    • $(TargetDir)\$(TargetName).runtimeconfig.json.

    Additionally, it will consider files corresponding to the following globs as generated by the project, regardless of their actual contents:

    • **/$(TargetName).pdb,
    • **/$(TargetName).deps.json.
  2. NuGet coverage pattern:

    { type = "nuget" }
    

    this pattern will consider NuGet-generated files to be covered by the license source employing this pattern:

    • [Content_Types].xml,
    • _rels/.rels,
    • package/services/metadata/core-properties/*.psmdcp,
    • *.nuspec.

Ignore Item Specification

Each ignore item specification is a record in form of:

{ type = "preset", name = "licenses" }

where

  • type is always preset,
  • name is the name of the preset to apply.

Currently supported presets (all paths are glob patterns that are applied relatively to the package root; case-insensitive):

  • licenses: ignores LICENSES/*.txt.

Lock File

License lock file looks like this:

"file_name" = [
    { source_id = "FSharp.Core", source_version = "8.0.200", spdx = ["MIT"], copyright = ["© Microsoft Corporation. All rights reserved."] }
]

where

  • file_name is the path of the file (or a glob) relatively to the package root.
  • source_id (optional) is the NuGet package that is the origin of the file, if it originated from a NuGet package.
  • source_version (optional) is the version of the NuGet package, if the file originates from NuGet (note that it only gets filled if a file with same name is provided by several packages, i.e. it only serves the disambiguation purpose — this is done for the lock file to not be updated on every minor dependency version update).
  • spdx (optional for ignored items) is the list of SPDX identifiers of the license.
  • copyright (optional for ignored items) is the list of the copyright statements of the license.
  • is_ignored (optional) marks the items that were explicitly ignored by the user (or default ignore preset) when generating the lock file.

Each file is only covered by one entry (that may contain combined license information about the file).

Note that every file from the package is meant to be covered by the lock file. Orphaned files are not expected.

You are meant to commit the lock file and update it if something in the package contents change.

Documentation

Versioning Notes

This project's versioning follows the Semantic Versioning 2.0.0 specification.

When considering compatible changes, we currently consider the project's public API is the command-line interface:

  • the way of running the project (e.g., the executable file name),
  • the input arguments,
  • the input data formats,
  • and the output data format.

Note that the particular non-zero exit codes are not considered part of the public API.

License

This project's licensing follows the REUSE specification v 3.0. Consult each file's headers and the REUSE specification for possible details.

Contribution Policy

By contributing to this repository, you agree that any new files you contribute will be covered by the MIT license. If you want to contribute a file under a different license, you should clearly mark it in the file's header, according to the REUSE specification.

You are welcome to explicitly state your copyright in the file's header as described in the contributor guide, but the project maintainers may do this for you as well.

Packaged Content Licenses

The NuGet package of this tool bundles several third-party binaries.

The NuGet metadata includes the combined license information.

To figure out the licenses and copyright statements related to every packaged file, see the bundled license lock file (.dotnet-licenses.lock.toml) in the package root. For convenience, the texts of each references license are packed into the LICENSES directory in the package root.