Skip to content

Commit 5bd3592

Browse files
committed
feat: implement v2.0 with layered matching strategy and configuration schema
- Introduce a map-based configuration schema for Allowed and Blocked modules. - Implement a layered evaluation strategy (Exact > Prefix > Regex) for deterministic results. - Add support for regex matching and longest-prefix matching. - Refactor internal core to use a new Matcher interface and semver/v3 for version constraints. - Restructure project to move binary source to cmd/gomodguard. - Update CI/CD with a GitHub Action for automated releases using GoReleaser. - Add a migration guide and updated documentation to the README. - Modernize Makefile with improved linting, testing, and tagging targets. BREAKING CHANGE: The configuration schema has changed from lists to maps, and the matching logic has been overhauled. Existing v1 configurations require migration using the `gomodguard migrate` command.
1 parent c40093e commit 5bd3592

67 files changed

Lines changed: 1353 additions & 1457 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "cmd/gomodguard/v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v5
16+
with:
17+
fetch-depth: 0
18+
19+
- uses: actions/setup-go@v6
20+
with:
21+
go-version: stable
22+
23+
- name: Login to Docker Hub
24+
uses: docker/login-action@v3
25+
with:
26+
username: ${{ secrets.DOCKERHUB_USERNAME }}
27+
password: ${{ secrets.DOCKERHUB_TOKEN }}
28+
29+
- name: Run GoReleaser
30+
uses: goreleaser/goreleaser-action@v6
31+
with:
32+
version: "~> v2"
33+
args: release --clean
34+
workdir: cmd/gomodguard
35+
env:
36+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.golangci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ linters:
55
disable:
66
- lll
77
- gomodguard
8+
- gomoddirectives
89
- gochecknoglobals
910
- paralleltest
1011
- varnamelen
@@ -27,4 +28,3 @@ linters:
2728
rules:
2829
- name: package-comments
2930
disabled: true
30-

.goreleaser.yml

Lines changed: 0 additions & 37 deletions
This file was deleted.

Dockerfile

Lines changed: 0 additions & 13 deletions
This file was deleted.

Makefile

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
current_dir = $(shell pwd)
22

3+
.PHONY: goimports
4+
goimports:
5+
find . -name '*.go' -exec goimports -w -local github.com/ryancurrah/gomodguard {} +
6+
37
.PHONY: lint
48
lint:
59
golangci-lint run ./...
10+
cd cmd/gomodguard && golangci-lint run ./...
611

712
.PHONY: build
813
build:
9-
go build -o "$$(go env GOPATH)/bin/gomodguard" cmd/gomodguard/main.go
14+
cd cmd/gomodguard && go build -o "$$(go env GOPATH)/bin/gomodguard" main.go
1015

1116
.PHONY: run
1217
run: build
1318
./gomodguard
1419

1520
.PHONY: test
1621
test:
17-
go test -v -coverprofile coverage.out
22+
go test -v -coverprofile coverage.out
23+
cd cmd/gomodguard && go test -v -coverprofile coverage.out ./...
24+
cat cmd/gomodguard/coverage.out | tail -n +2 >> coverage.out
1825

1926
.PHONY: cover
2027
cover:
@@ -26,16 +33,25 @@ dockerrun: dockerbuild
2633

2734
.PHONY: snapshot
2835
snapshot:
29-
goreleaser --clean --snapshot
36+
cd cmd/gomodguard && goreleaser --clean --snapshot
3037

3138
.PHONY: release
3239
release:
33-
goreleaser --clean
40+
cd cmd/gomodguard && goreleaser --clean
3441

3542
.PHONY: clean
3643
clean:
3744
rm -rf dist/
3845
rm -f gomodguard coverage.xml coverage.out
46+
rm -f cmd/gomodguard/coverage.out
47+
48+
.PHONY: tag
49+
tag:
50+
@current=$$(git tag --sort=-v:refname --list 'v*' | head -n1 || echo "none"); \
51+
read -p "Current version: $$current. Enter new version: " version; \
52+
git tag "$$version" && \
53+
git tag "cmd/gomodguard/$$version" && \
54+
git push origin "$$version" "cmd/gomodguard/$$version"
3955

4056
.PHONY: install-mac-tools
4157
install-tools-mac:

README.md

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,66 @@ If the linted module imports a blocked module but the linted module is in the re
2626

2727
Version constraints can be specified for modules as well which lets you block new or old versions of modules or specific versions.
2828

29+
When multiple rules can match the same module (e.g., overlapping exact, prefix, and regex rules), they are evaluated using a layered strategy for deterministic results:
30+
31+
1. **Exact match** — highest priority; wins over prefix and regex.
32+
2. **Prefix match** — next priority; longest matching prefix wins.
33+
3. **Regex match** — lowest priority; evaluated in alphabetical key order; first match wins.
34+
2935
Results are printed to `stdout`.
3036

3137
Logging statements are printed to `stderr`.
3238

3339
Results can be exported to different report formats. Which can be imported into CI tools. See the help section for more information.
3440

35-
## Configuration
41+
# Configuration
3642

3743
```yaml
3844
allowed:
39-
modules: # List of allowed modules
40-
- gopkg.in/yaml.v3
41-
- github.com/go-xmlfmt/xmlfmt
42-
- github.com/phayes/checkstyle
43-
- github.com/mitchellh/go-homedir
44-
- github.com/confluentinc/confluent-kafka-go/v2 # Allow v2 only
45-
prefixes: # List of allowed module prefixes (Replaced domains which is now deprecated)
46-
- golang.org # Allow all golang.org modules
47-
- github.com/kubernetes # Allow all Kubernetes modules
48-
- github.com/apache/arrow-go # Allow all Apache Arrow module major versions
45+
go.yaml.in/yaml/v4:
46+
github.com/go-xmlfmt/xmlfmt:
47+
github.com/confluentinc/confluent-kafka-go/v2:
48+
version: "== 2.5.0"
49+
github.com/kubernetes:
50+
match_type: prefix
51+
github.com/apache/arrow-go:
52+
match_type: prefix
53+
"github.com/somecompany/.*":
54+
match_type: regex
4955

5056
blocked:
51-
modules: # List of blocked modules
52-
- github.com/uudashr/go-module: # Blocked module
53-
recommendations: # Recommended modules that should be used instead (Optional)
54-
- golang.org/x/mod
55-
reason: "`mod` is the official go.mod parser library." # Reason why the recommended module should be used (Optional)
56-
versions: # List of blocked module version constraints.
57-
- github.com/mitchellh/go-homedir: # Blocked module with version constraint.
58-
version: "<= 1.1.0" # Version constraint, see https://github.com/Masterminds/semver#basic-comparisons.
59-
reason: "testing if blocked version constraint works." # Reason why the version constraint exists.
57+
github.com/uudashr/go-module:
58+
match_type: exact # or regex, prefix
59+
recommendations:
60+
- golang.org/x/mod
61+
reason: "`mod` is the official go.mod parser library."
62+
github.com/mitchellh/go-homedir:
63+
version: "<= 1.1.0"
64+
reason: "testing if blocked version constraint works."
65+
"github.com/badcompany/.*":
66+
match_type: regex
67+
reason: "No badcompany packages are permitted."
68+
```
69+
70+
## Example .gomodguard.yaml Files
71+
72+
The following example configuration files are available:
73+
74+
- [examples/alloptions/.gomodguard.yaml](examples/alloptions/.gomodguard.yaml)
75+
- [examples/allowedversion/.gomodguard.yaml](examples/allowedversion/.gomodguard.yaml)
76+
- [examples/emptyallowlist/.gomodguard.yaml](examples/emptyallowlist/.gomodguard.yaml)
77+
- [examples/indirectdep/.gomodguard.yaml](examples/indirectdep/.gomodguard.yaml)
78+
- [examples/majorversion/.gomodguard.yaml](examples/majorversion/.gomodguard.yaml)
79+
- [examples/regexversion/.gomodguard.yaml](examples/regexversion/.gomodguard.yaml)
80+
- [examples/regextest/.gomodguard.yaml](examples/regextest/.gomodguard.yaml)
81+
82+
### Migrating from v1
83+
84+
If you have a v1 `.gomodguard.yaml` file, you can automatically migrate it to the new v2 schema by running:
85+
86+
```
87+
gomodguard migrate > .gomodguard-v2.yaml
88+
mv .gomodguard-v2.yaml .gomodguard.yaml
6089
```
6190
6291
## Usage
@@ -89,14 +118,14 @@ Flags:
89118
## Example
90119
91120
```
92-
╰─ ./gomodguard -r checkstyle -f gomodguard-checkstyle.xml ./...
93-
94-
info: allowed modules, [gopkg.in/yaml.v3 github.com/go-xmlfmt/xmlfmt github.com/phayes/checkstyle github.com/mitchellh/go-homedir]
95-
info: allowed module prefixes, [golang.org]
96-
info: blocked modules, [github.com/uudashr/go-module]
97-
info: found `2` blocked modules in the go.mod file, [github.com/gofrs/uuid github.com/uudashr/go-module]
98-
blocked_example.go:6: import of package `github.com/gofrs/uuid` is blocked because the module is not in the allowed modules list.
99-
blocked_example.go:7: import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library.
121+
╰─ cd examples/alloptions
122+
╰─ gomodguard -r checkstyle -f gomodguard-checkstyle.xml ./...
123+
124+
info: allowed modules, [github.com/Masterminds/semver/v3 github.com/go-xmlfmt/xmlfmt golang.org gopkg.in/yaml.v3]
125+
info: blocked modules, [github.com/gofrs/uuid github.com/mitchellh/go-homedir github.com/uudashr/go-module]
126+
blocked_example.go:6:1 import of package `github.com/gofrs/uuid` is blocked because the module is in the blocked modules list. `github.com/ryancurrah/gomodguard` is a recommended module. testing if module is not blocked when it is recommended.
127+
blocked_example.go:7:1 import of package `github.com/mitchellh/go-homedir` is blocked because the module is in the blocked modules list. version `v1.1.0` is blocked because it does not meet the version constraint `<=1.1.0`. testing if blocked version constraint works.
128+
blocked_example.go:8:1 import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library.
100129
```
101130
102131
Resulting checkstyle file
@@ -107,26 +136,25 @@ Resulting checkstyle file
107136
<?xml version="1.0" encoding="UTF-8"?>
108137
<checkstyle version="1.0.0">
109138
<file name="blocked_example.go">
110-
<error line="6" column="1" severity="error" message="import of package `github.com/gofrs/uuid` is blocked because the module is not in the allowed modules list." source="gomodguard">
111-
</error>
112-
<error line="7" column="1" severity="error" message="import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library." source="gomodguard">
113-
</error>
139+
<error line="6" column="1" severity="error" message="import of package `github.com/gofrs/uuid` is blocked because the module is in the blocked modules list. `github.com/ryancurrah/gomodguard` is a recommended module. testing if module is not blocked when it is recommended." source="gomodguard"></error>
140+
<error line="7" column="1" severity="error" message="import of package `github.com/mitchellh/go-homedir` is blocked because the module is in the blocked modules list. version `v1.1.0` is blocked because it does not meet the version constraint `&lt;=1.1.0`. testing if blocked version constraint works." source="gomodguard"></error>
141+
<error line="8" column="1" severity="error" message="import of package `github.com/uudashr/go-module` is blocked because the module is in the blocked modules list. `golang.org/x/mod` is a recommended module. `mod` is the official go.mod parser library." source="gomodguard"></error>
114142
</file>
115143
</checkstyle>
116144
```
117145
118146
## Install
119147
120148
```
121-
go install github.com/ryancurrah/gomodguard/cmd/gomodguard
149+
go install github.com/ryancurrah/gomodguard/v2/cmd/gomodguard@latest
122150
```
123151
124152
## Develop
125153
126154
```
127-
git clone https://github.com/ryancurrah/gomodguard.git && cd gomodguard
155+
git clone https://github.com/ryancurrah/gomodguard.git && cd gomodguard/cmd/gomodguard
128156

129-
go build -o gomodguard cmd/gomodguard/main.go
157+
go build -o gomodguard main.go
130158
```
131159
132160
## License

_example/allOptions/.gomodguard.yaml

Lines changed: 0 additions & 26 deletions
This file was deleted.

_example/allOptions/go.sum

Lines changed: 0 additions & 30 deletions
This file was deleted.

_example/emptyAllowList/.gomodguard.yaml

Lines changed: 0 additions & 6 deletions
This file was deleted.

_example/indirectDep/.gomodguard.yaml

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)