Dependencies

Attribution and NOTICE

Generate the third-party attribution document — components, licenses, copyright holders and license texts — deterministically, with a CI gate that catches it going stale.

Attribution and NOTICE

xgrep deps notice generates the attribution document that ships with a product: every third-party component, the license it is distributed under, the copyright notices to reproduce, and the full license text where the dependency ships one.

xgrep deps notice .                          # plain-text NOTICE on stdout
xgrep deps notice --format markdown .        # text | markdown | html | json | csv
xgrep deps notice -o NOTICE .                # write to a file
xgrep deps notice --check NOTICE .           # CI: fail if it is out of date

Where the content comes from

Licenses come from the same two signals the license check uses — the license declared in a manifest, and the license concluded from SPDX-License-Identifier headers and the license files shipped with vendored dependencies. Copyright holders are read from those same license and NOTICE files.

When the two license signals disagree, the document attributes the concluded license and shows the declared one beside it. A notice should credit what you actually ship:

sneaky 1.0.0
License: AGPL-3.0-only (its manifest declares MIT)

Curations and license choices from your policy file apply here too, so a package the team has already ruled on is attributed the way it was ruled on. The attribution and the compliance gate can never disagree about a package — both go through the same assessment.

Components with no license

A component whose license could not be determined gets its own section rather than being dropped:

Components with no license determined
--------------------------------------------------------------------------------
  - lodash 4.17.21
      Copyright 2012-2020 The lodash authors

An attribution document that silently omits what it could not resolve is worse than one that says so. Any copyright statements found are still shown, since those need crediting regardless.

--license-full resolves most of these: it identifies a license by matching the text of its license file against an embedded corpus of every SPDX license, which covers the many dependencies whose LICENSE is prose with no identifier in it.

Keeping it current in CI

Output is deterministic: the same tree produces byte-identical output every run, so the document can be committed and reviewed as a diff. --check compares a committed file against a freshly generated one:

xgrep deps notice --check NOTICE .

It exits 0 when the file is current and 1 when it is not, naming the command to regenerate it. A trailing-newline difference is ignored, so an editor or a pre-commit hook cannot cause a false alarm.

$ xgrep deps notice --check NOTICE .
NOTICE is up to date (2 components, digest 6d04b8c5c099)

$ xgrep deps notice --check NOTICE .
NOTICE is out of date: regenerate it with `xgrep deps notice --format text -o NOTICE`

The digest covers what is attributed — the component set, their licenses, copyright statements and license texts. Retitling the document or refreshing the embedded SPDX license list does not change it.

Custom formats

--template renders through your own Go text/template, for teams whose attribution document has a required house format:

{{ range .Components }}{{ .Name }} {{ .Version }} — {{ licenseOf . }}
{{ range .Copyrights }}    {{ . }}
{{ end }}{{ end }}

The template receives the document, whose fields are the same ones the json format emits. licenseOf renders NOASSERTION for a component with no license determined.

Flags

FlagDescription
--format <name>text (default), markdown, html, json, csv.
-o, --output <file>Write to a file instead of stdout.
--check <file>Compare against an existing document; exit 1 if out of date.
--title <text>Document title (default: "Third-party notices").
--template <file>Render through a Go text/template instead of a built-in format.
--license-fullAlso identify licenses by matching license-file text against the embedded SPDX corpus.
--no-license-textList components, licenses and copyrights without the full license texts.
--policy <file>Policy YAML, for curations and license choices.
--ref <git-ref>Read files from a commit, tag, or branch instead of the working tree.
--ecosystem <list>Restrict to named ecosystems, e.g. go,npm.

This generates a document from what it can read in your tree. Whether it satisfies your obligations is a question for your own counsel.

On this page