Skip to content

Commit

Permalink
greplogs: set more flag defaults when --triage is set
Browse files Browse the repository at this point in the history
Also omit builders with known issues when --triage is set.

For golang/go#52653.
  • Loading branch information
Bryan C. Mills committed May 27, 2022
1 parent f32396e commit 59e2ae9
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 0 deletions.
26 changes: 26 additions & 0 deletions greplogs/_embed/broken.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
110 changes: 110 additions & 0 deletions greplogs/broken.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// 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"
"errors"
"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)
}
}()

// Though this be madness, yet there is method in 't.
//
// Our goals here are:
//
// 1. Always use the most up-to-date information about broken builders, even
// if the user hasn't recently updated the greplogs binary.
//
// 2. Avoid the need to massively refactor the builder configuration right
// now. (Currently, the Go builders are configured programmatically in the
// x/build/dashboard package, not in external configuration files.)
//
// 3. Avoid the need to redeploy a production x/build/cmd/coordinator or
// x/build/devapp to pick up changes. (A user triaging test failures might
// not have access to deploy the coordinator, or might not want to disrupt
// running tests or active gomotes by pushing it.)
//
// Goals (2) and (3) imply that we must use x/build/dashboard, not fetch the
// list from build.golang.org or dev.golang.org. Since that is a Go package,
// we must run it as a Go program in order to evaluate it.
//
// Goal (1) implies that we must use x/build at HEAD, not (say) at whatever
// version of x/build this command was built with. We could perhaps relax that
// constraint if we move greplogs itself into x/build and consistently triage
// using 'go run golang.org/x/build/cmd/greplogs@HEAD' instead of an installed
// 'greplogs'.

if os.Getenv("GO111MODULE") == "off" {
return nil, errors.New("operation requires GO111MODULE=on or auto")
}

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(),
"PWD="+modDir, // match cmd.Dir
"GOPRIVATE=golang.org/x/build", // avoid proxy cache; see https://go.dev/issue/38065
)
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
}
29 changes: 29 additions & 0 deletions greplogs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -91,6 +93,28 @@ 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) }()

Expand Down Expand Up @@ -169,6 +193,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
}
Expand Down

0 comments on commit 59e2ae9

Please sign in to comment.