Files
atlantis/github_client.go
2017-05-24 17:29:43 -07:00

93 lines
2.9 KiB
Go

package main
import (
"fmt"
"github.com/google/go-github/github"
"context"
)
type GithubClient struct {
client *github.Client
ctx context.Context
}
const (
statusContext = "Atlantis"
PendingStatus = "pending"
SuccessStatus = "success"
ErrorStatus = "error"
FailureStatus = "failure"
)
func (g *GithubClient) UpdateStatus(ctx *PullRequestContext, status string, description string) {
repoStatus := github.RepoStatus{State: github.String(status), Description: github.String(description), Context: github.String(statusContext)}
g.client.Repositories.CreateStatus(g.ctx, ctx.owner, ctx.repoName, ctx.head, &repoStatus)
// todo: deal with error updating status
}
func (g *GithubClient) GetModifiedFiles(ctx *PullRequestContext) ([]string, error) {
var files = []string{}
comparison, _, err := g.client.Repositories.CompareCommits(g.ctx, ctx.owner, ctx.repoName, ctx.base, ctx.head)
if err != nil {
return files, err
}
for _, file := range comparison.Files {
files = append(files, *file.Filename)
}
return files, nil
}
func (g *GithubClient) CreateComment(ctx *PullRequestContext, comment string) error {
_, _, err := g.client.Issues.CreateComment(g.ctx, ctx.owner, ctx.repoName, ctx.number, &github.IssueComment{Body: &comment})
return err
}
// CommentExists searches through comments on a pull request and returns true if one matches matcher
func (g *GithubClient) CommentExists(ctx *PullRequestContext, matcher func(*github.IssueComment) bool) (bool, error) {
opt := &github.IssueListCommentsOptions{}
// need to loop since there may be multiple pages of comments
for {
comments, resp, err := g.client.Issues.ListComments(g.ctx, ctx.owner, ctx.repoName, ctx.number, opt)
if err != nil {
return false, fmt.Errorf("failed to retrieve comments: %v", err)
}
for _, comment := range comments {
if matcher(comment) {
return true, nil
}
}
if resp.NextPage == 0 {
break
}
opt.ListOptions.Page = resp.NextPage
}
return false, nil
}
func (g *GithubClient) PullIsApproved(ctx *PullRequestContext) (bool, error) {
// todo: move back to using g.client.PullRequests.ListReviews when we update our GitHub enterprise version
// to where we don't need to include the custom accept header
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", ctx.owner, ctx.repoName, ctx.number)
req, err := g.client.NewRequest("GET", u, nil)
if err != nil {
return false, err
}
req.Header.Set("Accept", "application/vnd.github.black-cat-preview+json")
var reviews []*github.PullRequestReview
_, err = g.client.Do(g.ctx, req, &reviews)
if err != nil {
return false, fmt.Errorf("failed to retrieve reviews: %v", err)
}
for _, review := range reviews {
if review != nil && review.State != nil && *review.State == "APPROVED" {
return true, nil
}
}
return false, nil
}
func (g *GithubClient) GetPullRequest(owner string, repo string, number int) (*github.PullRequest, *github.Response, error) {
return g.client.PullRequests.Get(g.ctx, owner, repo, number)
}