// Copyright 2014 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.

// The retrybuilds command clears build failures from the build.golang.org dashboard
// to force them to be rebuilt.
//
// Valid usage modes:
//
//	retrybuilds -loghash=f45f0eb8
//	retrybuilds -builder=openbsd-amd64
//	retrybuilds -builder=openbsd-amd64 -hash=6fecb7
//	retrybuilds -redo-flaky
//	retrybuilds -redo-flaky -builder=linux-amd64-clang
//	retrybuilds -substr="failed to find foo"
//	retrybuilds -substr="failed to find foo" -builder=linux-amd64-stretch
package main

import (
	"bytes"
	"context"
	"crypto/hmac"
	"crypto/md5"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"golang.org/x/build/buildenv"
	"golang.org/x/build/cmd/coordinator/protos"
	"golang.org/x/build/internal/iapclient"
	"golang.org/x/build/internal/secret"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/oauth"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

var (
	dryRun        = flag.Bool("dry-run", false, "just report what would've been done, without changing anything")
	masterKeyFile = flag.String("masterkey", filepath.Join(os.Getenv("HOME"), "keys", "gobuilder-master.key"), "path to Go builder master key. If present, the key argument is not necessary")
	keyFile       = flag.String("key", "", "path to key file")
	builder       = flag.String("builder", "", "builder to wipe a result for. Empty means all.")
	hash          = flag.String("hash", "", "Hash to wipe. If empty, all will be wiped.")
	redoFlaky     = flag.Bool("redo-flaky", false, "Reset all flaky builds. If builder is empty, the master key is required.")
	builderPrefix = flag.String("builder-prefix", "https://build.golang.org", "builder URL prefix")
	logHash       = flag.String("loghash", "", "If non-empty, clear the build that failed with this loghash prefix")
	sendMasterKey = flag.Bool("sendmaster", false, "send the master key in request instead of a builder-specific key; allows overriding actions of revoked keys")
	branch        = flag.String("branch", "master", "branch to find flakes from (for use with -redo-flaky)")
	substr        = flag.String("substr", "", "if non-empty, redoes all build failures whose failure logs contain this substring")
	grpcHost      = flag.String("grpc-host", "build.golang.org:443", "use gRPC for communicating with the Coordinator API")
)

type Failure struct {
	Builder string
	Hash    string
	LogURL  string
}

func main() {
	log.SetFlags(0)
	buildenv.RegisterStagingFlag()
	flag.Parse()

	*builderPrefix = strings.TrimSuffix(*builderPrefix, "/")
	ctx := context.Background()
	ts, err := iapclient.TokenSource(ctx)
	if err != nil {
		log.Fatalf("failed to retrieve oauth token: %s", err)
	}
	opts := []grpc.DialOption{
		grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{InsecureSkipVerify: strings.HasPrefix(*grpcHost, "localhost:")})),
		grpc.WithDefaultCallOptions(grpc.PerRPCCredentials(oauth.TokenSource{TokenSource: ts})),
		grpc.WithBlock(),
	}
	cc, err := grpc.DialContext(ctx, *grpcHost, opts...)
	if err != nil {
		log.Fatalf("grpc.DialContext(_, %q, _) = %v, wanted no error", *grpcHost, err)
	}
	cl := client{
		coordinator: protos.NewCoordinatorClient(cc),
	}

	if *logHash != "" {
		substr := "/log/" + *logHash
		for _, f := range failures() {
			if strings.Contains(f.LogURL, substr) {
				log.Printf("Restarting %+v", f)
				cl.wipe(f.Builder, f.Hash)
			}
		}
		log.Printf("wiped %d matching failures\n", cl.wiped)
		return
	}
	if *substr != "" {
		foreachFailure(func(f Failure, failLog string) {
			if strings.Contains(failLog, *substr) {
				log.Printf("Restarting %+v", f)
				cl.wipe(f.Builder, f.Hash)
			}
		})
		log.Printf("wiped %d matching failures\n", cl.wiped)
		return
	}
	if *redoFlaky {
		foreachFailure(func(f Failure, failLog string) {
			if isFlaky(failLog) {
				log.Printf("Restarting flaky %+v", f)
				cl.wipe(f.Builder, f.Hash)
			}
		})
		log.Printf("wiped %d matching failures\n", cl.wiped)
		return
	}
	if *builder == "" {
		log.Fatalf("Missing -builder, -redo-flaky, -substr, or -loghash flag.")
	}
	if *hash == "" {
		for _, f := range failures() {
			if f.Builder != *builder {
				continue
			}
			log.Printf("Restarting %+v", f)
			cl.wipe(f.Builder, f.Hash)
		}
		log.Printf("wiped %d matching failures\n", cl.wiped)
		return
	}
	fullHash := fullHash(*hash)
	log.Printf("Restarting %q", fullHash)
	cl.wipe(*builder, fullHash)
	log.Printf("wiped %d matching failures\n", cl.wiped)
}

func foreachFailure(fn func(f Failure, failLog string)) {
	gate := make(chan bool, 50)
	var wg sync.WaitGroup
	for _, f := range failures() {
		f := f
		if *builder != "" && f.Builder != *builder {
			continue
		}
		gate <- true
		wg.Add(1)
		go func() {
			defer wg.Done()
			defer func() { <-gate }()
			res, err := http.Get(f.LogURL)
			if err != nil {
				log.Fatalf("Error fetching %s: %v", f.LogURL, err)
			}
			failLog, err := ioutil.ReadAll(res.Body)
			res.Body.Close()
			if err != nil {
				log.Fatalf("Error reading %s: %v", f.LogURL, err)
			}
			fn(f, string(failLog))
		}()
	}
	wg.Wait()
}

var flakePhrases = []string{
	"No space left on device",
	"no space left on device", // solaris case apparently
	"fatal error: error in backend: IO failure on output stream",
	"Boffset: unknown state 0",
	"Bseek: unknown state 0",
	"error exporting repository: exit status",
	"remote error: User Is Over Quota",
	"fatal: remote did not send all necessary objects",
	"Failed to schedule \"", // e.g. Failed to schedule "go_test:archive/tar" test after 3 tries.
	"lookup _xmpp-server._tcp.google.com. on 8.8.8.8:53: dial udp 8.8.8.8:53: i/o timeout",
	"lookup _xmpp-server._tcp.google.com on",
	"lookup gmail.com. on 8.8.8.8:53: dial udp 8.8.8.8:53: i/o timeout",
	"lookup gmail.com on 8.8.8.8:53",
	"lookup www.mit.edu on ",
	"undefined: runtime.SetMutexProfileFraction", // ppc64 builders had not-quite-go1.8 bootstrap
	"make.bat: The parameter is incorrect",
	"killed",
	"memory",
	"allocate",
	"Killed",
	"Error running API checker: exit status 1",
	"/compile: exit status 1",
	"cmd/link: exit status 1",
}

func isFlaky(failLog string) bool {
	if strings.Count(strings.TrimSpace(failLog), "\n") < 2 {
		return true
	}
	if strings.HasPrefix(failLog, "exit status ") {
		return true
	}
	if strings.HasPrefix(failLog, "timed out after ") {
		return true
	}
	if strings.HasPrefix(failLog, "Failed to schedule ") {
		return true
	}
	for _, phrase := range flakePhrases {
		if strings.Contains(failLog, phrase) {
			return true
		}
	}
	numLines := strings.Count(failLog, "\n")
	if numLines < 20 && strings.Contains(failLog, "error: exit status") {
		return true
	}
	// e.g. fatal: destination path 'go.tools.TMP' already exists and is not an empty directory.
	// To be fixed in golang.org/issue/9407
	if strings.Contains(failLog, "fatal: destination path '") &&
		strings.Contains(failLog, "' already exists and is not an empty directory.") {
		return true
	}
	return false
}

func fullHash(h string) string {
	if len(h) == 40 {
		return h
	}
	if h != "" {
		for _, f := range failures() {
			if strings.HasPrefix(f.Hash, h) {
				return f.Hash
			}
		}
	}
	log.Fatalf("invalid hash %q; failed to finds its full hash. Not a recent failure?", h)
	panic("unreachable")
}

type client struct {
	coordinator protos.CoordinatorClient
	wiped       int // wiped is how many build results have been wiped.
}

// grpcWipe wipes a git hash failure for the provided builder and hash.
// Only the main Go repo is currently supported.
// TODO(golang.org/issue/34744) - replace HTTP wipe with this after gRPC API for ClearResults is deployed
func (c *client) grpcWipe(builder, hash string) {
	md := metadata.New(map[string]string{"coordinator-authorization": "builder " + builderKey(builder)})
	for i := 0; i < 10; i++ {
		ctx, cancel := context.WithTimeout(metadata.NewOutgoingContext(context.Background(), md), time.Minute)
		resp, err := c.coordinator.ClearResults(ctx, &protos.ClearResultsRequest{
			Builder: builder,
			Hash:    hash,
		})
		cancel()

		if err != nil {
			s, _ := status.FromError(err)
			switch s.Code() {
			case codes.Aborted:
				log.Printf("Concurrent datastore transaction wiping %v %v: retrying in 1 second", builder, hash)
				time.Sleep(time.Second)
			case codes.DeadlineExceeded:
				log.Printf("Timeout wiping %v %v: retrying", builder, hash)
			default:
				log.Fatalln(err)
			}
			continue
		}
		log.Printf("cl.ClearResults(%q, %q) = %v: resp: %v", builder, hash, status.Code(err), resp)
		c.wiped++
		return
	}
}

// wipe wipes the git hash failure for the provided failure.
// Only the main go repo is currently supported.
func (c *client) wipe(builder, hash string) {
	if *dryRun {
		c.wiped++ // Pretend.
		return
	}
	if *grpcHost != "" {
		// TODO(golang.org/issue/34744) - Remove HTTP logic after gRPC API for ClearResults is deployed
		// to the Coordinator.
		c.grpcWipe(builder, hash)
		return
	}
	vals := url.Values{
		"builder": {builder},
		"hash":    {hash},
		"key":     {builderKey(builder)},
	}
	for i := 0; i < 10; i++ {
		res, err := http.PostForm(*builderPrefix+"/clear-results?"+vals.Encode(), nil)
		if err != nil {
			log.Fatal(err)
		}
		body, err := ioutil.ReadAll(res.Body)
		res.Body.Close()
		if err != nil {
			log.Fatal(err)
		}
		if res.StatusCode != 200 {
			log.Fatalf("Error clearing %v hash %q: %v", builder, hash, res.Status)
		}
		var dashResponse struct {
			Error string
		}
		if err := json.Unmarshal(body, &dashResponse); err != nil {
			log.Fatalf("Bad dashboard response: %v\nBody: %s", err, body)
		}

		switch e := dashResponse.Error; e {
		case "datastore: concurrent transaction":
			log.Printf("Concurrent datastore transaction wiping %v %v: retrying in 1 second", builder, hash)
			time.Sleep(time.Second)
			continue
		default:
			log.Fatalf("Dashboard error: %v", e)
		case "":
			c.wiped++
			return
		}
	}
	log.Fatalf("Too many datastore transaction issues wiping %v %v", builder, hash)
}

func builderKey(builder string) string {
	if v, ok := builderKeyFromMaster(builder); ok {
		return v
	}
	if *keyFile == "" {
		log.Fatalf("No --key specified for builder %s", builder)
	}
	slurp, err := ioutil.ReadFile(*keyFile)
	if err != nil {
		log.Fatalf("Error reading builder key %s: %v", builder, err)
	}
	return strings.TrimSpace(string(slurp))
}

func builderKeyFromMaster(builder string) (key string, ok bool) {
	masterKey, err := getMasterKeyFromSecretManager()
	if err != nil {
		slurp, err := ioutil.ReadFile(*masterKeyFile)
		if err != nil {
			return "", false
		}
		masterKey = string(bytes.TrimSpace(slurp))
	}
	if *sendMasterKey {
		return masterKey, true
	}
	h := hmac.New(md5.New, []byte(masterKey))
	h.Write([]byte(builder))
	return fmt.Sprintf("%x", h.Sum(nil)), true
}

// getMasterKeyFromSecretManager retrieves the master key
// from the secret manager service.
func getMasterKeyFromSecretManager() (string, error) {
	sc, err := secret.NewClientInProject(buildenv.FromFlags().ProjectName)
	if err != nil {
		return "", err
	}
	defer sc.Close()
	return sc.Retrieve(context.Background(), secret.NameBuilderMasterKey)
}

var (
	failMu    sync.Mutex
	failCache []Failure
)

func failures() (ret []Failure) {
	failMu.Lock()
	ret = failCache
	failMu.Unlock()
	if ret != nil {
		return
	}
	ret = []Failure{} // non-nil

	res, err := http.Get(*builderPrefix + "/?mode=failures&branch=" + url.QueryEscape(*branch))
	if err != nil {
		log.Fatal(err)
	}
	slurp, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		log.Fatal(err)
	}
	body := string(slurp)
	for _, line := range strings.Split(body, "\n") {
		f := strings.Fields(line)
		if len(f) == 3 {
			ret = append(ret, Failure{
				Hash:    f[0],
				Builder: f[1],
				LogURL:  f[2],
			})
		}
	}

	failMu.Lock()
	failCache = ret
	failMu.Unlock()
	return ret
}
