package routers import ( "context" "fmt" "io" "io/fs" "net/http" "path/filepath" "strconv" "gitea.com/gitea/pr-deployer/pkgs/services" "gitea.com/gitea/pr-deployer/pkgs/settings" "golang.org/x/oauth2" "gitea.com/go-chi/session" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/google/go-github/v39/github" log "github.com/sirupsen/logrus" "github.com/unrolled/render" ) var rnd *render.Render type tmplFS struct { fs.FS } func (tfs tmplFS) Walk(root string, walkFn filepath.WalkFunc) error { return fs.WalkDir(tfs, root, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } info, err := d.Info() return walkFn(path, info, err) }) } func (tfs tmplFS) ReadFile(filename string) ([]byte, error) { f, err := tfs.Open(filename) if err != nil { return nil, err } defer f.Close() return io.ReadAll(f) } func convertFS(templateFS fs.FS) render.FileSystem { return tmplFS{templateFS} } func Web(publicFS, templateFS fs.FS) { rnd = render.New(render.Options{ Directory: ".", IsDevelopment: true, FileSystem: convertFS(templateFS), }) c := chi.NewRouter() c.Use(session.Sessioner()) c.Use(middleware.Logger) c.Get("/", Home) c.Get("/callback", OAuth2Callback) c.Get("/prs", ListPRs) c.Post("/pr/{index}/run", RunPR) c.Post("/pr/{index}/stop", StopPR) c.Post("/webhook", Webhook) fs := http.StripPrefix("/public", http.FileServer(http.FS(publicFS))) c.Get("/public/*", func(w http.ResponseWriter, r *http.Request) { fs.ServeHTTP(w, r) }) http.ListenAndServe(":3001", c) } func ListPRs(w http.ResponseWriter, r *http.Request) { sess := session.GetSession(r) pToken := sess.Get("token") if pToken == nil { http.Redirect(w, r, "/", 302) return } p, _ := strconv.Atoi(r.FormValue("p")) if p < 1 { p = 1 } token := pToken.(*oauth2.Token) fmt.Printf("%#v\n", token) c, err := services.NewClient(token) if err != nil { log.Error(err) return } pulls, err := c.GetPullRequests(p) if err != nil { log.Error(err) return } user := sess.Get("user") if err := rnd.HTML(w, http.StatusOK, "pulls", map[string]interface{}{ "pulls": pulls, "user": user, }); err != nil { log.Error(err) } } func RunPR(w http.ResponseWriter, r *http.Request) { idx := chi.URLParam(r, "index") i, _ := strconv.Atoi(idx) if i <= 0 { log.Errorf("start failed: %s is not a valid index", idx) return } ctx := context.Background() sess := session.GetSession(r) pToken := sess.Get("token") if pToken == nil { http.Redirect(w, r, "/", 302) return } token := pToken.(*oauth2.Token) fmt.Printf("%#v\n", token) client, err := services.NewClient(token) if err != nil { log.Error(err) return } if err := services.UpdateAndStartPullRequest(ctx, client, i, ""); err != nil { log.Error(err) } } func StopPR(w http.ResponseWriter, r *http.Request) { idx := chi.URLParam(r, "index") i, _ := strconv.Atoi(idx) if i <= 0 { log.Error("stop failed") return } if err := services.StopPullRequest(i); err != nil { log.Error("stop failed") } } func Webhook(w http.ResponseWriter, r *http.Request) { payload, err := github.ValidatePayload(r, settings.WebhookSecretKey) if err != nil { log.Error(err) return } event, err := github.ParseWebHook(github.WebHookType(r), payload) if err != nil { log.Error(err) return } switch evt := event.(type) { case *github.PullRequestEvent: switch *evt.Action { case "synchronize": ctx := context.Background() // FIXME: get token client, err := services.NewClient(nil) if err != nil { log.Error(err) return } if err := services.UpdateAndStartPullRequest(ctx, client, *evt.Number, *evt.After); err != nil { log.Error(err) } default: log.Trace("pull request %d is %s", *evt.Number, *evt.Action) } default: log.Warn("received %v type event, ignored", event) } }