Go Dependency License Compliance#
CloudNativePG manages two overlapping but distinct scans for Go dependency licenses: go-licenses (covers the full module graph) and Snyk (vulnerability + license scanning). A key nuance is that Go module tooling does not distinguish test-only imports from production imports in go.mod—every require directive is visible to scanners regardless of whether the dependency ends up in the shipped binary.
The pgregory.net/rapid MPL-2.0 Case#
pgregory.net/rapid v1.3.0 was added to go.mod by PR #11494 as a direct dependency for property-based tests in pkg/postgres/status_rapid_test.go. It was imported only in that single _test.go file and was not linked into the operator binary or image.
Despite being test-only, pgregory.net/rapid appeared as a direct require in go.mod, which meant:
- Downstream SCA tools saw it. Snyk flagged it as
SNYK:LIC:GOLANG:PGREGORY.NET:RAPID:MPL-2.0in theplugin-barman-cloudrepo's PR checks, attributed viagithub.com/cloudnative-pg/cloudnative-pg@v1.30.1. Any project depending on the CloudNativePG module inherited the finding. - go-licenses did not surface it. The
licenses/go-licensesdirectory had nopgregory.net/entry. Themake licensestarget runsgo-licenses save ./..., which skips test-only imports when determining what to save.
This divergence is by design in go-licenses (it tracks packages that appear in the compiled binary), while Snyk inspects the raw module graph and flags any go.mod entry with a non-permissive license.
The issue was tracked in #11591. The MPL-2.0 compliance issue was resolved in PR #11592, which replaced pgregory.net/rapid with a deterministic standard-library seeded loop in pkg/postgres/status_property_test.go. Each iteration uses its index as seed for reproducibility. The dependency was removed from go.mod entirely.
License Scanning Infrastructure#
| Tool | Trigger | Scope | Output |
|---|---|---|---|
| go-licenses | Weekly schedule + workflow_dispatch via refresh-licenses.yml; make licenses | Full ./... module graph, compiled-binary perspective | licenses/go-licenses/ directory, auto-PRed |
| Snyk | Push to main + workflow_dispatch via snyk.yml | Static code analysis + raw go.mod module graph | SARIF uploaded to GitHub Code Scanning |
make licenses (Makefile:382–389):
- Runs
$(GO_LICENSES) save ./... --save_path licenses/go-licenses --force || true - The
|| trueis intentional:go-licensesexits non-zero because it cannot identify the project's own Apache-2.0 license header. - Removes
.modand.gofiles from the output, keeping only license text files. - A weekly GitHub Actions workflow (
refresh-licenses.yml) runsmake licensesand opens an automated PR if the result changes.
Snyk (snyk.yml):
- Runs two steps:
snyk code test(static analysis →snyk-static.sarif) andsnyk test(dependency/license scan →snyk-test.sarif). - The
GOTOOLCHAIN: autoenv var is set sogo listcan fetch a newer toolchain than what is bundled in the Snyk Docker image. - Both steps use
continue-on-error: true; findings are uploaded to GitHub Code Scanning rather than hard-failing the build.
Key Nuances for Engineers and SCA Operators#
-
Test-only ≠absent from module graph. A dependency used only in
_test.gofiles is still a directrequireingo.modand will appear in Snyk findings. -
go-licenses and Snyk do not agree by design.
go-licensesoperates on compiled packages; Snyk scans the raw dependency manifest. Expect Snyk to surface licenses thatgo-licensesomits. -
Downstream consumers inherit the finding. If a library (e.g.,
plugin-barman-cloud) imports CloudNativePG as a module, its Snyk scan will include all of CloudNativePG'sgo.modentries—including test-only ones. -
MPL-2.0 is not on the CNCF allowlist (to maintainers' knowledge). Even for test-only use, a resolution (replacing the dependency or obtaining an explicit exception) is required.
-
Prefer stdlib or Apache/MIT-licensed test helpers to avoid introducing non-permissive licenses into the module graph. The
rapidMPL-2.0 dependency was removed by replacing it with a standard-library seeded loop rather than seeking an exception.
Key Files#
| Path | Purpose |
|---|---|
go.mod | Module graph; all require entries are visible to SCA tools |
Makefile (licenses target) | Runs go-licenses save ./... |
.github/workflows/refresh-licenses.yml | Weekly automation for make licenses + auto-PR |
.github/workflows/snyk.yml | Snyk static + dependency scan on push to main |
licenses/go-licenses/ | Checked-in license texts for compiled dependencies |
pkg/postgres/status_property_test.go | Property-based tests using stdlib random generation; replaced the former status_rapid_test.go (which used pgregory.net/rapid) in PR #11592 |