Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(check-plugin): format output for indirect dependencies #28

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/mattn/go-isatty v0.0.19
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.9.0
golang.org/x/mod v0.8.0
)

Expand Down Expand Up @@ -51,6 +52,7 @@ require (
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
Expand Down Expand Up @@ -123,6 +125,7 @@ require (
github.com/pelletier/go-toml v1.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20180406234716-d932a24a8ccb // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sony/gobreaker v0.4.1 // indirect
Expand Down
5 changes: 3 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -772,8 +772,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand All @@ -784,8 +784,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
Expand Down
78 changes: 56 additions & 22 deletions plugin.go
Original file line number Diff line number Diff line change
@@ -1,56 +1,90 @@
package cmd

import (
"fmt"
"os"
"path/filepath"

"github.com/krakendio/krakend-cobra/v2/plugin"
"github.com/spf13/cobra"
"golang.org/x/mod/modfile"
)

func pluginFunc(cmd *cobra.Command, _ []string) {
// indirectRequires returns the indirect dependencies of the go.sum file.
func indirectRequires(goSum string) (map[string]struct{}, error) {
dir := filepath.Dir(goSum)
filename := filepath.Join(dir, "go.mod")
data, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("read go.mod: %w", err)
}

f, err := modfile.Parse(filename, data, nil)
if err != nil {
return nil, fmt.Errorf("parse go.mod: %w", err)
}

indirects := map[string]struct{}{}
for _, r := range f.Require {
if r.Indirect {
indirects[r.Mod.Path] = struct{}{}
}
}

return indirects, nil
}

// getBuildInfo returns the dependencies of the binary calling it.
// It is a var to allow the replacement of the function in the tests
// as the debug.ReadBuildInfo function is not available in the tests
// https://github.com/golang/go/issues/68045
var localDescriber = plugin.Local

func pluginFunc(cmd *cobra.Command, _ []string) error {
f, err := os.Open(goSum)
if err != nil {
cmd.Println(err)
os.Exit(1)
return
return err
}

defer func() { _ = f.Close() }() // Workaround false positive for GO-S2307.

desc, err := plugin.Describe(f, goVersion, libcVersion)
if err != nil {
cmd.Println(err)
f.Close()
os.Exit(1)
return
return err
}

diffs := plugin.Local().Compare(desc)
diffs := localDescriber().Compare(desc)
if len(diffs) == 0 {
cmd.Println("No incompatibilities found!")
f.Close()
return
return nil
}

cmd.Println(len(diffs), "incompatibility(ies) found...")
if gogetEnabled {
indirects, err := indirectRequires(goSum)
if err != nil {
return err
}
for _, diff := range diffs {
if diff.Name != "go" && diff.Name != "libc" {
cmd.Printf("go get %s@%s\n", diff.Name, diff.Expected)
if _, ok := indirects[diff.Name]; ok {
cmd.Printf("go mod edit --replace %s=%s@%s\n", diff.Name, diff.Name, diff.Expected)
} else {
cmd.Printf("go get %s@%s\n", diff.Name, diff.Expected)
}
continue
}

cmd.Println(diff.Name)
cmd.Println("\thave:", diff.Have)
cmd.Println("\twant:", diff.Expected)
}
f.Close()
os.Exit(1)
} else {
for _, diff := range diffs {
cmd.Println(diff.Name)
cmd.Println("\thave:", diff.Have)
cmd.Println("\twant:", diff.Expected)
}
}

for _, diff := range diffs {
cmd.Println(diff.Name)
cmd.Println("\thave:", diff.Have)
cmd.Println("\twant:", diff.Expected)
}
f.Close()
os.Exit(1)
return fmt.Errorf("%d incompatibilities found", len(diffs))
}
90 changes: 90 additions & 0 deletions plugin_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cmd

import (
"bytes"
"testing"

"github.com/krakendio/krakend-cobra/v2/plugin"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)

func Test_pluginFunc(t *testing.T) {
var buf bytes.Buffer
cmd := &cobra.Command{}
cmd.SetOutput(&buf)

localDescriber = func() plugin.Descriptor {
return plugin.Descriptor{
Go: goVersion,
Libc: libcVersion,
Deps: map[string]string{
"golang.org/x/mod": "v0.6.0-dev.0.20220419223038-86c51ed26bb4",
"github.com/Azure/azure-sdk-for-go": "v59.3.0+incompatible",
"cloud.google.com/go": "v0.100.2",
},
}
}

defer func() { localDescriber = plugin.Local }()

tests := map[string]struct {
goSum string
expected string
fix bool
err string
}{
"missing": {
goSum: "./testdata/missing-go.sum",
err: "open ./testdata/missing-go.sum: no such file or directory",
},
"matching": {
goSum: "./testdata/match-go.sum",
expected: "No incompatibilities found!\n",
},
"changes": {
goSum: "./testdata/changes-go.sum",
expected: `cloud.google.com/go
have: v0.100.3
want: v0.100.2
github.com/Azure/azure-sdk-for-go
have: v59.3.1+incompatible
want: v59.3.0+incompatible
golang.org/x/mod
have: v0.6.10-dev.0.20220419223038-86c51ed26bb4
want: v0.6.0-dev.0.20220419223038-86c51ed26bb4
`,
err: "3 incompatibilities found",
},
"fix": {
goSum: "./testdata/changes-go.sum",
fix: true,
expected: `go mod edit --replace cloud.google.com/go=cloud.google.com/[email protected]
go mod edit --replace github.com/Azure/azure-sdk-for-go=github.com/Azure/[email protected]+incompatible
go get golang.org/x/[email protected]
`,
err: "3 incompatibilities found",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
buf.Reset()

orig := goSum
goSum = tc.goSum
defer func() { goSum = orig }()

fix := gogetEnabled
gogetEnabled = tc.fix
defer func() { gogetEnabled = fix }()

err := pluginFunc(cmd, nil)
if tc.err != "" {
require.EqualError(t, err, tc.err)
} else {
require.NoError(t, err)
}
require.Equal(t, tc.expected, buf.String())
})
}
}
4 changes: 2 additions & 2 deletions root.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var (
Use: "check-plugin",
Short: "Checks your plugin dependencies are compatible.",
Long: "Checks your plugin dependencies are compatible and proposes commands to update your dependencies.",
Run: pluginFunc,
RunE: pluginFunc,
Example: "krakend check-plugin -g 1.19.0 -s ./go.sum -f",
}

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

goSumFlag := StringFlagBuilder(&goSum, "sum", "s", goSum, "Path to the go.sum file to analize")
goSumFlag := StringFlagBuilder(&goSum, "sum", "s", goSum, "Path to the go.sum file to analyze")
goVersionFlag := StringFlagBuilder(&goVersion, "go", "g", goVersion, "The version of the go compiler used for your plugin")
libcVersionFlag := StringFlagBuilder(&libcVersion, "libc", "l", "", "Version of the libc library used")
gogetFlag := BoolFlagBuilder(&gogetEnabled, "format", "f", false, "Shows fix commands to update your dependencies")
Expand Down
12 changes: 12 additions & 0 deletions testdata/changes-go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
cloud.google.com/go v0.100.3 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
cloud.google.com/go v0.100.3/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v59.3.1+incompatible h1:dPIm0BO4jsMXFcCI/sLTPkBtE7mk8WMuRHA0JeWhlcQ=
github.com/Azure/azure-sdk-for-go v59.3.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.10-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.10-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
13 changes: 13 additions & 0 deletions testdata/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module github.com/krakendio/krakend-cobra/v2

go 1.17

require (
github.com/gin-gonic/gin v1.8.2
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
)

require (
cloud.google.com/go v0.100.2 // indirect
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible // indirect
)
12 changes: 12 additions & 0 deletions testdata/match-go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible h1:dPIm0BO4jsMXFcCI/sLTPkBtE7mk8WMuRHA0JeWhlcQ=
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=