Skip to content

Commit f1e4d89

Browse files
authored
fix: add go.mod hash to the cache salt (#5739)
1 parent 43e07c4 commit f1e4d89

File tree

4 files changed

+52
-6
lines changed

4 files changed

+52
-6
lines changed

Diff for: pkg/commands/run.go

+41-2
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ import (
2121

2222
"github.com/fatih/color"
2323
"github.com/gofrs/flock"
24+
"github.com/ldez/grignotin/goenv"
2425
"github.com/spf13/cobra"
2526
"github.com/spf13/pflag"
2627
"github.com/spf13/viper"
2728
"go.uber.org/automaxprocs/maxprocs"
29+
"golang.org/x/mod/sumdb/dirhash"
2830
"gopkg.in/yaml.v3"
2931

3032
"github.com/golangci/golangci-lint/v2/internal/cache"
@@ -216,7 +218,7 @@ func (c *runCommand) preRunE(_ *cobra.Command, args []string) error {
216218

217219
c.contextBuilder = lint.NewContextBuilder(c.cfg, pkgLoader, pkgCache, guard)
218220

219-
if err = initHashSalt(c.buildInfo.Version, c.cfg); err != nil {
221+
if err = initHashSalt(c.log.Child(logutils.DebugKeyGoModSalt), c.buildInfo.Version, c.cfg); err != nil {
220222
return fmt.Errorf("failed to init hash salt: %w", err)
221223
}
222224

@@ -618,7 +620,7 @@ func formatMemory(memBytes uint64) string {
618620

619621
// Related to cache.
620622

621-
func initHashSalt(version string, cfg *config.Config) error {
623+
func initHashSalt(logger logutils.Log, version string, cfg *config.Config) error {
622624
binSalt, err := computeBinarySalt(version)
623625
if err != nil {
624626
return fmt.Errorf("failed to calculate binary salt: %w", err)
@@ -629,9 +631,18 @@ func initHashSalt(version string, cfg *config.Config) error {
629631
return fmt.Errorf("failed to calculate config salt: %w", err)
630632
}
631633

634+
goModSalt, err := computeGoModSalt()
635+
if err != nil {
636+
// NOTE: missing go.mod must be ignored.
637+
logger.Warnf("Failed to calculate go.mod salt: %v", err)
638+
}
639+
632640
b := bytes.NewBuffer(binSalt)
633641
b.Write(configSalt)
642+
b.WriteString(goModSalt)
643+
634644
cache.SetSalt(b)
645+
635646
return nil
636647
}
637648

@@ -648,15 +659,19 @@ func computeBinarySalt(version string) ([]byte, error) {
648659
if err != nil {
649660
return nil, err
650661
}
662+
651663
f, err := os.Open(p)
652664
if err != nil {
653665
return nil, err
654666
}
667+
655668
defer f.Close()
669+
656670
h := sha256.New()
657671
if _, err := io.Copy(h, f); err != nil {
658672
return nil, err
659673
}
674+
660675
return h.Sum(nil), nil
661676
}
662677

@@ -678,5 +693,29 @@ func computeConfigSalt(cfg *config.Config) ([]byte, error) {
678693
if _, err := h.Write(configData.Bytes()); err != nil {
679694
return nil, err
680695
}
696+
681697
return h.Sum(nil), nil
682698
}
699+
700+
func computeGoModSalt() (string, error) {
701+
values, err := goenv.Get(context.Background(), goenv.GOMOD)
702+
if err != nil {
703+
return "", fmt.Errorf("failed to get goenv: %w", err)
704+
}
705+
706+
goModPath := filepath.Clean(values[goenv.GOMOD])
707+
708+
data, err := os.ReadFile(goModPath)
709+
if err != nil {
710+
return "", fmt.Errorf("failed to read go.mod: %w", err)
711+
}
712+
713+
sum, err := dirhash.Hash1([]string{goModPath}, func(string) (io.ReadCloser, error) {
714+
return io.NopCloser(bytes.NewReader(data)), nil
715+
})
716+
if err != nil {
717+
return "", fmt.Errorf("failed to compute go.sum: %w", err)
718+
}
719+
720+
return sum, nil
721+
}

Diff for: pkg/config/config.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"github.com/ldez/grignotin/goenv"
1414
"github.com/ldez/grignotin/gomod"
1515
"golang.org/x/mod/modfile"
16+
17+
"github.com/golangci/golangci-lint/v2/pkg/logutils"
1618
)
1719

1820
// defaultGoVersion the value should be "oldstable" - 1.
@@ -102,16 +104,16 @@ func IsGoGreaterThanOrEqual(current, limit string) bool {
102104
return v1.GreaterThanOrEqual(l)
103105
}
104106

105-
func detectGoVersion(ctx context.Context) string {
106-
return cmp.Or(detectGoVersionFromGoMod(ctx), defaultGoVersion)
107+
func detectGoVersion(ctx context.Context, log logutils.Log) string {
108+
return cmp.Or(detectGoVersionFromGoMod(ctx, log), defaultGoVersion)
107109
}
108110

109111
// detectGoVersionFromGoMod tries to get Go version from go.mod.
110112
// It returns `toolchain` version if present,
111113
// else it returns `go` version if present,
112114
// else it returns `GOVERSION` version if present,
113115
// else it returns empty.
114-
func detectGoVersionFromGoMod(ctx context.Context) string {
116+
func detectGoVersionFromGoMod(ctx context.Context, log logutils.Log) string {
115117
values, err := goenv.Get(ctx, goenv.GOMOD, goenv.GOVERSION)
116118
if err != nil {
117119
values = map[string]string{
@@ -128,6 +130,10 @@ func detectGoVersionFromGoMod(ctx context.Context) string {
128130
return parseGoVersion(values[goenv.GOVERSION])
129131
}
130132

133+
if file.Module != nil {
134+
log.Infof("Module name %q", file.Module.Mod.Path)
135+
}
136+
131137
// The toolchain exists only if 'toolchain' version > 'go' version.
132138
// If 'toolchain' version <= 'go' version, `go mod tidy` will remove 'toolchain' version from go.mod.
133139
if file.Toolchain != nil && file.Toolchain.Name != "" {

Diff for: pkg/config/loader.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func (l *Loader) checkConfigurationVersion() error {
161161

162162
func (l *Loader) handleGoVersion() {
163163
if l.cfg.Run.Go == "" {
164-
l.cfg.Run.Go = detectGoVersion(context.Background())
164+
l.cfg.Run.Go = detectGoVersion(context.Background(), l.log)
165165
}
166166

167167
l.cfg.Linters.Settings.Govet.Go = l.cfg.Run.Go

Diff for: pkg/logutils/logutils.go

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const envDebug = "GL_DEBUG"
1717

1818
const (
1919
DebugKeyBinSalt = "bin_salt"
20+
DebugKeyGoModSalt = "gomod_salt"
2021
DebugKeyConfigReader = "config_reader"
2122
DebugKeyEmpty = ""
2223
DebugKeyEnabledLinters = "enabled_linters"

0 commit comments

Comments
 (0)