Skip to content

Commit 39986b6

Browse files
committed
fix(check-plugin): format output for indirect dependencies
Fix the output of go mod directives from check-plugin command when operating with --format / -f flag. This now output go mod edit --replace directives for indirect dependencies which ensures that the versions are correctly pinned. Previously "fixes" were lost when go mod tidy was run. Fixes #27
1 parent 9ea9eba commit 39986b6

File tree

8 files changed

+191
-26
lines changed

8 files changed

+191
-26
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/mattn/go-isatty v0.0.19
1111
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
1212
github.com/spf13/cobra v0.0.5
13+
github.com/stretchr/testify v1.9.0
1314
golang.org/x/mod v0.8.0
1415
)
1516

@@ -51,6 +52,7 @@ require (
5152
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
5253
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
5354
github.com/clbanning/mxj v1.8.4 // indirect
55+
github.com/davecgh/go-spew v1.1.1 // indirect
5456
github.com/dimchansky/utfbom v1.1.1 // indirect
5557
github.com/fatih/color v1.13.0 // indirect
5658
github.com/fsnotify/fsnotify v1.5.1 // indirect
@@ -123,6 +125,7 @@ require (
123125
github.com/pelletier/go-toml v1.2.0 // indirect
124126
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
125127
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
128+
github.com/pmezard/go-difflib v1.0.0 // indirect
126129
github.com/rcrowley/go-metrics v0.0.0-20180406234716-d932a24a8ccb // indirect
127130
github.com/ryanuber/go-glob v1.0.0 // indirect
128131
github.com/sony/gobreaker v0.4.1 // indirect

go.sum

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,8 +772,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
772772
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
773773
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
774774
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
775-
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
776775
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
776+
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
777777
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
778778
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
779779
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -784,8 +784,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
784784
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
785785
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
786786
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
787-
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
788787
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
788+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
789+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
789790
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
790791
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
791792
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=

plugin.go

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,90 @@
11
package cmd
22

33
import (
4+
"fmt"
45
"os"
6+
"path/filepath"
57

68
"github.com/krakendio/krakend-cobra/v2/plugin"
79
"github.com/spf13/cobra"
10+
"golang.org/x/mod/modfile"
811
)
912

10-
func pluginFunc(cmd *cobra.Command, _ []string) {
13+
// indirectRequires returns the indirect dependencies of the go.sum file.
14+
func indirectRequires(goSum string) (map[string]struct{}, error) {
15+
dir := filepath.Dir(goSum)
16+
filename := filepath.Join(dir, "go.mod")
17+
data, err := os.ReadFile(filename)
18+
if err != nil {
19+
return nil, fmt.Errorf("read go.mod: %w", err)
20+
}
21+
22+
f, err := modfile.Parse(filename, data, nil)
23+
if err != nil {
24+
return nil, fmt.Errorf("parse go.mod: %w", err)
25+
}
26+
27+
indirects := map[string]struct{}{}
28+
for _, r := range f.Require {
29+
if r.Indirect {
30+
indirects[r.Mod.Path] = struct{}{}
31+
}
32+
}
33+
34+
return indirects, nil
35+
}
36+
37+
// getBuildInfo returns the dependencies of the binary calling it.
38+
// It is a var to allow the replacement of the function in the tests
39+
// as the debug.ReadBuildInfo function is not available in the tests
40+
// https://github.com/golang/go/issues/68045
41+
var localDescriber = plugin.Local
42+
43+
func pluginFunc(cmd *cobra.Command, _ []string) error {
1144
f, err := os.Open(goSum)
1245
if err != nil {
13-
cmd.Println(err)
14-
os.Exit(1)
15-
return
46+
return err
1647
}
1748

49+
defer f.Close()
50+
1851
desc, err := plugin.Describe(f, goVersion, libcVersion)
1952
if err != nil {
20-
cmd.Println(err)
21-
f.Close()
22-
os.Exit(1)
23-
return
53+
return err
2454
}
2555

26-
diffs := plugin.Local().Compare(desc)
56+
diffs := localDescriber().Compare(desc)
2757
if len(diffs) == 0 {
2858
cmd.Println("No incompatibilities found!")
29-
f.Close()
30-
return
59+
return nil
3160
}
3261

33-
cmd.Println(len(diffs), "incompatibility(ies) found...")
3462
if gogetEnabled {
63+
indirects, err := indirectRequires(goSum)
64+
if err != nil {
65+
return err
66+
}
3567
for _, diff := range diffs {
3668
if diff.Name != "go" && diff.Name != "libc" {
37-
cmd.Printf("go get %s@%s\n", diff.Name, diff.Expected)
69+
if _, ok := indirects[diff.Name]; ok {
70+
cmd.Printf("go mod edit --replace %s=%s@%s\n", diff.Name, diff.Name, diff.Expected)
71+
} else {
72+
cmd.Printf("go get %s@%s\n", diff.Name, diff.Expected)
73+
}
3874
continue
3975
}
4076

4177
cmd.Println(diff.Name)
4278
cmd.Println("\thave:", diff.Have)
4379
cmd.Println("\twant:", diff.Expected)
4480
}
45-
f.Close()
46-
os.Exit(1)
81+
} else {
82+
for _, diff := range diffs {
83+
cmd.Println(diff.Name)
84+
cmd.Println("\thave:", diff.Have)
85+
cmd.Println("\twant:", diff.Expected)
86+
}
4787
}
4888

49-
for _, diff := range diffs {
50-
cmd.Println(diff.Name)
51-
cmd.Println("\thave:", diff.Have)
52-
cmd.Println("\twant:", diff.Expected)
53-
}
54-
f.Close()
55-
os.Exit(1)
89+
return fmt.Errorf("%d incompatibilities found", len(diffs))
5690
}

plugin_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/krakendio/krakend-cobra/v2/plugin"
8+
"github.com/spf13/cobra"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func Test_pluginFunc(t *testing.T) {
13+
var buf bytes.Buffer
14+
cmd := &cobra.Command{}
15+
cmd.SetOutput(&buf)
16+
17+
localDescriber = func() plugin.Descriptor {
18+
return plugin.Descriptor{
19+
Go: goVersion,
20+
Libc: libcVersion,
21+
Deps: map[string]string{
22+
"golang.org/x/mod": "v0.6.0-dev.0.20220419223038-86c51ed26bb4",
23+
"github.com/Azure/azure-sdk-for-go": "v59.3.0+incompatible",
24+
"cloud.google.com/go": "v0.100.2",
25+
},
26+
}
27+
}
28+
29+
defer func() { localDescriber = plugin.Local }()
30+
31+
tests := map[string]struct {
32+
goSum string
33+
expected string
34+
fix bool
35+
err string
36+
}{
37+
"missing": {
38+
goSum: "./testdata/missing-go.sum",
39+
err: "open ./testdata/missing-go.sum: no such file or directory",
40+
},
41+
"matching": {
42+
goSum: "./testdata/match-go.sum",
43+
expected: "No incompatibilities found!\n",
44+
},
45+
"changes": {
46+
goSum: "./testdata/changes-go.sum",
47+
expected: `cloud.google.com/go
48+
have: v0.100.3
49+
want: v0.100.2
50+
github.com/Azure/azure-sdk-for-go
51+
have: v59.3.1+incompatible
52+
want: v59.3.0+incompatible
53+
golang.org/x/mod
54+
have: v0.6.10-dev.0.20220419223038-86c51ed26bb4
55+
want: v0.6.0-dev.0.20220419223038-86c51ed26bb4
56+
`,
57+
err: "3 incompatibilities found",
58+
},
59+
"fix": {
60+
goSum: "./testdata/changes-go.sum",
61+
fix: true,
62+
expected: `go mod edit --replace cloud.google.com/go=cloud.google.com/go@v0.100.2
63+
go mod edit --replace github.com/Azure/azure-sdk-for-go=github.com/Azure/azure-sdk-for-go@v59.3.0+incompatible
64+
go get golang.org/x/mod@v0.6.0-dev.0.20220419223038-86c51ed26bb4
65+
`,
66+
err: "3 incompatibilities found",
67+
},
68+
}
69+
for name, tc := range tests {
70+
t.Run(name, func(t *testing.T) {
71+
buf.Reset()
72+
73+
orig := goSum
74+
goSum = tc.goSum
75+
defer func() { goSum = orig }()
76+
77+
fix := gogetEnabled
78+
gogetEnabled = tc.fix
79+
defer func() { gogetEnabled = fix }()
80+
81+
err := pluginFunc(cmd, nil)
82+
if tc.err != "" {
83+
require.EqualError(t, err, tc.err)
84+
} else {
85+
require.NoError(t, err)
86+
}
87+
require.Equal(t, tc.expected, buf.String())
88+
})
89+
}
90+
}

root.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ var (
6666
Use: "check-plugin",
6767
Short: "Checks your plugin dependencies are compatible.",
6868
Long: "Checks your plugin dependencies are compatible and proposes commands to update your dependencies.",
69-
Run: pluginFunc,
69+
RunE: pluginFunc,
7070
Example: "krakend check-plugin -g 1.19.0 -s ./go.sum -f",
7171
}
7272

@@ -106,7 +106,7 @@ func init() {
106106
portFlag := IntFlagBuilder(&port, "port", "p", 0, "Listening port for the http service")
107107
RunCommand = NewCommand(runCmd, cfgFlag, debugFlag, portFlag)
108108

109-
goSumFlag := StringFlagBuilder(&goSum, "sum", "s", goSum, "Path to the go.sum file to analize")
109+
goSumFlag := StringFlagBuilder(&goSum, "sum", "s", goSum, "Path to the go.sum file to analyze")
110110
goVersionFlag := StringFlagBuilder(&goVersion, "go", "g", goVersion, "The version of the go compiler used for your plugin")
111111
libcVersionFlag := StringFlagBuilder(&libcVersion, "libc", "l", "", "Version of the libc library used")
112112
gogetFlag := BoolFlagBuilder(&gogetEnabled, "format", "f", false, "Shows fix commands to update your dependencies")

testdata/changes-go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
2+
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
3+
cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
4+
cloud.google.com/go v0.100.3 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
5+
cloud.google.com/go v0.100.3/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
6+
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
7+
github.com/Azure/azure-sdk-for-go v59.3.1+incompatible h1:dPIm0BO4jsMXFcCI/sLTPkBtE7mk8WMuRHA0JeWhlcQ=
8+
github.com/Azure/azure-sdk-for-go v59.3.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
9+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
10+
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
11+
golang.org/x/mod v0.6.10-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
12+
golang.org/x/mod v0.6.10-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=

testdata/go.mod

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module github.com/krakendio/krakend-cobra/v2
2+
3+
go 1.17
4+
5+
require (
6+
github.com/gin-gonic/gin v1.8.2
7+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
8+
)
9+
10+
require (
11+
cloud.google.com/go v0.100.2 // indirect
12+
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible // indirect
13+
)

testdata/match-go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
2+
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
3+
cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
4+
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
5+
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
6+
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
7+
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible h1:dPIm0BO4jsMXFcCI/sLTPkBtE7mk8WMuRHA0JeWhlcQ=
8+
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
9+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
10+
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
11+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
12+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=

0 commit comments

Comments
 (0)