github.com/friedemannf/reviewdog@v0.14.0/doghouse/appengine/main.go (about)

     1  package main
     2  
     3  import (
     4  	"io/ioutil"
     5  	"log"
     6  	"net/http"
     7  	"os"
     8  	"strconv"
     9  
    10  	"contrib.go.opencensus.io/exporter/stackdriver"
    11  	"contrib.go.opencensus.io/exporter/stackdriver/propagation"
    12  	"github.com/haya14busa/secretbox"
    13  	"github.com/justinas/nosurf"
    14  	"go.opencensus.io/plugin/ochttp"
    15  	"go.opencensus.io/trace"
    16  
    17  	"github.com/friedemannf/reviewdog/doghouse/server/cookieman"
    18  	"github.com/friedemannf/reviewdog/doghouse/server/storage"
    19  )
    20  
    21  func mustCookieMan() *cookieman.CookieMan {
    22  	// Create secret key by following command.
    23  	// $ ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'
    24  	cipher, err := secretbox.NewFromHexKey(mustGetenv("SECRETBOX_SECRET"))
    25  	if err != nil {
    26  		log.Fatalf("failed to create secretbox: %v", err)
    27  	}
    28  	c := cookieman.CookieOption{
    29  		Cookie: http.Cookie{
    30  			HttpOnly: true,
    31  			Secure:   true,
    32  			Path:     "/",
    33  		},
    34  	}
    35  	return cookieman.New(cipher, c)
    36  }
    37  
    38  func mustGitHubAppsPrivateKey() []byte {
    39  	// Private keys https://github.com/settings/apps/reviewdog
    40  	githubAppsPrivateKey, err := ioutil.ReadFile(mustGetenv("GITHUB_PRIVATE_KEY_FILE"))
    41  	if err != nil {
    42  		log.Fatalf("could not read private key: %s", err)
    43  	}
    44  	return githubAppsPrivateKey
    45  }
    46  
    47  func mustGetenv(name string) string {
    48  	s := os.Getenv(name)
    49  	if s == "" {
    50  		log.Fatalf("%s is not set", name)
    51  	}
    52  	return s
    53  }
    54  
    55  func mustIntEnv(name string) int {
    56  	s := os.Getenv(name)
    57  	if s == "" {
    58  		log.Fatalf("%s is not set", name)
    59  	}
    60  	i, err := strconv.Atoi(s)
    61  	if err != nil {
    62  		log.Fatal(err)
    63  	}
    64  	return i
    65  }
    66  
    67  func main() {
    68  	configureTrace()
    69  	initTemplates()
    70  
    71  	integrationID := mustIntEnv("GITHUB_INTEGRATION_ID")
    72  	ghPrivateKey := mustGitHubAppsPrivateKey()
    73  
    74  	ghInstStore := storage.GitHubInstallationDatastore{}
    75  	ghRepoTokenStore := storage.GitHubRepoTokenDatastore{}
    76  
    77  	ghHandler := NewGitHubHandler(
    78  		mustGetenv("GITHUB_CLIENT_ID"),
    79  		mustGetenv("GITHUB_CLIENT_SECRET"),
    80  		mustCookieMan(),
    81  		ghPrivateKey,
    82  		integrationID,
    83  	)
    84  
    85  	ghChecker := githubChecker{
    86  		privateKey:       ghPrivateKey,
    87  		integrationID:    integrationID,
    88  		ghInstStore:      &ghInstStore,
    89  		ghRepoTokenStore: &ghRepoTokenStore,
    90  		tr: &ochttp.Transport{
    91  			// Use Google Cloud propagation format.
    92  			Propagation: &propagation.HTTPFormat{},
    93  		},
    94  	}
    95  
    96  	ghWebhookHandler := githubWebhookHandler{
    97  		secret:      []byte(mustGetenv("GITHUB_WEBHOOK_SECRET")),
    98  		ghInstStore: &ghInstStore,
    99  	}
   100  
   101  	mu := http.NewServeMux()
   102  
   103  	// Register Admin handlers.
   104  	mu.HandleFunc("/_ah/warmup", warmupHandler)
   105  
   106  	handleFunc(mu, "/", handleTop)
   107  	handleFunc(mu, "/check", ghChecker.handleCheck)
   108  	handleFunc(mu, "/gh_/webhook", ghWebhookHandler.handleWebhook)
   109  	handleFunc(mu, "/gh_/auth/callback", ghHandler.HandleAuthCallback)
   110  	handleFunc(mu, "/gh_/logout", ghHandler.HandleLogout)
   111  	mu.Handle("/gh/", nosurf.New(ochttp.WithRouteTag(ghHandler.LogInHandler(http.HandlerFunc(ghHandler.HandleGitHubTop)), "/gh/")))
   112  
   113  	http.Handle("/", mu)
   114  	log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), &ochttp.Handler{
   115  		Handler:     mu,
   116  		Propagation: &propagation.HTTPFormat{},
   117  	}))
   118  }
   119  
   120  func handleFunc(mu *http.ServeMux, pattern string, handler func(http.ResponseWriter, *http.Request)) {
   121  	mu.Handle(pattern,
   122  		ochttp.WithRouteTag(http.HandlerFunc(handler), pattern))
   123  }
   124  
   125  func handleTop(w http.ResponseWriter, _ *http.Request) {
   126  	var data struct {
   127  		Title string
   128  	}
   129  	data.Title = "reviewdog"
   130  	topTmpl.ExecuteTemplate(w, "base", &data)
   131  }
   132  
   133  // Document: https://cloud.google.com/trace/docs/setup/go
   134  func configureTrace() {
   135  	// Create and register a OpenCensus Stackdriver Trace exporter.
   136  	exporter, err := stackdriver.NewExporter(stackdriver.Options{
   137  		ProjectID: os.Getenv("GOOGLE_CLOUD_PROJECT"),
   138  	})
   139  	if err != nil {
   140  		log.Fatal(err)
   141  	}
   142  	trace.RegisterExporter(exporter)
   143  	trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
   144  }