this repo has no description
at master 4.4 kB view raw
1package main 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "io/fs" 8 "os" 9 "os/exec" 10 "os/signal" 11 "path/filepath" 12 "syscall" 13) 14 15var debug = os.Getenv("DEBUG") == "1" 16 17func main() { 18 ctx := context.Background() 19 ctx, done := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM) 20 defer done() 21 22 err := run(ctx) 23 if err != nil { 24 fmt.Fprintln(os.Stderr, "pre-commit", err) 25 os.Exit(1) 26 } 27} 28 29func run(ctx context.Context) error { 30 tools, err := selectTools() 31 if err != nil { 32 return err 33 } 34 35 for i, tool := range tools { 36 if debug { 37 fmt.Fprintln(os.Stderr, "running tool", i, tool.name) 38 } 39 out, err := tool.run(ctx) 40 var exit *exec.ExitError 41 if errors.As(err, &exit) { 42 if tool.allowfail { 43 continue 44 } 45 return fmt.Errorf("tool %d %q exited with nonzero status %d, out:\n%s", i, tool.name, exit.ExitCode(), out) 46 } else if err != nil { 47 return fmt.Errorf("tool %d %q unexpected error: %w", i, tool.name, err) 48 } 49 } 50 return nil 51} 52 53type tool struct { 54 name string 55 run func(ctx context.Context) ([]byte, error) 56 allowfail bool 57} 58 59func selectTools() ([]tool, error) { 60 var cuefiles, gofiles []string 61 var prettier, terraform, misspell bool 62 err := filepath.WalkDir(".", func(p string, d fs.DirEntry, err error) error { 63 if err != nil || d.IsDir() { 64 if d.Name() == ".git" { 65 return fs.SkipDir 66 } 67 return err 68 } 69 switch filepath.Ext(d.Name()) { 70 case ".css", ".html", ".json", ".md", ".yaml": 71 prettier = true 72 misspell = true 73 case ".go": 74 gofiles = append(gofiles, p) 75 misspell = true 76 case ".cue": 77 fmt.Println(p, d.Name()) 78 cuefiles = append(cuefiles, p) 79 case ".tf": 80 terraform = true 81 } 82 return nil 83 }) 84 if err != nil { 85 return nil, fmt.Errorf("select tools: walk over '.': %w", err) 86 } 87 88 var tools []tool 89 if misspell { 90 tools = append(tools, tool{ 91 name: "misspell", 92 run: func(ctx context.Context) ([]byte, error) { 93 return exec.CommandContext(ctx, 94 "misspell", "-w", "-q", ".", 95 ).CombinedOutput() 96 }, 97 }) 98 } 99 if prettier { 100 tools = append(tools, tool{ 101 name: "prettier", 102 run: func(ctx context.Context) ([]byte, error) { 103 return exec.CommandContext(ctx, 104 "prettier", "-w", ".", 105 ).CombinedOutput() 106 }, 107 }) 108 } 109 if len(cuefiles) > 0 { 110 tools = append(tools, tool{ 111 name: "cue fmt", 112 run: func(ctx context.Context) ([]byte, error) { 113 return exec.CommandContext(ctx, 114 "cue", append([]string{"fmt"}, cuefiles...)..., 115 ).CombinedOutput() 116 }, 117 }) 118 } 119 if terraform { 120 tools = append(tools, tool{ 121 name: "terraform fmt", 122 run: func(ctx context.Context) ([]byte, error) { 123 return exec.CommandContext(ctx, 124 "terraform", "fmt", "-write", "-recursive", ".", 125 ).CombinedOutput() 126 }, 127 }) 128 } 129 if len(gofiles) > 0 { 130 godirsm := make(map[string]struct{}) 131 for _, dir := range gofiles { 132 godirsm[filepath.Dir(dir)] = struct{}{} 133 } 134 godirs := make([]string, 0, len(godirsm)) 135 for dir := range godirsm { 136 godirs = append(godirs, dir) 137 } 138 tools = append(tools, tool{ 139 name: "go mod tidy", 140 run: func(ctx context.Context) ([]byte, error) { 141 return exec.CommandContext(ctx, 142 "go", "mod", "tidy", 143 ).CombinedOutput() 144 }, 145 }, tool{ 146 name: "gofumpt", 147 run: func(ctx context.Context) ([]byte, error) { 148 return exec.CommandContext(ctx, 149 "gofumpt", append([]string{"-w"}, godirs...)..., 150 ).CombinedOutput() 151 }, 152 }, tool{ 153 name: "go vet", 154 run: func(ctx context.Context) ([]byte, error) { 155 return exec.CommandContext(ctx, 156 "go", "vet", "./...", 157 ).CombinedOutput() 158 }, 159 }, tool{ 160 name: "staticcheck", 161 run: func(ctx context.Context) ([]byte, error) { 162 return exec.CommandContext(ctx, 163 "staticcheck", "./...", 164 ).CombinedOutput() 165 }, 166 }, tool{ 167 name: "guvulncheck", 168 run: func(ctx context.Context) ([]byte, error) { 169 return exec.CommandContext(ctx, 170 "govulncheck", "./...", 171 ).CombinedOutput() 172 }, 173 }, tool{ 174 name: "go build", 175 run: func(ctx context.Context) ([]byte, error) { 176 return exec.CommandContext(ctx, 177 "go", "build", "-o", "/dev/null", "./...", 178 ).CombinedOutput() 179 }, 180 }) 181 } 182 if len(tools) > 0 { 183 tools = append(tools, tool{ 184 name: "git commit", 185 run: func(ctx context.Context) ([]byte, error) { 186 return exec.CommandContext(ctx, 187 "git", "add", ".", 188 ).CombinedOutput() 189 }, 190 }) 191 } 192 return tools, nil 193}