-
Notifications
You must be signed in to change notification settings - Fork 124
First pr merge semver #27
base: master
Are you sure you want to change the base?
Changes from 15 commits
c3ceee2
1d995f0
f2b46bc
a49a2af
31bb3ca
51190da
5e2214c
249b0d3
19bd637
e6dd925
6b31038
18cc997
0da11a3
f2f12e2
1d407bd
88f076b
ccd9950
34ccb73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,5 @@ bindata.go | |
web/react/node_modules | ||
web/static/files/script.js | ||
#web/static/files/*.css | ||
|
||
.idea |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package model | ||
|
||
type BranchStatus string |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package model | ||
|
||
type StatusHook struct { | ||
SHA string | ||
Repo *Repo | ||
} | ||
|
||
type PullRequest struct { | ||
Issue | ||
Branch Branch | ||
} | ||
|
||
type Branch struct { | ||
Name string | ||
BranchStatus string | ||
Mergeable bool | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rename |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package model | ||
|
||
type Tag string |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,8 @@ import ( | |
"github.com/lgtmco/lgtm/model" | ||
"github.com/lgtmco/lgtm/shared/httputil" | ||
"golang.org/x/oauth2" | ||
"github.com/hashicorp/go-version" | ||
"errors" | ||
) | ||
|
||
// name of the status message posted to GitHub | ||
|
@@ -180,11 +182,6 @@ func (g *Github) GetRepos(u *model.User) ([]*model.Repo, error) { | |
func (g *Github) SetHook(user *model.User, repo *model.Repo, link string) error { | ||
client := setupClient(g.API, user.Token) | ||
|
||
repo_, _, err := client.Repositories.Get(repo.Owner, repo.Name) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
old, err := GetHook(client, repo.Owner, repo.Name, link) | ||
if err == nil && old != nil { | ||
client.Repositories.DeleteHook(repo.Owner, repo.Name, *old.ID) | ||
|
@@ -196,12 +193,24 @@ func (g *Github) SetHook(user *model.User, repo *model.Repo, link string) error | |
return err | ||
} | ||
|
||
repo_, _, err := client.Repositories.Get(repo.Owner, repo.Name) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
in := new(Branch) | ||
in.Protection.Enabled = true | ||
in.Protection.Checks.Enforcement = "non_admins" | ||
in.Protection.Checks.Contexts = []string{context} | ||
|
||
/* | ||
JCB 04/21/16 confirmed with Github support -- must specify all existing contexts when | ||
adding a new one, otherwise the other contexts will be removed. | ||
*/ | ||
client_ := NewClientToken(g.API, user.Token) | ||
branch, _ := client_.Branch(repo.Owner, repo.Name, *repo_.DefaultBranch) | ||
|
||
in.Protection.Checks.Contexts = append(buildOtherContextSlice(branch), context) | ||
|
||
err = client_.BranchProtect(repo.Owner, repo.Name, *repo_.DefaultBranch, in) | ||
if err != nil { | ||
if g.URL == "https://github.com" { | ||
|
@@ -236,14 +245,21 @@ func (g *Github) DelHook(user *model.User, repo *model.Repo, link string) error | |
if len(branch.Protection.Checks.Contexts) == 0 { | ||
return nil | ||
} | ||
|
||
branch.Protection.Checks.Contexts = buildOtherContextSlice(branch) | ||
|
||
return client_.BranchProtect(repo.Owner, repo.Name, *repo_.DefaultBranch, branch) | ||
} | ||
|
||
// buildOtherContextSlice returns all contexts besides the one for LGTM | ||
func buildOtherContextSlice(branch *Branch) []string { | ||
checks := []string{} | ||
for _, check := range branch.Protection.Checks.Contexts { | ||
if check != context { | ||
checks = append(checks, check) | ||
} | ||
} | ||
branch.Protection.Checks.Contexts = checks | ||
return client_.BranchProtect(repo.Owner, repo.Name, *repo_.DefaultBranch, branch) | ||
return checks | ||
} | ||
|
||
func (g *Github) GetComments(u *model.User, r *model.Repo, num int) ([]*model.Comment, error) { | ||
|
@@ -330,3 +346,162 @@ func (g *Github) GetHook(r *http.Request) (*model.Hook, error) { | |
|
||
return hook, nil | ||
} | ||
|
||
func (g *Github) GetStatusHook(r *http.Request) (*model.StatusHook, error) { | ||
|
||
// only process comment hooks | ||
if r.Header.Get("X-Github-Event") != "status" { | ||
return nil, nil | ||
} | ||
|
||
data := statusHook{} | ||
err := json.NewDecoder(r.Body).Decode(&data) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
log.Debug(data) | ||
|
||
if data.State != "success" { | ||
return nil, nil | ||
} | ||
|
||
hook := new(model.StatusHook) | ||
|
||
hook.SHA = data.SHA | ||
|
||
hook.Repo = new(model.Repo) | ||
hook.Repo.Owner = data.Repository.Owner.Login | ||
hook.Repo.Name = data.Repository.Name | ||
hook.Repo.Slug = data.Repository.FullName | ||
|
||
log.Debug(*hook) | ||
|
||
return hook, nil | ||
} | ||
|
||
func (g *Github) GetPullRequestsForCommit(u *model.User, r *model.Repo, sha *string) ([]model.PullRequest, error) { | ||
client := setupClient(g.API, u.Token) | ||
fmt.Println("sha == ", sha, *sha) | ||
issues, _, err := client.Search.Issues(fmt.Sprintf("%s&type=pr", *sha), &github.SearchOptions { | ||
TextMatch: false, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
out := make([]model.PullRequest, len(issues.Issues)) | ||
for k, v := range issues.Issues { | ||
pr, _, err := client.PullRequests.Get(r.Owner, r.Name, *v.Number) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
mergeable:= true | ||
if pr.Mergeable != nil { | ||
mergeable = *pr.Mergeable | ||
} | ||
|
||
status, _, err := client.Repositories.GetCombinedStatus(r.Owner, r.Name, *sha, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
out[k] = model.PullRequest{ | ||
Issue: model.Issue{ | ||
Number: *v.Number, | ||
Title: *v.Title, | ||
Author: *v.User.Login, | ||
}, | ||
Branch: model.Branch { | ||
Name: *pr.Head.Ref, | ||
BranchStatus: *status.State, | ||
Mergeable: mergeable, | ||
|
||
}, | ||
} | ||
} | ||
return out, nil | ||
} | ||
|
||
func (g *Github) GetBranchStatus(u *model.User, r *model.Repo, branch string) (*model.BranchStatus, error) { | ||
client := setupClient(g.API, u.Token) | ||
statuses, _, err := client.Repositories.GetCombinedStatus(r.Owner, r.Name, branch, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return (*model.BranchStatus)(statuses.State), nil | ||
} | ||
|
||
func (g *Github) MergePR(u *model.User, r *model.Repo, pullRequest model.PullRequest) (*string, error) { | ||
client := setupClient(g.API, u.Token) | ||
|
||
result, _, err := client.PullRequests.Merge(r.Owner, r.Name, pullRequest.Number, "Merged by LGTM") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if !(*result.Merged) { | ||
return nil, errors.New(*result.Message) | ||
} | ||
return result.SHA, nil | ||
} | ||
|
||
func (g *Github) GetMaxExistingTag(u *model.User, r *model.Repo) (*version.Version, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm planning on combining the We can then add a helper function to separately get the max. The added benefit here is that if we ever support additional remotes (like gogs, etc) we don't have to duplicate the max logic in each remote. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for the helper function, perhaps follow a pattern similar to this, adding a |
||
client := setupClient(g.API, u.Token) | ||
|
||
//find the previous largest semver value | ||
var maxVer *version.Version | ||
|
||
tags, _, err := client.Repositories.ListTags(r.Owner, r.Name, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
for _, v := range tags { | ||
curVer, err := version.NewVersion(*v.Name) | ||
if err != nil { | ||
continue | ||
} | ||
if maxVer == nil || curVer.GreaterThan(maxVer) { | ||
maxVer = curVer | ||
} | ||
} | ||
|
||
if maxVer == nil { | ||
maxVer, _ = version.NewVersion("v0.0.0") | ||
} | ||
log.Debugf("maxVer found is %s", maxVer.String()) | ||
return maxVer, nil | ||
} | ||
|
||
func (g *Github) Tag(u *model.User, r *model.Repo, version *version.Version, sha *string) error { | ||
client := setupClient(g.API, u.Token) | ||
|
||
t := time.Now() | ||
tag, _, err := client.Git.CreateTag(r.Owner, r.Name, &github.Tag{ | ||
Tag: github.String(version.String()), | ||
SHA: sha, | ||
Message: github.String("Tagged by LGTM"), | ||
Tagger: &github.CommitAuthor{ | ||
Date: &t, | ||
Name: github.String("LGTM"), | ||
Email: github.String("[email protected]"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also maybe make this configurable as part of the github configuration? Not sure if people will care / want to customize or not. Open to suggestions here. If not, we can ignore the idea |
||
}, | ||
Object: &github.GitObject{ | ||
SHA: sha, | ||
Type: github.String("commit"), | ||
}, | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
_, _, err = client.Git.CreateRef(r.Owner, r.Name, &github.Reference{ | ||
Ref: github.String("refs/tags/" + version.String()), | ||
Object: &github.GitObject{ | ||
SHA: tag.SHA, | ||
}, | ||
}) | ||
|
||
return err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is
gofmt
run on the code? I would expect it to remove the spacing after re