From 51351d9a9d02f5fef6ee7944e8b2c092f3dbae62 Mon Sep 17 00:00:00 2001 From: letusfly85 Date: Sat, 25 Jul 2015 17:49:39 +0900 Subject: [PATCH 1/5] add gitlab imp --- cmd/drone-server/drone.go | 1 + pkg/remote/gitlab/gitlab.go | 374 ++++++++++++++++++++++++++++++++++++ pkg/remote/gitlab/helper.go | 92 +++++++++ 3 files changed, 467 insertions(+) create mode 100644 pkg/remote/gitlab/gitlab.go create mode 100644 pkg/remote/gitlab/helper.go diff --git a/cmd/drone-server/drone.go b/cmd/drone-server/drone.go index 8d1717ef..1ce65b98 100644 --- a/cmd/drone-server/drone.go +++ b/cmd/drone-server/drone.go @@ -20,6 +20,7 @@ import ( "github.com/drone/drone/pkg/store" _ "github.com/drone/drone/pkg/remote/builtin/github" + _ "github.com/drone/drone/pkg/remote/gitlab" _ "github.com/drone/drone/pkg/store/builtin" _ "net/http/pprof" diff --git a/pkg/remote/gitlab/gitlab.go b/pkg/remote/gitlab/gitlab.go new file mode 100644 index 00000000..499c9a79 --- /dev/null +++ b/pkg/remote/gitlab/gitlab.go @@ -0,0 +1,374 @@ +package gitlab + +import ( + "crypto/tls" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" + + "github.com/Bugagazavr/go-gitlab-client" + "github.com/drone/drone/Godeps/_workspace/src/github.com/hashicorp/golang-lru" + "github.com/drone/drone/pkg/config" + "github.com/drone/drone/pkg/oauth2" + "github.com/drone/drone/pkg/remote" + common "github.com/drone/drone/pkg/types" + "github.com/drone/drone/pkg/utils/httputil" +) + +const ( + DefaultScope = "repo" +) + +const ( + StatusPending = "pending" + StatusSuccess = "success" + StatusFailure = "failure" + StatusError = "error" +) + +const ( + DescPending = "this build is pending" + DescSuccess = "the build was successful" + DescFailure = "the build failed" + DescError = "oops, something went wrong" +) + +type Gitlab struct { + URL string + Client string + Secret string + AllowedOrgs []string + Open bool + PrivateMode bool + SkipVerify bool + + cache *lru.Cache +} + +func init() { + remote.Register("gitlab", NewDriver) +} + +func NewDriver(conf *config.Config) (remote.Remote, error) { + var gitlab = Gitlab{ + URL: conf.Gitlab.URL, + Client: conf.Gitlab.Client, + Secret: conf.Gitlab.Secret, + AllowedOrgs: conf.Gitlab.Orgs, + Open: conf.Gitlab.Open, + SkipVerify: conf.Gitlab.SkipVerify, + } + var err error + gitlab.cache, err = lru.New(1028) + if err != nil { + return nil, err + } + + // the URL must NOT have a trailing slash + if strings.HasSuffix(gitlab.URL, "/") { + gitlab.URL = gitlab.URL[:len(gitlab.URL)-1] + } + return &gitlab, nil +} + +func (r *Gitlab) Login(token, secret string) (*common.User, error) { + client := NewClient(r.URL, token, r.SkipVerify) + var login, err = client.CurrentUser() + if err != nil { + return nil, err + } + user := common.User{} + user.Login = login.Username + user.Email = login.Email + user.Token = token + user.Secret = secret + return &user, nil +} + +// Orgs fetches the organizations for the given user. +func (r *Gitlab) Orgs(u *common.User) ([]string, error) { + return nil, nil +} + +// Repo fetches the named repository from the remote system. +func (r *Gitlab) Repo(u *common.User, owner, name string) (*common.Repo, error) { + client := NewClient(r.URL, u.Token, r.SkipVerify) + id := ns(owner, name) + repo_, err := client.Project(id) + if err != nil { + return nil, err + } + + repo := &common.Repo{} + repo.Owner = owner + repo.Name = name + repo.FullName = repo_.PathWithNamespace + repo.Link = repo_.Url + repo.Clone = repo_.HttpRepoUrl + repo.Branch = "master" + + if repo_.DefaultBranch != "" { + repo.Branch = repo_.DefaultBranch + } + + if r.PrivateMode { + repo.Private = true + } + return repo, err +} + +// Perm fetches the named repository from the remote system. +func (r *Gitlab) Perm(u *common.User, owner, name string) (*common.Perm, error) { + key := fmt.Sprintf("%s/%s/%s", u.Login, owner, name) + val, ok := r.cache.Get(key) + if ok { + return val.(*common.Perm), nil + } + + client := NewClient(r.URL, u.Token, r.SkipVerify) + id := ns(owner, name) + repo, err := client.Project(id) + if err != nil { + return nil, err + } + m := &common.Perm{} + m.Admin = IsAdmin(repo) + m.Pull = IsRead(repo) + m.Push = IsWrite(repo) + r.cache.Add(key, m) + return m, nil +} + +// GetScript fetches the build script (.drone.yml) from the remote +// repository and returns in string format. +func (r *Gitlab) Script(user *common.User, repo *common.Repo, build *common.Build) ([]byte, error) { + var client = NewClient(r.URL, user.Token, r.SkipVerify) + var path = ns(repo.Owner, repo.Name) + return client.RepoRawFile(path, build.Commit.Sha, ".drone.yml") +} + +func (r *Gitlab) Status(u *common.User, repo *common.Repo, b *common.Build) error { + // how can I get Gitlab status + return nil +} + +// Netrc returns a .netrc file that can be used to clone +// private repositories from a remote system. +func (r *Gitlab) Netrc(u *common.User) (*common.Netrc, error) { + url_, err := url.Parse(r.URL) + if err != nil { + return nil, err + } + netrc := &common.Netrc{} + netrc.Login = u.Token + netrc.Password = "x-oauth-basic" + netrc.Machine = url_.Host + return netrc, nil +} + +// Activate activates a repository by adding a Post-commit hook and +// a Public Deploy key, if applicable. +func (r *Gitlab) Activate(user *common.User, repo *common.Repo, keys *common.Keypair, link string) error { + var client = NewClient(r.URL, user.Token, r.SkipVerify) + var path = ns(repo.Owner, repo.Name) + var title, err = GetKeyTitle(link) + if err != nil { + return err + } + + // if the repository is private we'll need + // to upload a github key to the repository + if repo.Private { + var err = client.AddProjectDeployKey(path, title, repo.Keys.Public) + if err != nil { + return err + } + } + + // append the repo owner / name to the hook url since gitlab + // doesn't send this detail in the post-commit hook + link += "?owner=" + repo.Owner + "&name=" + repo.Name + + // add the hook + return client.AddProjectHook(path, link, true, false, true) +} + +// Deactivate removes a repository by removing all the post-commit hooks +// which are equal to link and removing the SSH deploy key. +func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) error { + var client = NewClient(r.URL, user.Token, r.SkipVerify) + var path = ns(repo.Owner, repo.Name) + + keys, err := client.ProjectDeployKeys(path) + if err != nil { + return err + } + var pubkey = strings.TrimSpace(repo.Keys.Public) + for _, k := range keys { + if pubkey == strings.TrimSpace(k.Key) { + if err := client.RemoveProjectDeployKey(path, strconv.Itoa(k.Id)); err != nil { + return err + } + break + } + } + hooks, err := client.ProjectHooks(path) + if err != nil { + return err + } + link += "?owner=" + repo.Owner + "&name=" + repo.Name + for _, h := range hooks { + if link == h.Url { + if err := client.RemoveProjectHook(path, strconv.Itoa(h.Id)); err != nil { + return err + } + break + } + } + return nil +} + +// ParseHook parses the post-commit hook from the Request body +// and returns the required data in a standard format. +func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { + + defer req.Body.Close() + var payload, _ = ioutil.ReadAll(req.Body) + var parsed, err = gogitlab.ParseHook(payload) + if err != nil { + return nil, err + } + + if len(parsed.After) == 0 || parsed.TotalCommitsCount == 0 { + return nil, nil + } + + if parsed.ObjectKind == "merge_request" { + // TODO (bradrydzewski) figure out how to handle merge requests + return nil, nil + } + + if len(parsed.After) == 0 { + return nil, nil + } + + var hook = new(common.Hook) + hook.Repo.Owner = req.FormValue("owner") + hook.Repo.Name = req.FormValue("name") + hook.Commit.Sha = parsed.After + hook.Commit.Branch = parsed.Branch() + + var head = parsed.Head() + hook.Commit.Message = head.Message + hook.Commit.Timestamp = head.Timestamp + + // extracts the commit author (ideally email) + // from the post-commit hook + switch { + case head.Author != nil: + hook.Commit.Author.Login = head.Author.Email + case head.Author == nil: + hook.Commit.Author.Login = parsed.UserName + } + + return hook, nil +} + +// ¯\_(ツ)_/¯ +func (g *Gitlab) Oauth2Transport(r *http.Request) *oauth2.Transport { + return &oauth2.Transport{ + Config: &oauth2.Config{ + ClientId: g.Client, + ClientSecret: g.Secret, + Scope: DefaultScope, + AuthURL: fmt.Sprintf("%s/oauth/authorize", g.URL), + TokenURL: fmt.Sprintf("%s/oauth/access_token", g.URL), + RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(r)), + //settings.Server.Scheme, settings.Server.Hostname), + }, + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: &tls.Config{InsecureSkipVerify: g.SkipVerify}, + }, + } +} + +// Accessor method, to allowed remote organizations field. +func (r *Gitlab) GetOrgs() []string { + return r.AllowedOrgs +} + +// Accessor method, to open field. +func (r *Gitlab) GetOpen() bool { + return r.Open +} + +// return default scope for GitHub +func (r *Gitlab) Scope() string { + return DefaultScope +} + +// getStatus is a helper functin that converts a Drone +// status to a GitHub status. +func getStatus(status string) string { + switch status { + case common.StatePending, common.StateRunning: + return StatusPending + case common.StateSuccess: + return StatusSuccess + case common.StateFailure: + return StatusFailure + case common.StateError, common.StateKilled: + return StatusError + default: + return StatusError + } +} + +func New(conf *config.Config) *Gitlab { + var gitlab = Gitlab{ + URL: conf.Gitlab.URL, + Client: conf.Gitlab.Client, + Secret: conf.Gitlab.Secret, + SkipVerify: conf.Gitlab.SkipVerify, + AllowedOrgs: conf.Gitlab.Orgs, + Open: conf.Gitlab.Open, + } + var err error + gitlab.cache, err = lru.New(1028) + if err != nil { + panic(err) + } + + // the URL must NOT have a trailing slash + if strings.HasSuffix(gitlab.URL, "/") { + gitlab.URL = gitlab.URL[:len(gitlab.URL)-1] + } + return &gitlab +} + +// GetHost returns the hostname of this remote GitHub instance. +func (r *Gitlab) GetHost() string { + uri, _ := url.Parse(r.URL) + return uri.Host +} + +// getDesc is a helper function that generates a description +// message for the build based on the status. +func getDesc(status string) string { + switch status { + case common.StatePending, common.StateRunning: + return DescPending + case common.StateSuccess: + return DescSuccess + case common.StateFailure: + return DescFailure + case common.StateError, common.StateKilled: + return DescError + default: + return DescError + } +} diff --git a/pkg/remote/gitlab/helper.go b/pkg/remote/gitlab/helper.go new file mode 100644 index 00000000..4d3fc1b8 --- /dev/null +++ b/pkg/remote/gitlab/helper.go @@ -0,0 +1,92 @@ +package gitlab + +import ( + "encoding/base32" + "fmt" + "net/url" + + "github.com/Bugagazavr/go-gitlab-client" + "github.com/gorilla/securecookie" +) + +// NewClient is a helper function that returns a new GitHub +// client using the provided OAuth token. +func NewClient(url, accessToken string, skipVerify bool) *gogitlab.Gitlab { + client := gogitlab.NewGitlabCert(url, "/api/v3", accessToken, skipVerify) + client.Bearer = true + return client +} + +// IsRead is a helper function that returns true if the +// user has Read-only access to the repository. +func IsRead(proj *gogitlab.Project) bool { + var user = proj.Permissions.ProjectAccess + var group = proj.Permissions.GroupAccess + + switch { + case proj.Public: + return true + case user != nil && user.AccessLevel >= 20: + return true + case group != nil && group.AccessLevel >= 20: + return true + default: + return false + } +} + +// IsWrite is a helper function that returns true if the +// user has Read-Write access to the repository. +func IsWrite(proj *gogitlab.Project) bool { + var user = proj.Permissions.ProjectAccess + var group = proj.Permissions.GroupAccess + + switch { + case user != nil && user.AccessLevel >= 30: + return true + case group != nil && group.AccessLevel >= 30: + return true + default: + return false + } +} + +// IsAdmin is a helper function that returns true if the +// user has Admin access to the repository. +func IsAdmin(proj *gogitlab.Project) bool { + var user = proj.Permissions.ProjectAccess + var group = proj.Permissions.GroupAccess + + switch { + case user != nil && user.AccessLevel >= 40: + return true + case group != nil && group.AccessLevel >= 40: + return true + default: + return false + } +} + +// GetKeyTitle is a helper function that generates a title for the +// RSA public key based on the username and domain name. +func GetKeyTitle(rawurl string) (string, error) { + var uri, err = url.Parse(rawurl) + if err != nil { + return "", err + } + return fmt.Sprintf("drone@%s", uri.Host), nil +} + +func ns(owner, name string) string { + return fmt.Sprintf("%s%%2F%s", owner, name) +} + +func GetUserEmail(client *gogitlab.Gitlab, defaultURL string) (*gogitlab.Gitlab, error) { + return client, nil +} + +// GetRandom is a helper function that generates a 32-bit random +// key, base32 encoded as a string value. +func GetRandom() string { + return base32.StdEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) +} From 7baf72156194a465c19ac674d9995f6a64d6f044 Mon Sep 17 00:00:00 2001 From: letusfly85 Date: Sun, 26 Jul 2015 06:06:06 +0900 Subject: [PATCH 2/5] remove unnecessary functions --- pkg/remote/gitlab/gitlab.go | 153 +++++++++--------------------------- pkg/remote/gitlab/helper.go | 8 -- 2 files changed, 37 insertions(+), 124 deletions(-) diff --git a/pkg/remote/gitlab/gitlab.go b/pkg/remote/gitlab/gitlab.go index 499c9a79..eb566e24 100644 --- a/pkg/remote/gitlab/gitlab.go +++ b/pkg/remote/gitlab/gitlab.go @@ -5,7 +5,6 @@ import ( "fmt" "io/ioutil" "net/http" - "net/url" "strconv" "strings" @@ -22,20 +21,6 @@ const ( DefaultScope = "repo" ) -const ( - StatusPending = "pending" - StatusSuccess = "success" - StatusFailure = "failure" - StatusError = "error" -) - -const ( - DescPending = "this build is pending" - DescSuccess = "the build was successful" - DescFailure = "the build failed" - DescError = "oops, something went wrong" -) - type Gitlab struct { URL string Client string @@ -150,23 +135,18 @@ func (r *Gitlab) Script(user *common.User, repo *common.Repo, build *common.Buil return client.RepoRawFile(path, build.Commit.Sha, ".drone.yml") } +// NOTE Currently gitlab doesn't support status for commits and events, +// also if we want get MR status in gitlab we need implement a special plugin for gitlab, +// gitlab uses API to fetch build status on client side. But for now we skip this. func (r *Gitlab) Status(u *common.User, repo *common.Repo, b *common.Build) error { - // how can I get Gitlab status return nil } // Netrc returns a .netrc file that can be used to clone // private repositories from a remote system. +// NOTE gitlab does not support this, so now we skip this. func (r *Gitlab) Netrc(u *common.User) (*common.Netrc, error) { - url_, err := url.Parse(r.URL) - if err != nil { - return nil, err - } - netrc := &common.Netrc{} - netrc.Login = u.Token - netrc.Password = "x-oauth-basic" - netrc.Machine = url_.Host - return netrc, nil + return nil, nil } // Activate activates a repository by adding a Post-commit hook and @@ -235,45 +215,48 @@ func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) e // and returns the required data in a standard format. func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { - defer req.Body.Close() var payload, _ = ioutil.ReadAll(req.Body) - var parsed, err = gogitlab.ParseHook(payload) - if err != nil { - return nil, err - } + var parsed, _ = gogitlab.ParseHook(payload) + obj := parsed.ObjectAttributes - if len(parsed.After) == 0 || parsed.TotalCommitsCount == 0 { - return nil, nil - } - - if parsed.ObjectKind == "merge_request" { - // TODO (bradrydzewski) figure out how to handle merge requests - return nil, nil - } - - if len(parsed.After) == 0 { + if !(obj.State == "opened" && obj.MergeStatus == "unchecked") { return nil, nil } var hook = new(common.Hook) - hook.Repo.Owner = req.FormValue("owner") - hook.Repo.Name = req.FormValue("name") - hook.Commit.Sha = parsed.After - hook.Commit.Branch = parsed.Branch() - var head = parsed.Head() - hook.Commit.Message = head.Message - hook.Commit.Timestamp = head.Timestamp + hook.Repo.Name = obj.Source.Name + hook.Repo.Owner = obj.Source.Namespace - // extracts the commit author (ideally email) - // from the post-commit hook - switch { - case head.Author != nil: - hook.Commit.Author.Login = head.Author.Email - case head.Author == nil: - hook.Commit.Author.Login = parsed.UserName + // Check pull request comes from public fork + if obj.Source.VisibilityLevel < 20 { + //hook.SourceRemote = obj.Source.SshUrl + // If pull request source repo is not a public + // check for non-internal pull request + if obj.Source.Name != obj.Target.Name || obj.Source.Namespace != obj.Target.Namespace { + return nil, nil + } + } else { + //hook.SourceRemote = obj.Source.HttpUrl } + hook.Commit.Author.Login = req.FormValue("owner") + //hook.Repo = req.FormValue("name") + hook.Commit.Sha = obj.LastCommit.Id + hook.Commit.Branch = obj.TargetBranch + //hook.Commit.SourceBranch = obj.SourceBranch + hook.Commit.Timestamp = obj.LastCommit.Timestamp + hook.Commit.Message = obj.Title + + if obj.LastCommit.Author == nil { + // Waiting for merge https://github.com/gitlabhq/gitlabhq/pull/7967 + hook.Commit.Author.Email = "" + } else { + hook.Commit.Author.Email = obj.LastCommit.Author.Email + } + + hook.PullRequest.Number = obj.IId + return hook, nil } @@ -310,65 +293,3 @@ func (r *Gitlab) GetOpen() bool { func (r *Gitlab) Scope() string { return DefaultScope } - -// getStatus is a helper functin that converts a Drone -// status to a GitHub status. -func getStatus(status string) string { - switch status { - case common.StatePending, common.StateRunning: - return StatusPending - case common.StateSuccess: - return StatusSuccess - case common.StateFailure: - return StatusFailure - case common.StateError, common.StateKilled: - return StatusError - default: - return StatusError - } -} - -func New(conf *config.Config) *Gitlab { - var gitlab = Gitlab{ - URL: conf.Gitlab.URL, - Client: conf.Gitlab.Client, - Secret: conf.Gitlab.Secret, - SkipVerify: conf.Gitlab.SkipVerify, - AllowedOrgs: conf.Gitlab.Orgs, - Open: conf.Gitlab.Open, - } - var err error - gitlab.cache, err = lru.New(1028) - if err != nil { - panic(err) - } - - // the URL must NOT have a trailing slash - if strings.HasSuffix(gitlab.URL, "/") { - gitlab.URL = gitlab.URL[:len(gitlab.URL)-1] - } - return &gitlab -} - -// GetHost returns the hostname of this remote GitHub instance. -func (r *Gitlab) GetHost() string { - uri, _ := url.Parse(r.URL) - return uri.Host -} - -// getDesc is a helper function that generates a description -// message for the build based on the status. -func getDesc(status string) string { - switch status { - case common.StatePending, common.StateRunning: - return DescPending - case common.StateSuccess: - return DescSuccess - case common.StateFailure: - return DescFailure - case common.StateError, common.StateKilled: - return DescError - default: - return DescError - } -} diff --git a/pkg/remote/gitlab/helper.go b/pkg/remote/gitlab/helper.go index 4d3fc1b8..39339196 100644 --- a/pkg/remote/gitlab/helper.go +++ b/pkg/remote/gitlab/helper.go @@ -1,12 +1,10 @@ package gitlab import ( - "encoding/base32" "fmt" "net/url" "github.com/Bugagazavr/go-gitlab-client" - "github.com/gorilla/securecookie" ) // NewClient is a helper function that returns a new GitHub @@ -84,9 +82,3 @@ func ns(owner, name string) string { func GetUserEmail(client *gogitlab.Gitlab, defaultURL string) (*gogitlab.Gitlab, error) { return client, nil } - -// GetRandom is a helper function that generates a 32-bit random -// key, base32 encoded as a string value. -func GetRandom() string { - return base32.StdEncoding.EncodeToString(securecookie.GenerateRandomKey(32)) -} From b516cb57827112d9c1415f963e52d8ff48777bbe Mon Sep 17 00:00:00 2001 From: letusfly85 Date: Sun, 26 Jul 2015 07:52:57 +0900 Subject: [PATCH 3/5] add note for hook function --- pkg/remote/gitlab/gitlab.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/remote/gitlab/gitlab.go b/pkg/remote/gitlab/gitlab.go index eb566e24..087f3193 100644 --- a/pkg/remote/gitlab/gitlab.go +++ b/pkg/remote/gitlab/gitlab.go @@ -213,6 +213,8 @@ func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) e // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. +// NOTE: in gitlab 8.0, gitlab will get same MR models as github +// https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/981/diffs func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { var payload, _ = ioutil.ReadAll(req.Body) From dc1ee4a5f94e82c83133ae5192751d92a399b24b Mon Sep 17 00:00:00 2001 From: letusfly85 Date: Sun, 26 Jul 2015 08:02:33 +0900 Subject: [PATCH 4/5] return nil when pull request comes from gitlab and add note --- pkg/remote/gitlab/gitlab.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/remote/gitlab/gitlab.go b/pkg/remote/gitlab/gitlab.go index 087f3193..b1d51b4d 100644 --- a/pkg/remote/gitlab/gitlab.go +++ b/pkg/remote/gitlab/gitlab.go @@ -213,14 +213,18 @@ func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) e // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. -// NOTE: in gitlab 8.0, gitlab will get same MR models as github -// https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/981/diffs func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { var payload, _ = ioutil.ReadAll(req.Body) var parsed, _ = gogitlab.ParseHook(payload) - obj := parsed.ObjectAttributes + if parsed.ObjectKind == "merge_request" { + // NOTE: in gitlab 8.0, gitlab will get same MR models as github + // https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/981/diffs + return nil, nil + } + + obj := parsed.ObjectAttributes if !(obj.State == "opened" && obj.MergeStatus == "unchecked") { return nil, nil } @@ -238,15 +242,11 @@ func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { if obj.Source.Name != obj.Target.Name || obj.Source.Namespace != obj.Target.Namespace { return nil, nil } - } else { - //hook.SourceRemote = obj.Source.HttpUrl } hook.Commit.Author.Login = req.FormValue("owner") - //hook.Repo = req.FormValue("name") hook.Commit.Sha = obj.LastCommit.Id hook.Commit.Branch = obj.TargetBranch - //hook.Commit.SourceBranch = obj.SourceBranch hook.Commit.Timestamp = obj.LastCommit.Timestamp hook.Commit.Message = obj.Title From a3d227fb1220ea6daf1c177c4e6a82741ce477cf Mon Sep 17 00:00:00 2001 From: letusfly85 Date: Sun, 26 Jul 2015 08:22:16 +0900 Subject: [PATCH 5/5] remove merge request scope --- pkg/remote/gitlab/gitlab.go | 53 +++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/pkg/remote/gitlab/gitlab.go b/pkg/remote/gitlab/gitlab.go index b1d51b4d..8ee9363a 100644 --- a/pkg/remote/gitlab/gitlab.go +++ b/pkg/remote/gitlab/gitlab.go @@ -214,9 +214,16 @@ func (r *Gitlab) Deactivate(user *common.User, repo *common.Repo, link string) e // ParseHook parses the post-commit hook from the Request body // and returns the required data in a standard format. func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { - + defer req.Body.Close() var payload, _ = ioutil.ReadAll(req.Body) - var parsed, _ = gogitlab.ParseHook(payload) + var parsed, err = gogitlab.ParseHook(payload) + if err != nil { + return nil, err + } + + if len(parsed.After) == 0 || parsed.TotalCommitsCount == 0 { + return nil, nil + } if parsed.ObjectKind == "merge_request" { // NOTE: in gitlab 8.0, gitlab will get same MR models as github @@ -224,41 +231,29 @@ func (r *Gitlab) Hook(req *http.Request) (*common.Hook, error) { return nil, nil } - obj := parsed.ObjectAttributes - if !(obj.State == "opened" && obj.MergeStatus == "unchecked") { + if len(parsed.After) == 0 { return nil, nil } var hook = new(common.Hook) + hook.Repo.Owner = req.FormValue("owner") + hook.Repo.Name = req.FormValue("name") + hook.Commit.Sha = parsed.After + hook.Commit.Branch = parsed.Branch() - hook.Repo.Name = obj.Source.Name - hook.Repo.Owner = obj.Source.Namespace + var head = parsed.Head() + hook.Commit.Message = head.Message + hook.Commit.Timestamp = head.Timestamp - // Check pull request comes from public fork - if obj.Source.VisibilityLevel < 20 { - //hook.SourceRemote = obj.Source.SshUrl - // If pull request source repo is not a public - // check for non-internal pull request - if obj.Source.Name != obj.Target.Name || obj.Source.Namespace != obj.Target.Namespace { - return nil, nil - } + // extracts the commit author (ideally email) + // from the post-commit hook + switch { + case head.Author != nil: + hook.Commit.Author.Email = head.Author.Email + case head.Author == nil: + hook.Commit.Author.Login = parsed.UserName } - hook.Commit.Author.Login = req.FormValue("owner") - hook.Commit.Sha = obj.LastCommit.Id - hook.Commit.Branch = obj.TargetBranch - hook.Commit.Timestamp = obj.LastCommit.Timestamp - hook.Commit.Message = obj.Title - - if obj.LastCommit.Author == nil { - // Waiting for merge https://github.com/gitlabhq/gitlabhq/pull/7967 - hook.Commit.Author.Email = "" - } else { - hook.Commit.Author.Email = obj.LastCommit.Author.Email - } - - hook.PullRequest.Number = obj.IId - return hook, nil }