Skip to content

Commit 5b8f2a2

Browse files
authored
Configurable check (#150)
* allow to configure the check command * update linter version + fix new lint issues * update readme + change flags for consistency * Don't validate the license names upfront * simplify the interface * add extra usage documentation * add support for unknown licenses * move global usage comment
1 parent 5d4915e commit 5b8f2a2

18 files changed

+427
-54
lines changed

.github/workflows/golangci-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ jobs:
2626
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
2727
# NOTICE: golangci-lint version should be the same as go.mod. When upgrading, also update go.mod by:
2828
# go get github.com/golangci/[email protected]
29-
version: v1.29
29+
version: v1.49

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test: FORCE
1919
go test ./...
2020

2121
# Note, when upgrading, also upgrade version in .github/workflows/golangci-lint.yml.
22-
GOLANGCI_LINT_VERSION=v1.29
22+
GOLANGCI_LINT_VERSION=v1.49
2323
lint: FORCE
2424
@which golangci-lint >/dev/null || ( \
2525
echo 'golangci-lint is not installed. Install by:\ngo install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)' \

README.md

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,19 @@ for licenses considered forbidden.
180180

181181
## Usages
182182

183+
### Global
184+
Typically, specify the Go package that builds your Go binary.
185+
go-licenses expects the same package argument format as `go build`. For examples:
186+
187+
* A rooted import path like `github.com/google/go-licenses` or `github.com/google/go-licenses/licenses`.
188+
* A relative path that denotes the package in that directory, like `.` or `./cmd/some-command`.
189+
190+
To learn more about package argument, run `go help packages`.
191+
192+
To learn more about go-licenses usages, run `go-licenses help`.
193+
194+
### Report
195+
183196
Report usage (default csv output):
184197

185198
```shell
@@ -192,29 +205,46 @@ Report usage (using custom template file):
192205
go-licenses report <package> [package...] --template=<template_file>
193206
```
194207

208+
### Save
209+
195210
Save licenses, copyright notices and source code (depending on license type):
196211

197212
```shell
198213
go-licenses save <package> [package...] --save_path=<save_path>
199214
```
200215

201-
Checking for forbidden licenses usage:
216+
### Check
217+
218+
Checking for forbidden and unknown licenses usage:
202219

203220
```shell
204-
go-licenses check <package> [package...]
221+
go-licenses check <package> [package...]
205222
```
206223

207-
Typically, specify the Go package that builds your Go binary.
208-
go-licenses expects the same package argument format as `go build`. For examples:
224+
Checking for disallowed license types:
209225

210-
* A rooted import path like `github.com/google/go-licenses` or `github.com/google/go-licenses/licenses`.
211-
* A relative path that denotes the package in that directory, like `.` or `./cmd/some-command`.
226+
```shell
227+
go-licenses check <package> [package...] --disallowed_types=<comma separated license types>
228+
```
212229

213-
To learn more about package argument, run `go help packages`.
230+
Supported license types:
231+
* See `forbidden` list: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L341)
232+
* See `notice` list: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L249)
233+
* See `permissive` list: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L321)
234+
* See `reciprocal` list: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L225)
235+
* See `restricted` list: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L185)
236+
* See `unencumbered` list: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L324)
237+
* `unknown`
214238

215-
To learn more about go-licenses usages, run `go-licenses help`.
239+
Allow only specific license names:
240+
241+
```shell
242+
go-licenses check <package> [package...] --allowed_licenses=<comma separated license names>
243+
```
244+
245+
* See supported license names: [github.com/google/licenseclassifier](https://github.com/google/licenseclassifier/blob/e6a9bb99b5a6f71d5a34336b8245e305f5430f99/license_type.go#L28)
216246

217-
## Build tags
247+
### Build tags
218248

219249
To read dependencies from packages with
220250
[build tags](https://golang.org/pkg/go/build/#hdr-Build_Constraints). Use the
@@ -233,7 +263,7 @@ github.com/client9/misspell,https://github.com/client9/misspell/blob/master/LICE
233263
github.com/golang/protobuf/proto,https://github.com/golang/protobuf/blob/master/proto/LICENSE,BSD-3-Clause
234264
```
235265

236-
## Ignoring packages
266+
### Ignoring packages
237267

238268
Use the `--ignore` global flag to specify package path prefixes to be ignored.
239269
For example, to ignore your organization's internal packages under `github.com/example-corporation`:

check.go

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,57 @@ package main
1616

1717
import (
1818
"context"
19+
"errors"
1920
"fmt"
2021
"os"
22+
"strings"
2123

2224
"github.com/google/go-licenses/licenses"
2325
"github.com/spf13/cobra"
26+
"golang.org/x/text/cases"
27+
"golang.org/x/text/language"
2428
)
2529

2630
var (
27-
checkHelp = "Checks whether licenses for a package are not Forbidden."
31+
checkHelp = "Checks whether licenses for a package are not allowed."
2832
checkCmd = &cobra.Command{
2933
Use: "check <package> [package...]",
3034
Short: checkHelp,
3135
Long: checkHelp + packageHelp,
3236
Args: cobra.MinimumNArgs(1),
3337
RunE: checkMain,
3438
}
39+
40+
allowedLicenses []string
41+
disallowedTypes []string
3542
)
3643

3744
func init() {
45+
checkCmd.Flags().StringSliceVar(&allowedLicenses, "allowed_licenses", []string{}, "list of allowed license names, can't be used in combination with disallowed_types")
46+
checkCmd.Flags().StringSliceVar(&disallowedTypes, "disallowed_types", []string{}, "list of disallowed license types, can't be used in combination with allowed_licenses (default: forbidden, unknown)")
47+
3848
rootCmd.AddCommand(checkCmd)
3949
}
4050

4151
func checkMain(_ *cobra.Command, args []string) error {
52+
var disallowedLicenseTypes []licenses.Type
53+
54+
allowedLicenseNames := getAllowedLicenseNames()
55+
disallowedLicenseTypes = getDisallowedLicenseTypes()
56+
57+
hasLicenseNames := len(allowedLicenseNames) > 0
58+
hasLicenseType := len(disallowedLicenseTypes) > 0
59+
60+
if hasLicenseNames && hasLicenseType {
61+
return errors.New("allowed_licenses && disallowed_types can't be used at the same time")
62+
}
63+
64+
if !hasLicenseNames && !hasLicenseType {
65+
// fallback to original behaviour to avoid breaking changes
66+
disallowedLicenseTypes = []licenses.Type{licenses.Forbidden, licenses.Unknown}
67+
hasLicenseType = true
68+
}
69+
4270
classifier, err := licenses.NewClassifier(confidenceThreshold)
4371
if err != nil {
4472
return err
@@ -58,8 +86,18 @@ func checkMain(_ *cobra.Command, args []string) error {
5886
return err
5987
}
6088

61-
if licenseType == licenses.Forbidden {
62-
fmt.Fprintf(os.Stderr, "Forbidden license type %s for library %v\n", licenseName, lib)
89+
if hasLicenseNames && !isAllowedLicenseName(licenseName, allowedLicenseNames) {
90+
fmt.Fprintf(os.Stderr, "Not allowed license %s found for library %v\n", licenseName, lib)
91+
found = true
92+
}
93+
94+
if hasLicenseType && isDisallowedLicenseType(licenseType, disallowedLicenseTypes) {
95+
fmt.Fprintf(
96+
os.Stderr,
97+
"%s license type %s found for library %v\n",
98+
cases.Title(language.English).String(licenseType.String()),
99+
licenseName,
100+
lib)
63101
found = true
64102
}
65103
}
@@ -70,3 +108,72 @@ func checkMain(_ *cobra.Command, args []string) error {
70108

71109
return nil
72110
}
111+
112+
func getDisallowedLicenseTypes() []licenses.Type {
113+
if len(disallowedTypes) == 0 {
114+
return []licenses.Type{}
115+
}
116+
117+
excludedLicenseTypes := make([]licenses.Type, 0)
118+
119+
for _, v := range disallowedTypes {
120+
switch strings.TrimSpace(strings.ToLower(v)) {
121+
case "forbidden":
122+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Forbidden)
123+
case "notice":
124+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Notice)
125+
case "permissive":
126+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Permissive)
127+
case "reciprocal":
128+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Reciprocal)
129+
case "restricted":
130+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Restricted)
131+
case "unencumbered":
132+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Unencumbered)
133+
case "unknown":
134+
excludedLicenseTypes = append(excludedLicenseTypes, licenses.Unknown)
135+
default:
136+
fmt.Fprintf(
137+
os.Stderr,
138+
"Unknown license type '%s' provided.\n"+
139+
"Allowed types: forbidden, notice, permissive, reciprocal, restricted, unencumbered, unknown\n",
140+
v)
141+
}
142+
}
143+
144+
return excludedLicenseTypes
145+
}
146+
147+
func isDisallowedLicenseType(licenseType licenses.Type, excludedLicenseTypes []licenses.Type) bool {
148+
for _, excluded := range excludedLicenseTypes {
149+
if excluded == licenseType {
150+
return true
151+
}
152+
}
153+
154+
return false
155+
}
156+
157+
func getAllowedLicenseNames() []string {
158+
if len(allowedLicenses) == 0 {
159+
return []string{}
160+
}
161+
162+
var allowed []string
163+
164+
for _, licenseName := range allowedLicenses {
165+
allowed = append(allowed, strings.TrimSpace(licenseName))
166+
}
167+
168+
return allowed
169+
}
170+
171+
func isAllowedLicenseName(licenseName string, allowedLicenseNames []string) bool {
172+
for _, allowed := range allowedLicenseNames {
173+
if allowed == licenseName {
174+
return true
175+
}
176+
}
177+
178+
return false
179+
}

0 commit comments

Comments
 (0)