@@ -4,339 +4,21 @@ import (
44 "bytes"
55 "errors"
66 "fmt"
7- "io"
87 "os"
98 "os/exec"
10- "path/filepath"
11- "runtime"
129 "strings"
1310
1411 "github.com/craiggwilson/goke/pkg/sh"
1512 "github.com/craiggwilson/goke/task"
1613)
1714
18- const (
19- goimportsVersion = "v0.29.0"
20- goimportsPkg = "golang.org/x/tools/cmd/goimports@" + goimportsVersion
21-
22- // For JS tools like eslint and prettier, these versions need to match the ones in the
23- // `package.json` file. To update to a new version, run a command like this:
24- //
25- // npm install --save-dev --save-exact prettier@3.3.1
26- //
27- // Then update the version in this file as well.
28-
29- // This is the latest version to support a YAML config file. Updating to
30- // the new config file syntax did not seem trivial.
31- eslintVersion = "8.57.0"
32- gitHubCodeownersVersion = "0.2.1"
33- golangCILintVersion = "2.6.2"
34- golinesVersion = "0.12.2" // 0.13.0 fails w/ libc errors
35- gosecVersion = "2.22.10"
36- preciousVersion = "0.10.1"
37- ubiVersion = "0.8.4"
38- prettierVersion = "3.6.2"
39- )
40-
41- func SAInstallDevTools (ctx * task.Context ) error {
42- if err := installUBI (ctx ); err != nil {
43- return err
44- }
45- if err := installGoimports (ctx ); err != nil {
46- return err
47- }
48- if err := installGolangCILint (ctx ); err != nil {
49- return err
50- }
51- if err := installGolines (ctx ); err != nil {
52- return err
53- }
54- if err := installGosec (ctx ); err != nil {
55- return err
56- }
57- if err := installPrecious (ctx ); err != nil {
58- return err
59- }
60- return installJSTools (ctx )
61- }
62-
63- // Install goimports.
64- func installGoimports (ctx * task.Context ) error {
65- return goInstall (ctx , goimportsPkg )
66- }
67-
68- // Install UBI.
69- func installUBI (ctx * task.Context ) error {
70- var err error
71- devBin , err := devBinDir ()
72- if err != nil {
73- return err
74- }
75-
76- ubi , err := devBinFile ("ubi" )
77- if err != nil {
78- return err
79- }
80-
81- exists , err := executableExistsWithVersion (ctx , ubi , ubiVersion )
82- if err != nil {
83- return err
84- }
85- if exists {
86- return nil
87- }
88-
89- var ubiBootstrapURL string
90- switch runtime .GOOS {
91- case "windows" :
92- ubiBootstrapURL = "https://raw.githubusercontent.com/houseabsolute/ubi/ci-for-bootstrap/bootstrap/bootstrap-ubi.ps1"
93- default :
94- ubiBootstrapURL = fmt .Sprintf (
95- "https://raw.githubusercontent.com/houseabsolute/ubi/v%s/bootstrap/bootstrap-ubi.sh" ,
96- ubiVersion ,
97- )
98- }
99-
100- s := strings .Split (ubiBootstrapURL , "/" )
101- bootstrapPath := filepath .Join (os .TempDir (), s [len (s )- 1 ])
102-
103- out , err := os .Create (bootstrapPath )
104- if err != nil {
105- return err
106- }
107- defer out .Close ()
108-
109- resp , err := httpGetWithRetries (ubiBootstrapURL , 5 )
110- if err != nil {
111- return err
112- }
113- defer resp .Body .Close ()
114-
115- _ , err = io .Copy (out , resp .Body )
116- if err != nil {
117- return err
118- }
119-
120- var cmd []string
121- if strings .HasSuffix (ubiBootstrapURL , ".ps1" ) {
122- cmd = []string {"powershell" , bootstrapPath }
123- } else {
124- cmd = []string {"sh" , bootstrapPath }
125- }
126-
127- // On Windows the bootstrapper always installs into the current directory,
128- // so chdir there first.
129- return doInDir (devBin , func () error {
130- c := exec .CommandContext (ctx , cmd [0 ], cmd [1 :]... )
131- c .Env = []string {"TARGET=" + devBin , "TAG=v" + ubiVersion }
132- return sh .RunCmd (ctx , c )
133- })
134- }
135-
136- // Install golangci-lint.
137- func installGolangCILint (ctx * task.Context ) error {
138- return installBinaryTool (
139- ctx ,
140- "golangci-lint" ,
141- golangCILintVersion ,
142- "golangci/golangci-lint" ,
143- fmt .Sprintf (
144- "https://github.com/golangci/golangci-lint/releases/download/v%s/golangci-lint-%s-linux-amd64.tar.gz" ,
145- golangCILintVersion ,
146- golangCILintVersion ,
147- ),
148- )
149- }
150-
151- // Install golines.
152- func installGolines (ctx * task.Context ) error {
153- return installBinaryTool (
154- ctx ,
155- "golines" ,
156- golinesVersion ,
157- "segmentio/golines" ,
158- fmt .Sprintf (
159- "https://github.com/segmentio/golines/releases/download/v%s/golines_%s_linux_amd64.tar.gz" ,
160- golinesVersion ,
161- golinesVersion ,
162- ),
163- )
164- }
165-
166- // Install gosec.
167- func installGosec (ctx * task.Context ) error {
168- return installBinaryTool (
169- ctx ,
170- "gosec" ,
171- gosecVersion ,
172- "securego/gosec" ,
173- fmt .Sprintf (
174- "https://github.com/securego/gosec/releases/download/v%s/gosec_%s_linux_amd64.tar.gz" ,
175- gosecVersion ,
176- gosecVersion ,
177- ),
178- )
179- }
180-
181- func installPrecious (ctx * task.Context ) error {
182- return installBinaryTool (
183- ctx ,
184- "precious" ,
185- preciousVersion ,
186- "houseabsolute/precious" ,
187- fmt .Sprintf (
188- "https://github.com/houseabsolute/precious/releases/download/v%s/precious-Linux-musl-x86_64.tar.gz" ,
189- preciousVersion ,
190- ),
191- )
192- }
193-
194- // Install a Golang package as an executable with "go install".
195- func goInstall (ctx * task.Context , link string ) error {
196- root , err := repoRoot ()
197- if err != nil {
198- return err
199- }
200- if err = os .Setenv ("GOBIN" , filepath .Join (root , "dev-bin" )); err != nil {
201- return err
202- }
203-
204- return withRetries (
205- 5 ,
206- fmt .Sprintf ("go install %s" , link ),
207- func () error {
208- return sh .Run (ctx , "go" , "install" , link )
209- },
210- )
211- }
212-
213- func installBinaryTool (
214- ctx * task.Context ,
215- exeName , toolVersion , githubProject , downloadURLForCI string ,
216- ) error {
217- devBin , err := devBinDir ()
218- if err != nil {
219- return err
220- }
221-
222- devBinExe , err := devBinFile (exeName )
223- if err != nil {
224- return err
225- }
226-
227- exists , err := executableExistsWithVersion (ctx , devBinExe , toolVersion )
228- if err != nil {
229- return err
230- }
231- if exists {
232- return nil
233- }
234-
235- cmd := []string {
236- filepath .Join (devBin , "ubi" ),
237- "--in" , devBin ,
238- }
239- if inCI () {
240- // Using the `--url` arg avoids hitting the GitHub API, but it skips
241- // all the platform detection ubi provides. We do it this way because
242- // even with authentication, the limits on the GitHub API are
243- // something like 5,000 requests an hour. Without it, the limit is way
244- // lower.
245- //
246- // This seemed simpler than adding a GitHub token to Evergreen. If we
247- // ever switch to GH Actions we can reconsider, since in that case
248- // we'd have a token automatically available in the `GITHUB_TOKEN` env
249- // var.
250- cmd = append (cmd , "--url" , downloadURLForCI )
251- } else {
252- cmd = append (
253- cmd ,
254- "--project" , githubProject ,
255- "--tag" , "v" + toolVersion ,
256- )
257- }
258-
259- return withRetries (
260- 5 ,
261- fmt .Sprintf ("installing %s" , exeName ),
262- func () error {
263- return sh .Run (ctx , cmd [0 ], cmd [1 :]... )
264- },
265- )
266- }
267-
268- // We have to install all the JS tools at once. If we run `npm install <tool>` multiple times, each
269- // execution wipes the entire `node_modules` directory, so we only end up with one tool (the last
270- // one) installed.
271- func installJSTools (ctx * task.Context ) error {
272- eslint , err := npmPath ("eslint" )
273- if err != nil {
274- return err
275- }
276-
277- prettier , err := npmPath ("prettier" )
278- if err != nil {
279- return err
280- }
281-
282- for _ , tool := range [][]string {
283- {eslint , eslintVersion },
284- {prettier , prettierVersion },
285- } {
286- exists , err := executableExistsWithVersion (ctx , tool [0 ], tool [1 ])
287- if err != nil {
288- return err
289- }
290- if ! exists {
291- return runNPMInstall (ctx )
292- }
293- }
294-
295- gitHubCodeowners , err := npmPath ("github-codeowners" )
296- if err != nil {
297- return err
298- }
299-
300- // This program doesn't have any way to print its version. :(
301- exists , err := fileExists (gitHubCodeowners )
302- if err != nil {
303- return err
304- }
305- if ! exists {
306- return runNPMInstall (ctx )
307- }
308-
309- return nil
310- }
311-
312- func runNPMInstall (ctx * task.Context ) error {
313- return sh .Run (
314- ctx ,
315- "npm" , "install" ,
316- )
317- }
318-
319- func npmPath (exe string ) (string , error ) {
320- root , err := repoRoot ()
321- if err != nil {
322- return "" , err
323- }
324-
325- return filepath .Join (root , "node_modules" , ".bin" , exe ), nil
326- }
327-
32815func SAPreciousLint (ctx * task.Context ) error {
32916 return runPrecious (ctx , "lint" , "--all" )
33017}
33118
33219func runPrecious (ctx * task.Context , args ... string ) error {
333- devBin , err := devBinDir ()
334- if err != nil {
335- return err
336- }
337-
33820 cmd := append (
339- []string {filepath . Join ( devBin , "precious" ) },
21+ []string {"mise" , "exec" , "github:houseabsolute/ precious", "--" , "precious" },
34022 args ... ,
34123 )
34224
0 commit comments