[tools] internal/server: store vulncheck prompt preference

2 views
Skip to first unread message

Gopher Robot (Gerrit)

unread,
Dec 19, 2025, 1:22:44 PM (2 days ago) Dec 19
to Ethan Lee, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Go LUCI, Hongxiang Jiang, golang-co...@googlegroups.com

Gopher Robot submitted the change with unreviewed changes

Unreviewed changes

25 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:

```
The name of the file: gopls/internal/server/vulncheck_prompt_test.go
Insertions: 1, Deletions: 3.

@@ -263,9 +263,7 @@
t.Fatal(err)
}

- done := make(chan struct{})
- s.checkGoModDeps(ctx, uri, done)
- <-done
+ s.checkGoModDeps(ctx, uri)

if promptShown != tt.wantPrompt {
t.Errorf("promptShown = %v, want %v", promptShown, tt.wantPrompt)
```
```
The name of the file: gopls/internal/server/text_synchronization.go
Insertions: 1, Deletions: 1.

@@ -262,7 +262,7 @@
}
}
for uri := range uris {
- s.checkGoModDeps(ctx, uri, nil)
+ go s.checkGoModDeps(ctx, uri)
}

viewsToDiagnose, err := s.session.DidModifyFiles(ctx, modifications)
```
```
The name of the file: gopls/internal/server/vulncheck_prompt.go
Insertions: 68, Deletions: 73.

@@ -48,87 +48,82 @@
return hex.EncodeToString(h.Sum(nil)), nil
}

-func (s *server) checkGoModDeps(ctx context.Context, uri protocol.DocumentURI, done chan<- struct{}) {
- go func() {
- if done != nil {
- defer close(done)
- }
- if s.Options().Vulncheck != settings.ModeVulncheckPrompt {
+func (s *server) checkGoModDeps(ctx context.Context, uri protocol.DocumentURI) {
+ if s.Options().Vulncheck != settings.ModeVulncheckPrompt {
+ return
+ }
+ ctx, done := event.Start(ctx, "server.CheckGoModDeps")
+ defer done()
+
+ var (
+ newHash, oldHash string
+ pathHash [32]byte
+ )
+ {
+ newContent, err := os.ReadFile(uri.Path())
+ if err != nil {
+ event.Error(ctx, "reading new go.mod content failed", err)
return
}
- ctx, done := event.Start(ctx, "server.CheckGoModDeps")
- defer done()
-
- var (
- newHash, oldHash string
- pathHash [32]byte
- )
- {
- newContent, err := os.ReadFile(uri.Path())
- if err != nil {
- event.Error(ctx, "reading new go.mod content failed", err)
- return
- }
- newModFile, err := modfile.Parse("go.mod", newContent, nil)
- if err != nil {
- event.Error(ctx, "parsing new go.mod failed", err)
- return
- }
- hash, err := computeGoModHash(newModFile)
- if err != nil {
- event.Error(ctx, "computing new go.mod hash failed", err)
- return
- }
- newHash = hash
-
- pathHash = sha256.Sum256([]byte(uri.Path()))
- oldHashBytes, err := filecache.Get(goModHashKind, pathHash)
- if err != nil && err != filecache.ErrNotFound {
- event.Error(ctx, "reading old go.mod hash from filecache failed", err)
- return
- }
- oldHash = string(oldHashBytes)
+ newModFile, err := modfile.Parse("go.mod", newContent, nil)
+ if err != nil {
+ event.Error(ctx, "parsing new go.mod failed", err)
+ return
}
- if oldHash != newHash {
- fileLink := fmt.Sprintf("[%s](%s)", uri.Path(), string(uri))
- govulncheckLink := "[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)"
- message := fmt.Sprintf("Dependencies have changed in %s, would you like to run %s to check for vulnerabilities?", fileLink, govulncheckLink)
+ hash, err := computeGoModHash(newModFile)
+ if err != nil {
+ event.Error(ctx, "computing new go.mod hash failed", err)
+ return
+ }
+ newHash = hash

- preference, err := getVulncheckPreference()
- if err != nil {
- event.Error(ctx, "reading vulncheck preference failed", err)
- }
- if preference == "Never" {
- return
- }
- if preference == "Always" {
- // TODO: Update this so that we run vulncheck when Always is set.
- return
- }
- action, err := showMessageRequest(ctx, s.client, protocol.Info, message, "Yes", "No", "Always", "Never")
- if err != nil {
- event.Error(ctx, "showing go.mod changed notification", err)
- return
- }
+ pathHash = sha256.Sum256([]byte(uri.Path()))
+ oldHashBytes, err := filecache.Get(goModHashKind, pathHash)
+ if err != nil && err != filecache.ErrNotFound {
+ event.Error(ctx, "reading old go.mod hash from filecache failed", err)
+ return
+ }
+ oldHash = string(oldHashBytes)
+ }
+ if oldHash != newHash {
+ fileLink := fmt.Sprintf("[%s](%s)", uri.Path(), string(uri))
+ govulncheckLink := "[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)"
+ message := fmt.Sprintf("Dependencies have changed in %s, would you like to run %s to check for vulnerabilities?", fileLink, govulncheckLink)

- if action == "Always" || action == "Never" {
- if err := setVulncheckPreference(action); err != nil {
- event.Error(ctx, "writing vulncheck preference failed", err)
- showMessage(ctx, s.client, protocol.Error, fmt.Sprintf("Failed to save vulncheck preference: %v", err))
- }
- }
+ preference, err := getVulncheckPreference()
+ if err != nil {
+ event.Error(ctx, "reading vulncheck preference failed", err)
+ }
+ if preference == "Never" {
+ return
+ }
+ if preference == "Always" {
+ // TODO: Update this so that we run vulncheck when Always is set.
+ return
+ }
+ action, err := showMessageRequest(ctx, s.client, protocol.Info, message, "Yes", "No", "Always", "Never")
+ if err != nil {
+ event.Error(ctx, "showing go.mod changed notification", err)
+ return
+ }

- // TODO: Implement the logic to run govulncheck when action is "Yes" or "Always".
- if action == "No" || action == "Never" || action == "" {
- return // Skip the check and don't update the hash.
- }
-
- if err := filecache.Set(goModHashKind, pathHash, []byte(newHash)); err != nil {
- event.Error(ctx, "writing new go.mod hash to filecache failed", err)
- return
+ if action == "Always" || action == "Never" {
+ if err := setVulncheckPreference(action); err != nil {
+ event.Error(ctx, "writing vulncheck preference failed", err)
+ showMessage(ctx, s.client, protocol.Error, fmt.Sprintf("Failed to save vulncheck preference: %v", err))
}
}
- }()
+
+ // TODO: Implement the logic to run govulncheck when action is "Yes" or "Always".
+ if action == "No" || action == "Never" || action == "" {
+ return // Skip the check and don't update the hash.
+ }
+
+ if err := filecache.Set(goModHashKind, pathHash, []byte(newHash)); err != nil {
+ event.Error(ctx, "writing new go.mod hash to filecache failed", err)
+ return
+ }
+ }
}

type vulncheckConfig struct {
```

Change information

Commit message:
gopls/internal/server: store vulncheck prompt preference

- Store users' vulncheck prompt behavior preference in
os.UserConfigDir()

For golang/go#75447
Change-Id: Ic3f516871f5cb0afe483f111b1339f22e59dc3a8
Reviewed-by: Hongxiang Jiang <hxj...@golang.org>
Auto-Submit: Ethan Lee <etha...@google.com>
Files:
  • M gopls/internal/server/server.go
  • M gopls/internal/server/text_synchronization.go
  • M gopls/internal/server/vulncheck_prompt.go
  • M gopls/internal/server/vulncheck_prompt_test.go
Change size: M
Delta: 4 files changed, 157 insertions(+), 72 deletions(-)
Branch: refs/heads/master
Submit Requirements:
  • requirement satisfiedCode-Review: +2 by Hongxiang Jiang
  • requirement satisfiedTryBots-Pass: LUCI-TryBot-Result+1 by Go LUCI
Open in Gerrit
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: merged
Gerrit-Project: tools
Gerrit-Branch: master
Gerrit-Change-Id: Ic3f516871f5cb0afe483f111b1339f22e59dc3a8
Gerrit-Change-Number: 722120
Gerrit-PatchSet: 27
Gerrit-Owner: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Gopher Robot <go...@golang.org>
Gerrit-Reviewer: Hongxiang Jiang <hxj...@golang.org>
open
diffy
satisfied_requirement
Reply all
Reply to author
Forward
0 new messages