github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/cmd/verify-mod-tidy/verify-mod-tidy.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"flag"
     7  	"fmt"
     8  	"os"
     9  	"os/exec"
    10  	"time"
    11  
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  const (
    16  	goModFile = "go.mod"
    17  	goSumFile = "go.sum"
    18  )
    19  
    20  // verify-mod-tidy verifies that `go mod tidy` has been run to clean up the
    21  // go.mod and go.sum files.
    22  func main() {
    23  	var (
    24  		goBin   string
    25  		timeout time.Duration
    26  	)
    27  
    28  	flag.DurationVar(&timeout, "timeout", 0, "timeout for verifying modules are tidy")
    29  	flag.StringVar(&goBin, "goBin", "go", "path to go binary to use for mod tidy check")
    30  	flag.Parse()
    31  
    32  	ctx := context.Background()
    33  	if timeout != 0 {
    34  		var cancel context.CancelFunc
    35  		ctx, cancel = context.WithTimeout(ctx, timeout)
    36  		defer cancel()
    37  	}
    38  
    39  	oldGoMod, oldGoSum, err := readModuleFiles()
    40  	if err != nil {
    41  		fmt.Fprintln(os.Stderr, err)
    42  		os.Exit(1)
    43  	}
    44  
    45  	if err := runModTidy(ctx, goBin); err != nil {
    46  		fmt.Fprintln(os.Stderr, err)
    47  		os.Exit(1)
    48  	}
    49  
    50  	newGoMod, newGoSum, err := readModuleFiles()
    51  	if err != nil {
    52  		fmt.Fprintln(os.Stderr, err)
    53  		os.Exit(1)
    54  	}
    55  
    56  	if !bytes.Equal(oldGoMod, newGoMod) || !bytes.Equal(oldGoSum, newGoSum) {
    57  		fmt.Fprintf(os.Stderr, "%s and/or %s are not tidy - please run `go mod tidy`.\n", goModFile, goSumFile)
    58  		writeModuleFiles(oldGoMod, oldGoSum)
    59  		os.Exit(1)
    60  	}
    61  }
    62  
    63  // readModuleFiles reads the contents of the go module files.
    64  func readModuleFiles() (goMod []byte, goSum []byte, err error) {
    65  	goMod, err = os.ReadFile(goModFile)
    66  	if err != nil {
    67  		return nil, nil, errors.Wrapf(err, "reading file '%s'", goModFile)
    68  	}
    69  	goSum, err = os.ReadFile(goSumFile)
    70  	if err != nil {
    71  		return nil, nil, errors.Wrapf(err, "reading file '%s'", goSumFile)
    72  	}
    73  	return goMod, goSum, nil
    74  }
    75  
    76  // writeModuleFiles writes the contents of the go module files.
    77  func writeModuleFiles(goMod, goSum []byte) {
    78  	if err := os.WriteFile(goModFile, goMod, 0600); err != nil {
    79  		fmt.Fprintln(os.Stderr, err)
    80  	}
    81  	if err := os.WriteFile(goSumFile, goSum, 0600); err != nil {
    82  		fmt.Fprintln(os.Stderr, err)
    83  	}
    84  }
    85  
    86  // runModTidy runs the `go mod tidy` command with the given go binary.
    87  func runModTidy(ctx context.Context, goBin string) error {
    88  	cmd := exec.CommandContext(ctx, goBin, "mod", "tidy")
    89  	cmd.Stdout = os.Stdout
    90  	cmd.Stderr = os.Stderr
    91  	return errors.Wrap(cmd.Run(), "mod tidy")
    92  }