Skip to content

Commit cbc2134

Browse files
authored
Merge pull request #1013 from ryancurrah/add-gomodguard-linter
added new linter gomodguard
2 parents 789d200 + 68a7129 commit cbc2134

File tree

9 files changed

+181
-0
lines changed

9 files changed

+181
-0
lines changed

.golangci.example.yml

+12
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ linters-settings:
151151
mnd:
152152
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
153153
checks: argument,case,condition,operation,return,assign
154+
gomodguard:
155+
allowed:
156+
modules: # List of allowed modules
157+
# - gopkg.in/yaml.v2
158+
domains: # List of allowed module domains
159+
# - golang.org
160+
blocked:
161+
modules: # List of blocked modules
162+
# - github.com/uudashr/go-module: # Blocked module
163+
# recommendations: # Recommended modules that should be used instead (Optional)
164+
# - golang.org/x/mod
165+
# reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
154166
govet:
155167
# report about shadowed variables
156168
check-shadowing: true

README.md

+15
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ gofmt: Gofmt checks whether code was gofmt-ed. By default this tool runs with -s
221221
goimports: Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true]
222222
golint: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false]
223223
gomnd: An analyzer to detect magic numbers. [fast: true, auto-fix: false]
224+
gomodguard: Allow and block list linter for direct Go module dependencies. [fast: true, auto-fix: false]
224225
goprintffuncname: Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
225226
gosec (gas): Inspects source code for security problems [fast: true, auto-fix: false]
226227
interfacer: Linter that suggests narrower interface types [fast: true, auto-fix: false]
@@ -487,6 +488,7 @@ golangci-lint help linters
487488
- [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines!
488489
- [goprintffuncname](https://github.com/jirfag/go-printf-func-name) - Checks that printf-like functions are named with `f` at the end
489490
- [gomnd](https://github.com/tommy-muehle/go-mnd) - An analyzer to detect magic numbers.
491+
- [gomodguard](https://github.com/ryancurrah/gomodguard) - Allow and block list linter for direct Go module dependencies.
490492
- [godot](https://github.com/tetafro/godot) - Check if comments end in a period
491493
492494
## Configuration
@@ -761,6 +763,18 @@ linters-settings:
761763
mnd:
762764
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
763765
checks: argument,case,condition,operation,return,assign
766+
gomodguard:
767+
allowed:
768+
modules: # List of allowed modules
769+
# - gopkg.in/yaml.v2
770+
domains: # List of allowed module domains
771+
# - golang.org
772+
blocked:
773+
modules: # List of blocked modules
774+
# - github.com/uudashr/go-module: # Blocked module
775+
# recommendations: # Recommended modules that should be used instead (Optional)
776+
# - golang.org/x/mod
777+
# reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
764778
govet:
765779
# report about shadowed variables
766780
check-shadowing: true
@@ -1264,6 +1278,7 @@ Thanks to developers and authors of used linters:
12641278
- [bombsimon](https://github.com/bombsimon)
12651279
- [jirfag](https://github.com/jirfag)
12661280
- [tommy-muehle](https://github.com/tommy-muehle)
1281+
- [ryancurrah](https://github.com/ryancurrah)
12671282
- [tetafro](https://github.com/tetafro)
12681283
12691284
## Changelog

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ require (
3030
github.com/mitchellh/go-homedir v1.1.0
3131
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b
3232
github.com/pkg/errors v0.8.1
33+
github.com/ryancurrah/gomodguard v1.0.2
3334
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83
3435
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada // v2.19.8
3536
github.com/sirupsen/logrus v1.4.2

go.sum

+11
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUD
6868
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
6969
github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA=
7070
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
71+
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
7172
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
7273
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
7374
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b h1:ekuhfTjngPhisSjOJ0QWKpPQE8/rbknHaes6WVJj5Hw=
@@ -196,6 +197,7 @@ github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
196197
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
197198
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
198199
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
200+
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
199201
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
200202
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
201203
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -215,6 +217,12 @@ github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:
215217
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
216218
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
217219
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
220+
github.com/ryancurrah/gomodguard v1.0.0 h1:8bN8VUp6VLagAt8WpDwBuztk6axd43VjtxYDJp+3ykQ=
221+
github.com/ryancurrah/gomodguard v1.0.0/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE=
222+
github.com/ryancurrah/gomodguard v1.0.1 h1:bJQqszMqi0EqsxuQB55rjFQnLjOirbAL0Ww4WyT0IiM=
223+
github.com/ryancurrah/gomodguard v1.0.1/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE=
224+
github.com/ryancurrah/gomodguard v1.0.2 h1:vumZpZardqQ9EfFIZDNEpKaMxfqqEBMhu0uSRcDO5x4=
225+
github.com/ryancurrah/gomodguard v1.0.2/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE=
218226
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83 h1:AtnWoOvTioyDXFvu96MWEeE8qj4COSQnJogzLy/u41A=
219227
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE=
220228
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada h1:WokF3GuxBeL+n4Lk4Fa8v9mbdjlrl7bHuneF4N1bk2I=
@@ -299,6 +307,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
299307
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
300308
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
301309
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
310+
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
311+
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
302312
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
303313
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
304314
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -348,6 +358,7 @@ golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBn
348358
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
349359
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
350360
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
361+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
351362
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
352363
golang.org/x/tools v0.0.0-20200102140908-9497f49d5709 h1:AfG1EmoRkFK24HWWLxSrRKNg2G+oA3JVOG8GJsHWypQ=
353364
golang.org/x/tools v0.0.0-20200102140908-9497f49d5709/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=

pkg/config/config.go

+12
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ type LintersSettings struct {
187187
RowsErrCheck struct {
188188
Packages []string
189189
}
190+
Gomodguard struct {
191+
Allowed struct {
192+
Modules []string `mapstructure:"modules"`
193+
Domains []string `mapstructure:"domains"`
194+
} `mapstructure:"allowed"`
195+
Blocked struct {
196+
Modules []map[string]struct {
197+
Recommendations []string `mapstructure:"recommendations"`
198+
Reason string `mapstructure:"reason"`
199+
} `mapstructure:"modules"`
200+
} `mapstructure:"blocked"`
201+
}
190202

191203
WSL WSLSettings
192204
Lll LllSettings

pkg/golinters/gomodguard.go

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package golinters
2+
3+
import (
4+
"log"
5+
"os"
6+
"sync"
7+
8+
"github.com/ryancurrah/gomodguard"
9+
"golang.org/x/tools/go/analysis"
10+
11+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
12+
"github.com/golangci/golangci-lint/pkg/lint/linter"
13+
"github.com/golangci/golangci-lint/pkg/result"
14+
)
15+
16+
const (
17+
gomodguardName = "gomodguard"
18+
)
19+
20+
// NewGomodguard returns a new Gomodguard linter.
21+
func NewGomodguard() *goanalysis.Linter {
22+
var (
23+
issues []goanalysis.Issue
24+
mu = sync.Mutex{}
25+
analyzer = &analysis.Analyzer{
26+
Name: goanalysis.TheOnlyAnalyzerName,
27+
Doc: goanalysis.TheOnlyanalyzerDoc,
28+
}
29+
)
30+
31+
return goanalysis.NewLinter(
32+
gomodguardName,
33+
"Allow and block list linter for direct Go module dependencies.",
34+
[]*analysis.Analyzer{analyzer},
35+
nil,
36+
).WithContextSetter(func(lintCtx *linter.Context) {
37+
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
38+
var (
39+
files = []string{}
40+
linterCfg = lintCtx.Cfg.LintersSettings.Gomodguard
41+
processorCfg = gomodguard.Configuration{}
42+
)
43+
processorCfg.Allowed.Modules = linterCfg.Allowed.Modules
44+
processorCfg.Allowed.Domains = linterCfg.Allowed.Domains
45+
for n := range linterCfg.Blocked.Modules {
46+
for k, v := range linterCfg.Blocked.Modules[n] {
47+
m := gomodguard.BlockedModule{k: gomodguard.Recommendations{
48+
Recommendations: v.Recommendations,
49+
Reason: v.Reason,
50+
}}
51+
processorCfg.Blocked.Modules = append(processorCfg.Blocked.Modules, m)
52+
break
53+
}
54+
}
55+
56+
for _, file := range pass.Files {
57+
files = append(files, pass.Fset.Position(file.Pos()).Filename)
58+
}
59+
60+
processor, err := gomodguard.NewProcessor(processorCfg, log.New(os.Stderr, "", 0))
61+
if err != nil {
62+
lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+
63+
"it is suggested to disable this linter", err)
64+
return nil, nil
65+
}
66+
67+
gomodguardErrors := processor.ProcessFiles(files)
68+
if len(gomodguardErrors) == 0 {
69+
return nil, nil
70+
}
71+
72+
mu.Lock()
73+
defer mu.Unlock()
74+
75+
for _, err := range gomodguardErrors {
76+
issues = append(issues, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
77+
FromLinter: gomodguardName,
78+
Pos: err.Position,
79+
Text: err.Reason,
80+
}, pass))
81+
}
82+
83+
return nil, nil
84+
}
85+
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
86+
return issues
87+
}).WithLoadMode(goanalysis.LoadModeSyntax)
88+
}

pkg/lint/lintersdb/manager.go

+4
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
247247
linter.NewConfig(golinters.NewGoMND(m.cfg)).
248248
WithPresets(linter.PresetStyle).
249249
WithURL("https://github.com/tommy-muehle/go-mnd"),
250+
linter.NewConfig(golinters.NewGomodguard()).
251+
WithPresets(linter.PresetStyle).
252+
WithLoadForGoAnalysis().
253+
WithURL("https://github.com/ryancurrah/gomodguard"),
250254
linter.NewConfig(golinters.NewGodot()).
251255
WithPresets(linter.PresetStyle).
252256
WithURL("https://github.com/tetafro/godot"),

test/testdata/configs/gomodguard.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
linters-settings:
2+
gomodguard:
3+
allowed:
4+
modules: # List of allowed modules
5+
- golang.org/x/mod/modfile
6+
blocked:
7+
modules: # List of blocked modules
8+
- gopkg.in/yaml.v2: # Blocked module
9+
recommendations: # Recommended modules that should be used instead (Optional)
10+
- github.com/kylelemons/go-gypsy
11+
reason: "This is an example of recommendations." # Reason why the recommended module should be used (Optional)

test/testdata/gomodguard.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//args: -Egomodguard
2+
//config_path: testdata/configs/gomodguard.yml
3+
package testdata
4+
5+
import (
6+
"log"
7+
8+
"golang.org/x/mod/modfile"
9+
"gopkg.in/yaml.v2" // ERROR : "import of package `gopkg.in/yaml.v2` is blocked because the module is in the blocked modules list. `github.com/kylelemons/go-gypsy` is a recommended module. This is an example of recommendations."
10+
)
11+
12+
// Something just some struct
13+
type Something struct{}
14+
15+
func aAllowedImport() { // nolint: deadcode,unused
16+
mfile, _ := modfile.Parse("go.mod", []byte{}, nil)
17+
18+
log.Println(mfile)
19+
}
20+
21+
func aBlockedImport() { // nolint: deadcode,unused
22+
data := []byte{}
23+
something := Something{}
24+
_ = yaml.Unmarshal(data, &something)
25+
26+
log.Println(data)
27+
}

0 commit comments

Comments
 (0)