Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: autoroll/go/autoroll/main.go

Issue 1411553004: Add autoroll server (Closed) Base URL: https://skia.googlesource.com/buildbot@arb_status
Patch Set: More fixes Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: autoroll/go/autoroll/main.go
diff --git a/autoroll/go/autoroll/main.go b/autoroll/go/autoroll/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..5a68a40b049957529209d0fe6710d980e0ee9c15
--- /dev/null
+++ b/autoroll/go/autoroll/main.go
@@ -0,0 +1,232 @@
+/*
+ Automatic DEPS rolls of Skia into Chrome.
+*/
+
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "net/http"
+ "path"
+ "path/filepath"
+ "runtime"
+ "text/template"
+ "time"
+
+ "github.com/gorilla/mux"
+ "github.com/skia-dev/glog"
+
+ "go.skia.org/infra/go/auth"
+ "go.skia.org/infra/go/autoroll"
+ "go.skia.org/infra/go/common"
+ "go.skia.org/infra/go/login"
+ "go.skia.org/infra/go/metadata"
+ "go.skia.org/infra/go/rietveld"
+ "go.skia.org/infra/go/skiaversion"
+ "go.skia.org/infra/go/util"
+)
+
+const (
+ RIETVELD_URL = "https://codereview.chromium.org"
+)
+
+var (
+ arb *autoroll.AutoRoller = nil
+
+ mainTemplate *template.Template = nil
+)
+
+// flags
+var (
+ graphiteServer = flag.String("graphite_server", "localhost:2003", "Where is Graphite metrics ingestion server running.")
+ host = flag.String("host", "localhost", "HTTP service host")
+ port = flag.String("port", ":8003", "HTTP service port (e.g., ':8003')")
+ useMetadata = flag.Bool("use_metadata", true, "Load sensitive values from metadata not from flags.")
+ testing = flag.Bool("testing", false, "Set to true for locally testing rules. No email will be sent.")
+ workdir = flag.String("workdir", ".", "Directory to use for scratch work.")
+ resourcesDir = flag.String("resources_dir", "", "The directory to find templates, JS, and CSS files. If blank the current directory will be used.")
+)
+
+func getSheriff() ([]string, error) {
+ resp, err := http.Get("https://skia-tree-status.appspot.com/current-sheriff")
+ if err != nil {
+ return nil, err
+ }
+ defer util.Close(resp.Body)
+ var sheriff struct {
+ Username string `json:"username"`
+ }
+ if err := json.NewDecoder(resp.Body).Decode(&sheriff); err != nil {
+ return nil, err
+ }
+ // TODO(borenet): Use the real sheriff when ready to land.
+ glog.Infof("Faking the sheriff to avoid spam. Real sheriff is %s", sheriff.Username)
+ return []string{"borenet@google.com" /*sheriff.Username*/}, nil
+}
+
+func getCQExtraTrybots() ([]string, error) {
+ return []string{"tryserver.blink:linux_blink_rel"}, nil
+}
+
+func reloadTemplates() {
+ // Change the current working directory to two directories up from this source file so that we
+ // can read templates and serve static (res/) files.
+
+ if *resourcesDir == "" {
+ _, filename, _, _ := runtime.Caller(0)
+ *resourcesDir = filepath.Join(filepath.Dir(filename), "../..")
+ }
+ mainTemplate = template.Must(template.ParseFiles(
+ filepath.Join(*resourcesDir, "templates/main.html"),
+ filepath.Join(*resourcesDir, "templates/header.html"),
+ ))
+}
+
+func Init() {
+ reloadTemplates()
+}
+
+func modeJsonHandler(w http.ResponseWriter, r *http.Request) {
+ if !login.IsAGoogler(r) {
+ util.ReportError(w, r, fmt.Errorf("User does not have edit rights."), "You must be logged in with an @google.com account to do that.")
+ return
+ }
+
+ var mode struct {
+ Mode string `json:"mode"`
+ }
+ defer util.Close(r.Body)
+ if err := json.NewDecoder(r.Body).Decode(&mode); err != nil {
+ util.ReportError(w, r, err, "Failed to decode request body.")
+ return
+ }
+
+ if err := arb.SetMode(autoroll.Mode(mode.Mode)); err != nil {
+ util.ReportError(w, r, err, "Failed to set AutoRoll mode.")
+ return
+ }
+
+ // Return the ARB status.
+ statusJsonHandler(w, r)
+}
+
+func statusJsonHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ status := struct {
+ Mode string `json:"mode"`
+ Status string `json:"status"`
+ CurrentRoll *autoroll.AutoRollIssue `json:"currentRoll"`
+ Recent []*autoroll.AutoRollIssue `json:"recent"`
+ ValidModes []string `json:"validModes"`
+ }{
+ Mode: string(arb.GetMode()),
+ Status: string(arb.GetStatus()),
+ CurrentRoll: arb.GetCurrentRoll(),
+ Recent: arb.GetRecentRolls(),
+ ValidModes: autoroll.VALID_MODES,
+ }
+ if err := json.NewEncoder(w).Encode(&status); err != nil {
+ glog.Error(err)
+ }
+}
+
+func mainHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html")
+
+ // Don't use cached templates in testing mode.
+ if *testing {
+ reloadTemplates()
+ }
+
+ if err := mainTemplate.Execute(w, struct{}{}); err != nil {
+ glog.Errorln("Failed to expand template:", err)
+ }
+}
+
+func runServer(serverURL string) {
+ r := mux.NewRouter()
+ r.PathPrefix("/res/").HandlerFunc(util.MakeResourceHandler(*resourcesDir))
+ r.HandleFunc("/", mainHandler)
+ r.HandleFunc("/json/mode", modeJsonHandler).Methods("POST")
+ r.HandleFunc("/json/status", statusJsonHandler)
+ r.HandleFunc("/json/version", skiaversion.JsonHandler)
+ r.HandleFunc("/oauth2callback/", login.OAuth2CallbackHandler)
+ r.HandleFunc("/logout/", login.LogoutHandler)
+ r.HandleFunc("/loginstatus/", login.StatusHandler)
+ http.Handle("/", util.LoggingGzipRequestResponse(r))
+ glog.Infof("Ready to serve on %s", serverURL)
+ glog.Fatal(http.ListenAndServe(*port, nil))
+}
+
+func main() {
+ defer common.LogPanic()
+ common.InitWithMetrics("autoroll", graphiteServer)
+ v, err := skiaversion.GetVersion()
+ if err != nil {
+ glog.Fatal(err)
+ }
+ glog.Infof("Version %s, built at %s", v.Commit, v.Date)
+
+ if *testing {
+ *useMetadata = false
+ }
+
+ // Create the Rietveld client.
+ client, err := auth.NewClientFromIdAndSecret(rietveld.CLIENT_ID, rietveld.CLIENT_SECRET, path.Join(*workdir, "oauth_cache"), rietveld.OAUTH_SCOPES...)
+ if err != nil {
+ glog.Fatal(err)
+ }
+ r := rietveld.New(RIETVELD_URL, client)
+
+ // Retrieve the list of extra CQ trybots.
+ // TODO(borenet): Make this editable on the web front-end.
+ cqExtraTrybots, err := getCQExtraTrybots()
+ if err != nil {
+ glog.Fatal(err)
+ }
+
+ // Retrieve the initial email list.
+ emails, err := getSheriff()
+ if err != nil {
+ glog.Fatal(err)
+ }
+
+ // Start the autoroller.
+ arb, err = autoroll.NewAutoRoller(*workdir, cqExtraTrybots, emails, r, time.Minute)
+ if err != nil {
+ glog.Fatal(err)
+ }
+
+ // Update the current sheriff in a loop.
+ go func() {
+ for _ = range time.Tick(30 * time.Minute) {
+ emails, err := getSheriff()
+ if err != nil {
+ glog.Errorf("Failed to retrieve current sheriff: %s", err)
+ } else {
+ arb.SetEmails(emails)
+ }
+ }
+ }()
+
+ serverURL := "https://" + *host
+ if *testing {
+ serverURL = "http://" + *host + *port
+ }
+
+ // By default use a set of credentials setup for localhost access.
+ var cookieSalt = "notverysecret"
+ var clientID = "31977622648-1873k0c1e5edaka4adpv1ppvhr5id3qm.apps.googleusercontent.com"
+ var clientSecret = "cw0IosPu4yjaG2KWmppj2guj"
+ var redirectURL = serverURL + "/oauth2callback/"
+ if *useMetadata {
+ cookieSalt = metadata.Must(metadata.ProjectGet(metadata.COOKIESALT))
+ clientID = metadata.Must(metadata.ProjectGet(metadata.CLIENT_ID))
+ clientSecret = metadata.Must(metadata.ProjectGet(metadata.CLIENT_SECRET))
+ }
+ login.Init(clientID, clientSecret, redirectURL, cookieSalt, login.DEFAULT_SCOPE, login.DEFAULT_DOMAIN_WHITELIST, false)
+
+ runServer(serverURL)
+}
« no previous file with comments | « autoroll/elements.html ('k') | autoroll/package.json » ('j') | autoroll/templates/main.html » ('J')

Powered by Google App Engine
This is Rietveld 408576698