blob: 9be213a5d52ef0593063c9fe04e9832f1d2146ed [file] [log] [blame]
package main
import (
"context"
"flag"
"net/http"
"time"
"cloud.google.com/go/datastore"
"github.com/go-chi/chi/v5"
"go.skia.org/infra/autoroll/go/config"
"go.skia.org/infra/autoroll/go/config/db"
"go.skia.org/infra/autoroll/go/status"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/common"
"go.skia.org/infra/go/ds"
"go.skia.org/infra/go/firestore"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/go/webhook"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
)
const (
webhookSecretProject = "skia-infra-public"
webhookSecretName = "autoroll-google3-webhook-salt"
)
// flags
var (
rollerName = flag.String("roller_name", "", "Name of the roller.")
childBranch = flag.String("child_branch", "", "Git branch of the child.")
childRepo = flag.String("child_repo", "", "Git repo URL of the child.")
childDisplayName = flag.String("child_display_name", "", "Display name of the child.")
firestoreInstance = flag.String("firestore_instance", "", "Firestore instance to use, eg. \"production\"")
local = flag.Bool("local", false, "Running locally if true. As opposed to in production.")
port = flag.String("port", ":8000", "HTTP service port (e.g., ':8000')")
promPort = flag.String("prom_port", ":20000", "Metrics service address (e.g., ':10110')")
webhookSalt = flag.String("webhook_request_salt", "", "Path to a file containing webhook request salt.")
)
func main() {
common.InitWithMust(
"google3-autoroll",
common.PrometheusOpt(promPort),
)
defer common.Defer()
// Create the config. A lot of functionality requires an actual config
// struct, so we fake most of it here.
cfg := config.Config{
RollerName: *rollerName,
ChildDisplayName: *childDisplayName,
ParentDisplayName: "Google3",
ParentWaterfall: "https://goto.google.com/skia-testing-status",
OwnerPrimary: "fake",
OwnerSecondary: "fake",
Contacts: []string{"fake"},
ServiceAccount: "fake",
IsInternal: true,
Reviewer: []string{"fake"},
CommitMsg: &config.CommitMsgConfig{
BuiltIn: config.CommitMsgConfig_DEFAULT,
},
CodeReview: &config.Config_Google3{
Google3: &config.Google3Config{},
},
Kubernetes: &config.KubernetesConfig{
Cpu: "fake",
Memory: "fake",
Disk: "fake",
Image: "fake",
},
RepoManager: &config.Config_Google3RepoManager{
Google3RepoManager: &config.Google3RepoManagerConfig{
ChildBranch: *childBranch,
ChildRepo: *childRepo,
},
},
}
if err := cfg.Validate(); err != nil {
sklog.Fatal(err)
}
ctx := context.Background()
ts, err := google.DefaultTokenSource(ctx, auth.ScopeUserinfoEmail, auth.ScopeGerrit, datastore.ScopeDatastore)
if err != nil {
sklog.Fatal(err)
}
const namespace = ds.AUTOROLL_INTERNAL_NS
if err := ds.InitWithOpt(common.PROJECT_ID, namespace, option.WithTokenSource(ts)); err != nil {
sklog.Fatal(err)
}
client := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()
if !*local {
// Update the roller config in the DB.
configDB, err := db.NewDBWithParams(ctx, firestore.FIRESTORE_PROJECT, namespace, *firestoreInstance, ts)
if err != nil {
sklog.Fatal(err)
}
if err := configDB.Put(ctx, cfg.RollerName, &cfg); err != nil {
sklog.Fatal(err)
}
}
r := chi.NewRouter()
if *webhookSalt != "" {
webhook.MustInitRequestSaltFromFile(*webhookSalt)
} else {
webhook.MustInitRequestSaltFromSecret(webhookSecretProject, webhookSecretName)
}
statusDB, err := status.NewDB(ctx, firestore.FIRESTORE_PROJECT, namespace, *firestoreInstance, ts)
if err != nil {
sklog.Fatalf("Failed to create status DB: %s", err)
}
arb, err := NewAutoRoller(ctx, &cfg, client, statusDB)
if err != nil {
sklog.Fatal(err)
}
arb.AddHandlers(r)
arb.Start(ctx, time.Minute, time.Minute)
h := httputils.LoggingGzipRequestResponse(r)
if !*local {
h = httputils.HealthzAndHTTPS(h)
}
http.Handle("/", h)
sklog.Fatal(http.ListenAndServe(*port, nil))
}