golang.org/x/playground@v0.0.0-20230418134305-14ebe15bcd59/vet.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "context" 9 "fmt" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "strings" 14 "time" 15 16 "go.opencensus.io/stats" 17 "go.opencensus.io/tag" 18 ) 19 20 // vetCheck runs the "vet" tool on the source code in req.Body. 21 // In case of no errors it returns an empty, non-nil *response. 22 // Otherwise &response.Errors contains found errors. 23 // 24 // Deprecated: this is the handler for the legacy /vet endpoint; use 25 // the /compile (compileAndRun) handler instead with the WithVet 26 // boolean set. This code path doesn't support modules and only exists 27 // as a temporary compatibility bridge to older javascript clients. 28 func vetCheck(ctx context.Context, req *request) (*response, error) { 29 tmpDir, err := os.MkdirTemp("", "vet") 30 if err != nil { 31 return nil, fmt.Errorf("error creating temp directory: %v", err) 32 } 33 defer os.RemoveAll(tmpDir) 34 35 in := filepath.Join(tmpDir, progName) 36 if err := os.WriteFile(in, []byte(req.Body), 0400); err != nil { 37 return nil, fmt.Errorf("error creating temp file %q: %v", in, err) 38 } 39 vetOutput, err := vetCheckInDir(ctx, tmpDir, os.Getenv("GOPATH")) 40 if err != nil { 41 // This is about errors running vet, not vet returning output. 42 return nil, err 43 } 44 return &response{Errors: vetOutput}, nil 45 } 46 47 // vetCheckInDir runs go vet in the provided directory, using the 48 // provided GOPATH value. The returned error is only about whether 49 // go vet was able to run, not whether vet reported problem. The 50 // returned value is ("", nil) if vet successfully found nothing, 51 // and (non-empty, nil) if vet ran and found issues. 52 func vetCheckInDir(ctx context.Context, dir, goPath string) (output string, execErr error) { 53 start := time.Now() 54 defer func() { 55 status := "success" 56 if execErr != nil { 57 status = "error" 58 } 59 // Ignore error. The only error can be invalid tag key or value 60 // length, which we know are safe. 61 stats.RecordWithTags(ctx, []tag.Mutator{tag.Upsert(kGoVetSuccess, status)}, 62 mGoVetLatency.M(float64(time.Since(start))/float64(time.Millisecond))) 63 }() 64 65 cmd := exec.Command("go", "vet", "--tags=faketime", "--mod=mod") 66 cmd.Dir = dir 67 // Linux go binary is not built with CGO_ENABLED=0. 68 // Prevent vet to compile packages in cgo mode. 69 // See #26307. 70 cmd.Env = append(os.Environ(), "CGO_ENABLED=0", "GOPATH="+goPath) 71 cmd.Env = append(cmd.Env, 72 "GO111MODULE=on", 73 "GOPROXY="+playgroundGoproxy(), 74 ) 75 out, err := cmd.CombinedOutput() 76 if err == nil { 77 return "", nil 78 } 79 if _, ok := err.(*exec.ExitError); !ok { 80 return "", fmt.Errorf("error vetting go source: %v", err) 81 } 82 83 // Rewrite compiler errors to refer to progName 84 // instead of '/tmp/sandbox1234/main.go'. 85 errs := strings.Replace(string(out), dir, "", -1) 86 errs = removeBanner(errs) 87 return errs, nil 88 }