diff --git a/greplogs/_embed/broken.go b/greplogs/_embed/broken.go new file mode 100644 index 0000000..498ed28 --- /dev/null +++ b/greplogs/_embed/broken.go @@ -0,0 +1,26 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Command broken lists the current Go builders with known issues. +// +// To test this program, cd to its directory and run: +// go mod init +// go get golang.org/x/build/dashboard@HEAD +// go run . +// rm go.mod go.sum +package main + +import ( + "fmt" + + "golang.org/x/build/dashboard" +) + +func main() { + for _, b := range dashboard.Builders { + if len(b.KnownIssues) > 0 { + fmt.Println(b.Name) + } + } +} diff --git a/greplogs/broken.go b/greplogs/broken.go new file mode 100644 index 0000000..f7b70b9 --- /dev/null +++ b/greplogs/broken.go @@ -0,0 +1,76 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + _ "embed" + "fmt" + "os" + "os/exec" + "path/filepath" + "sort" + "strings" +) + +//go:embed _embed/broken.go +var brokenScript []byte + +// listBrokenBuilders returns the builders that are marked +// as broken in golang.org/x/build/dashboard at HEAD. +func listBrokenBuilders() (broken []string, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("identifying broken builders: %v", err) + } + }() + + modDir, err := os.MkdirTemp("", "greplogs") + if err != nil { + return nil, err + } + defer func() { + removeErr := os.RemoveAll(modDir) + if err == nil { + err = removeErr + } + }() + + runCommand := func(name string, args ...string) ([]byte, error) { + cmd := exec.Command(name, args...) + cmd.Dir = modDir + cmd.Env = append(os.Environ(), "GO111MODULE=on", "PWD="+modDir) + cmd.Stderr = new(strings.Builder) + + out, err := cmd.Output() + if err != nil { + return out, fmt.Errorf("%s: %w\nstderr:\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) + } + return out, nil + } + + _, err = runCommand("go", "mod", "init", "github.com/aclements/go-misc/greplogs/_embed") + if err != nil { + return nil, err + } + + _, err = runCommand("go", "get", "golang.org/x/build/dashboard@HEAD") + if err != nil { + return nil, err + } + + err = os.WriteFile(filepath.Join(modDir, "broken.go"), brokenScript, 0644) + if err != nil { + return nil, err + } + + out, err := runCommand("go", "run", "broken.go") + if err != nil { + return nil, err + } + + broken = strings.Split(strings.TrimSpace(string(out)), "\n") + sort.Strings(broken) + return broken, nil +} diff --git a/greplogs/main.go b/greplogs/main.go index d7de266..c38b160 100644 --- a/greplogs/main.go +++ b/greplogs/main.go @@ -64,6 +64,8 @@ const ( colorMatch = colorBold | colorFgRed ) +var brokenBuilders []string + func main() { // XXX What I want right now is just to point it at a bunch of // logs and have it extract the failures. @@ -91,6 +93,29 @@ func main() { os.Exit(2) } + if *flagTriage { + *flagFilesOnly = true + if len(failRegexps) == 0 && len(fileRegexps) == 0 { + failRegexps.Set(".") + } + + if before.Time.IsZero() { + year, month, day := time.Now().UTC().Date() + before = timeFlag{Time: time.Date(year, month, day, 0, 0, 0, 0, time.UTC)} + } + + var err error + brokenBuilders, err = listBrokenBuilders() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if len(brokenBuilders) > 0 { + fmt.Fprintf(os.Stderr, "omitting builders with known issues:\n\t%s\n\n", strings.Join(brokenBuilders, "\n\t")) + } + + } + status := 1 defer func() { os.Exit(status) }() @@ -169,6 +194,11 @@ var pathDateRE = regexp.MustCompile(`^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})-([0- func process(path, nicePath string) (found bool, err error) { // If this is from the dashboard, filter by builder and date and get the builder URL. builder := filepath.Base(nicePath) + for _, b := range brokenBuilders { + if builder == b { + return false, nil + } + } if omit.AnyMatchString(builder) { return false, nil }