login with oauth2 & update commit status
This commit is contained in:
parent
1cd16acc2b
commit
2422b739f5
|
@ -1 +1,2 @@
|
|||
pr-deployer
|
||||
config.yaml
|
|
@ -0,0 +1,18 @@
|
|||
ServiceType: github
|
||||
RepoURL: https://github.com/go-gitea/gitea
|
||||
OAuth2:
|
||||
ServerURL: https://github.com
|
||||
ClientID: xxxxxx
|
||||
ClientSecret: xxxxxxxx
|
||||
CallbackURL: http://localhost:3001
|
||||
|
||||
Domain: localhost
|
||||
DomainIP: localhost
|
||||
WebhookSecretKey: ''
|
||||
CodeCacheDir: './data'
|
||||
CloudflareToken: ''
|
||||
CloudflareEmail: ''
|
||||
Proxy:
|
||||
Enabled: false
|
||||
ProxyURL: 'socks5:127.0.0.1:1080'
|
||||
ProxyHosts: github.com
|
35
go.mod
35
go.mod
|
@ -3,37 +3,68 @@ module gitea.com/gitea/pr-deployer
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
gitea.com/go-chi/session v0.0.0-20211013065435-7d334f340c09
|
||||
github.com/cloudflare/cloudflare-go v0.26.0
|
||||
github.com/docker/docker v20.10.10+incompatible
|
||||
github.com/go-chi/chi/v5 v5.0.4
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/google/go-github/v39 v39.2.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cobra v1.2.1
|
||||
github.com/spf13/viper v1.8.1
|
||||
github.com/unrolled/render v1.4.0
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.17 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/containerd/containerd v1.5.7 // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/unknwon/com v1.0.1 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
|
||||
google.golang.org/grpc v1.38.0 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
9
main.go
9
main.go
|
@ -1,13 +1,18 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gitea.com/gitea/pr-deployer/cmd"
|
||||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := settings.Init(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package github
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"gitea.com/gitea/pr-deployer/pkgs/proxy"
|
||||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
|
||||
"github.com/google/go-github/v39/github"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func GetGithubClient(token *oauth2.Token) *github.Client {
|
||||
ts := oauth2.StaticTokenSource(token)
|
||||
var client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Base: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return proxy.Proxy()(req)
|
||||
},
|
||||
},
|
||||
Source: oauth2.ReuseTokenSource(nil, ts),
|
||||
},
|
||||
}
|
||||
|
||||
githubClient := github.NewClient(client)
|
||||
if settings.BaseURL != "https://github.com" {
|
||||
githubClient, _ = github.NewEnterpriseClient(settings.BaseURL, settings.BaseURL, client)
|
||||
}
|
||||
|
||||
return githubClient
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
hostMatchers []glob.Glob
|
||||
)
|
||||
|
||||
// GetProxyURL returns proxy url
|
||||
func GetProxyURL() string {
|
||||
if !settings.Proxy.Enabled {
|
||||
return ""
|
||||
}
|
||||
|
||||
if settings.Proxy.ProxyURL == "" {
|
||||
if os.Getenv("http_proxy") != "" {
|
||||
return os.Getenv("http_proxy")
|
||||
}
|
||||
return os.Getenv("https_proxy")
|
||||
}
|
||||
return settings.Proxy.ProxyURL
|
||||
}
|
||||
|
||||
// Match return true if url needs to be proxied
|
||||
func Match(u string) bool {
|
||||
if !settings.Proxy.Enabled {
|
||||
return false
|
||||
}
|
||||
|
||||
// enforce do once
|
||||
Proxy()
|
||||
|
||||
for _, v := range hostMatchers {
|
||||
if v.Match(u) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Proxy returns the system proxy
|
||||
func Proxy() func(req *http.Request) (*url.URL, error) {
|
||||
if !settings.Proxy.Enabled {
|
||||
return func(req *http.Request) (*url.URL, error) {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if settings.Proxy.ProxyURL == "" {
|
||||
return http.ProxyFromEnvironment
|
||||
}
|
||||
|
||||
once.Do(func() {
|
||||
for _, h := range settings.Proxy.ProxyHosts {
|
||||
if g, err := glob.Compile(h); err == nil {
|
||||
hostMatchers = append(hostMatchers, g)
|
||||
} else {
|
||||
log.Error("glob.Compile %s failed: %v", h, err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return func(req *http.Request) (*url.URL, error) {
|
||||
for _, v := range hostMatchers {
|
||||
if v.Match(req.URL.Host) {
|
||||
return http.ProxyURL(settings.Proxy.ProxyURLFixed)(req)
|
||||
}
|
||||
}
|
||||
return http.ProxyFromEnvironment(req)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
my_github "gitea.com/gitea/pr-deployer/pkgs/github"
|
||||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
|
||||
"github.com/google/go-github/v39/github"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func GetPullRequests(token *oauth2.Token, p int) ([]*github.PullRequest, error) {
|
||||
c := my_github.GetGithubClient(token)
|
||||
pulls, _, err := c.PullRequests.List(context.Background(), settings.RepoOwner, settings.RepoName, &github.PullRequestListOptions{
|
||||
Sort: "updated",
|
||||
Direction: "desc",
|
||||
ListOptions: github.ListOptions{
|
||||
Page: p,
|
||||
PerPage: 50,
|
||||
},
|
||||
})
|
||||
|
||||
return pulls, err
|
||||
}
|
|
@ -3,6 +3,7 @@ package services
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -10,13 +11,94 @@ import (
|
|||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
|
||||
"github.com/cloudflare/cloudflare-go"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
git "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/google/go-github/v39/github"
|
||||
)
|
||||
|
||||
func UpdateAndStartPullRequest(number int) error {
|
||||
func UpdateAndStartPullRequest(ctx context.Context, number int, sha string) error {
|
||||
// 0 send commit status
|
||||
if err := updateCommitStatus(ctx, number, sha, statusPending, "", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 1 download the git
|
||||
p := filepath.Join(settings.CodeCacheDir, strconv.Itoa(number))
|
||||
if err := updateGitRepo(number); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2 change domain
|
||||
if err := checkAndUpdateSubDomain(number); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 3 build
|
||||
if err := buildImage(ctx, number); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 4 change reverse server
|
||||
if err := runImage(ctx, number); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 5 send commit status
|
||||
if err := updateCommitStatus(ctx, number, sha, statusSuccess, "", fmt.Sprintf("https://try-pr-%d.gitea.io", number)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runImage(ctx context.Context, number int) error {
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = cli.ContainerExecCreate(ctx, "gitea/gitea:"+getImageTag(number), types.ExecConfig{
|
||||
WorkingDir: getPRDir(number),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func getRepoName() string {
|
||||
return "gitea"
|
||||
}
|
||||
|
||||
func getOwnerName() string {
|
||||
return "go-gitea"
|
||||
}
|
||||
|
||||
const (
|
||||
statusPending = "pending"
|
||||
statusSuccess = "success"
|
||||
statusError = "error"
|
||||
statusFailure = "failure"
|
||||
)
|
||||
|
||||
// updateCommitStatus
|
||||
func updateCommitStatus(ctx context.Context, number int, sha, status, desc, targetURL string) error {
|
||||
c := github.NewClient(nil)
|
||||
// pending, success, error, or failure
|
||||
_, _, err := c.Repositories.CreateStatus(ctx, getOwnerName(), getRepoName(), sha, &github.RepoStatus{
|
||||
State: github.String(status),
|
||||
TargetURL: github.String(targetURL),
|
||||
Description: github.String(desc),
|
||||
Context: github.String("pr-deployer"),
|
||||
// AvatarURL:
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func getPRDir(number int) string {
|
||||
return filepath.Join(settings.CodeCacheDir, strconv.Itoa(number))
|
||||
}
|
||||
|
||||
func updateGitRepo(number int) error {
|
||||
p := getPRDir(number)
|
||||
fmt.Println("clone code into", p)
|
||||
|
||||
// 1.1 git fetch origin +refs/heads/main
|
||||
|
@ -47,17 +129,26 @@ func UpdateAndStartPullRequest(number int) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 2 build
|
||||
func getImageTag(number int) string {
|
||||
return fmt.Sprintf("pr-%d", number)
|
||||
}
|
||||
|
||||
// 3 change domain
|
||||
if err := checkAndUpdateSubDomain(number); err != nil {
|
||||
// buildImage build the docker image via Dockerfile
|
||||
func buildImage(ctx context.Context, number int) error {
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 4 change reverse server
|
||||
|
||||
// 5 send commit status
|
||||
var buildContext io.Reader
|
||||
if _, err = cli.ImageBuild(ctx, buildContext, types.ImageBuildOptions{
|
||||
Tags: []string{getImageTag(number)},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,126 @@
|
|||
package settings
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var (
|
||||
ServiceType string
|
||||
RepoURL string
|
||||
BaseURL string
|
||||
RepoOwner string
|
||||
RepoName string
|
||||
OAuth2CallbackURL string
|
||||
OAuth2ServerURL string
|
||||
OAuth2ClientID string
|
||||
OAuth2ClientSecret string
|
||||
Domain string
|
||||
DomainIP string
|
||||
WebhookSecretKey []byte
|
||||
CodeCacheDir string
|
||||
CloudflareToken string
|
||||
CloudflareEmail string
|
||||
Proxy struct {
|
||||
Enabled bool
|
||||
ProxyURL string
|
||||
ProxyURLFixed *url.URL
|
||||
ProxyHosts []string
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
OAuth2Conf *oauth2.Config
|
||||
)
|
||||
|
||||
func Init() error {
|
||||
viper.SetConfigFile("./config.yaml")
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ServiceType = viper.GetString("ServiceType")
|
||||
if ServiceType == "" {
|
||||
return errors.New("ServiceType cannot be empty")
|
||||
}
|
||||
if !strings.EqualFold(ServiceType, "github") && !strings.EqualFold(ServiceType, "gitea") {
|
||||
return fmt.Errorf("unknow service type: %s", ServiceType)
|
||||
}
|
||||
|
||||
RepoURL = viper.GetString("RepoURL")
|
||||
if RepoURL == "" {
|
||||
return errors.New("RepoURL cannot be empty")
|
||||
}
|
||||
|
||||
u, err := url.Parse(RepoURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
BaseURL = u.Scheme + "://" + u.Host
|
||||
var p = u.Path
|
||||
if strings.HasPrefix(p, "/") {
|
||||
p = p[1:]
|
||||
}
|
||||
fields := strings.Split(p, "/")
|
||||
RepoOwner = fields[0]
|
||||
RepoName = fields[1]
|
||||
|
||||
OAuth2CallbackURL = viper.GetString("OAuth2.CallbackURL")
|
||||
if OAuth2CallbackURL == "" {
|
||||
return errors.New("OAuth2CallbackURL cannot be empty")
|
||||
}
|
||||
OAuth2ServerURL = viper.GetString("OAuth2.ServerURL")
|
||||
if OAuth2ServerURL == "" {
|
||||
return errors.New("OAuth2ServerURL cannot be empty")
|
||||
}
|
||||
|
||||
OAuth2ClientID = viper.GetString("OAuth2.ClientID")
|
||||
if OAuth2ClientID == "" {
|
||||
return errors.New("OAuth2ClientID cannot be empty")
|
||||
}
|
||||
OAuth2ClientSecret = viper.GetString("OAuth2.ClientSecret")
|
||||
if OAuth2ClientSecret == "" {
|
||||
return errors.New("OAuth2ClientSecret cannot be empty")
|
||||
}
|
||||
|
||||
Domain = viper.GetString("Domain")
|
||||
DomainIP = viper.GetString("DomainIP")
|
||||
WebhookSecretKey = []byte(viper.GetString("WebhookSecretKey"))
|
||||
CodeCacheDir = viper.GetString("CodeCacheDir")
|
||||
if err := os.MkdirAll(CodeCacheDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
CloudflareToken = viper.GetString("CloudflareToken")
|
||||
CloudflareEmail = viper.GetString("CloudflareEmail")
|
||||
|
||||
OAuth2Conf = &oauth2.Config{
|
||||
ClientID: OAuth2ClientID,
|
||||
ClientSecret: OAuth2ClientSecret, // change this to your gitea secret id
|
||||
Endpoint: oauth2.Endpoint{
|
||||
TokenURL: fmt.Sprintf("%s/login/oauth/access_token", OAuth2ServerURL),
|
||||
AuthURL: fmt.Sprintf("%s/login/oauth/authorize", OAuth2ServerURL),
|
||||
},
|
||||
RedirectURL: fmt.Sprintf("%s/callback", OAuth2CallbackURL),
|
||||
}
|
||||
|
||||
Proxy.Enabled = viper.GetBool("Proxy.Enabled")
|
||||
Proxy.ProxyURL = viper.GetString("Proxy.ProxyURL")
|
||||
if Proxy.ProxyURL != "" {
|
||||
var err error
|
||||
Proxy.ProxyURLFixed, err = url.Parse(Proxy.ProxyURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
Proxy.ProxyHosts = viper.GetStringSlice("Proxy.ProxyHosts")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package routers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"gitea.com/gitea/pr-deployer/pkgs/proxy"
|
||||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
"gitea.com/go-chi/session"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func Home(w http.ResponseWriter, r *http.Request) {
|
||||
sess := session.GetSession(r)
|
||||
user := sess.Get("user")
|
||||
oriState := "111111" // TODO: use a random
|
||||
|
||||
if user == nil {
|
||||
sess.Set("state", oriState)
|
||||
|
||||
url := settings.OAuth2Conf.AuthCodeURL(oriState, oauth2.AccessTypeOffline)
|
||||
fmt.Printf("Visit the URL for the auth dialog: %v", url)
|
||||
|
||||
http.Redirect(w, r, url, http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/prs", http.StatusFound)
|
||||
}
|
||||
|
||||
func OAuth2Callback(w http.ResponseWriter, r *http.Request) {
|
||||
sess := session.GetSession(r)
|
||||
oriState := sess.Get("state")
|
||||
state := r.FormValue("state")
|
||||
if state != oriState {
|
||||
log.Error("state is not equal")
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
httpClient := &http.Client{
|
||||
Timeout: 20 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
Proxy: func(req *http.Request) (*url.URL, error) {
|
||||
return proxy.Proxy()(req)
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
||||
|
||||
code := r.FormValue("code")
|
||||
tok, err := settings.OAuth2Conf.Exchange(ctx, code)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(tok)
|
||||
sess.Set("token", tok)
|
||||
|
||||
client := settings.OAuth2Conf.Client(ctx, tok)
|
||||
var url string
|
||||
if settings.ServiceType == "gitea" {
|
||||
url = settings.OAuth2ServerURL + "/api/v1/user"
|
||||
} else if settings.ServiceType == "github" {
|
||||
url = "https://api.github.com/user"
|
||||
}
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bs, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(bs))
|
||||
|
||||
var user = make(map[string]interface{})
|
||||
err = json.NewDecoder(bytes.NewReader(bs)).Decode(&user)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(user)
|
||||
sess.Set("user", user)
|
||||
|
||||
http.Redirect(w, r, "/", 302)
|
||||
}
|
|
@ -2,57 +2,68 @@ package routers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"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"
|
||||
|
||||
"gitea.com/gitea/pr-deployer/pkgs/services"
|
||||
"gitea.com/gitea/pr-deployer/pkgs/settings"
|
||||
)
|
||||
|
||||
var rnd *render.Render
|
||||
|
||||
func Web() {
|
||||
rnd = render.New()
|
||||
rnd = render.New(render.Options{
|
||||
IsDevelopment: true,
|
||||
})
|
||||
|
||||
c := chi.NewRouter()
|
||||
c.Use(session.Sessioner())
|
||||
c.Use(middleware.Logger)
|
||||
c.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("You are not login"))
|
||||
})
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
}
|
||||
c := github.NewClient(http.DefaultClient)
|
||||
pulls, _, err := c.PullRequests.List(context.Background(), "go-gitea", "gitea", &github.PullRequestListOptions{
|
||||
Sort: "updated",
|
||||
Direction: "desc",
|
||||
ListOptions: github.ListOptions{
|
||||
Page: p,
|
||||
PerPage: 100,
|
||||
},
|
||||
})
|
||||
|
||||
token := pToken.(*oauth2.Token)
|
||||
pulls, err := services.GetPullRequests(token, 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)
|
||||
}
|
||||
|
@ -65,7 +76,8 @@ func RunPR(w http.ResponseWriter, r *http.Request) {
|
|||
log.Error("start failed")
|
||||
return
|
||||
}
|
||||
if err := services.UpdateAndStartPullRequest(i); err != nil {
|
||||
ctx := context.Background()
|
||||
if err := services.UpdateAndStartPullRequest(ctx, i, fmt.Sprintf("refs/pull/%d/head", i)); err != nil {
|
||||
log.Error("start failed")
|
||||
}
|
||||
}
|
||||
|
@ -96,9 +108,16 @@ func Webhook(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
switch evt := event.(type) {
|
||||
case *github.PullRequestEvent:
|
||||
if err := services.UpdateAndStartPullRequest(*evt.Number); err != nil {
|
||||
switch *evt.Action {
|
||||
case "synchronize":
|
||||
ctx := context.Background()
|
||||
if err := services.UpdateAndStartPullRequest(ctx, *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)
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<div>{{.User.Name}}</div>
|
|
@ -1,5 +1,6 @@
|
|||
<div>{{.user.name}}</div>
|
||||
<ul>
|
||||
{{range .pulls}}
|
||||
<li>{{.Number}}</li>
|
||||
{{end
|
||||
<li>{{.Number}}: <a href="{{.HTMLURL}}">{{.Title}}</a> <button>Start Service</button></li>
|
||||
{{end}}
|
||||
</ul>
|
Loading…
Reference in New Issue