Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getting Merged Pull Requests function #1

Merged
merged 5 commits into from
Nov 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: lint tests mockgen
.PHONY: lint tests generate

lint:
golint -set_exit_status ./...
Expand Down
97 changes: 84 additions & 13 deletions github.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import (
"fmt"
"net/http"
"text/template"
"time"

"github.com/google/go-github/v28/github"
"golang.org/x/oauth2"
)

const (
baseBranch = "master"
listPerPage = 10
releaseTemplate = `
## Changelog
- test (#10) by @p1ass
Expand All @@ -27,16 +29,22 @@ var (

//go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAGE

// GitHubClient is a interface for calling GitHub API
type GitHubClient interface {
// GitHubRepositoriesClient is a interface for calling GitHub API about repositories
type GitHubRepositoriesClient interface {
CreateRelease(ctx context.Context, owner, repo string, release *github.RepositoryRelease) (*github.RepositoryRelease, *github.Response, error)
GetLatestRelease(ctx context.Context, owner, repo string) (*github.RepositoryRelease, *github.Response, error)
}

// GitHubService calls GitHub API through GitHubClient
// GitHubPullRequestsClient is a interface for calling GitHub API about pull requests
type GitHubPullRequestsClient interface {
List(ctx context.Context, owner string, repo string, opt *github.PullRequestListOptions) ([]*github.PullRequest, *github.Response, error)
}

// GitHubService handles application logic using GitHub API
type GitHubService struct {
owner string
cli GitHubClient
owner string
repoCli GitHubRepositoriesClient
prCli GitHubPullRequestsClient
}

// NewGitHubService returns a pointer of GitHubService
Expand All @@ -49,13 +57,14 @@ func NewGitHubService(owner, accessToken string) *GitHubService {
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)

return newGitHubService(owner, client.Repositories)
return newGitHubService(owner, client.Repositories, client.PullRequests)
}

func newGitHubService(owner string, githubCli GitHubClient) *GitHubService {
func newGitHubService(owner string, githubCli GitHubRepositoriesClient, prCli GitHubPullRequestsClient) *GitHubService {
return &GitHubService{
owner: owner,
cli: githubCli,
owner: owner,
repoCli: githubCli,
prCli: prCli,
}
}

Expand All @@ -67,7 +76,7 @@ func (s *GitHubService) CreateReleaseByTagName(repo, tagName string) (*github.Re
}

ctx := context.Background()
release, _, err := s.cli.CreateRelease(ctx, s.owner, repo, &github.RepositoryRelease{
release, _, err := s.repoCli.CreateRelease(ctx, s.owner, repo, &github.RepositoryRelease{
TagName: github.String(tagName),
Name: github.String(tagName),
Body: github.String(body),
Expand All @@ -92,10 +101,10 @@ func generateReleaseBody() (string, error) {
return buff.String(), nil
}

// GetLatestRelease gets the latest release
func (s *GitHubService) GetLatestRelease(repo string) (*github.RepositoryRelease, error) {
// getLatestRelease gets the latest release
func (s *GitHubService) getLatestRelease(repo string) (*github.RepositoryRelease, error) {
ctx := context.Background()
release, resp, err := s.cli.GetLatestRelease(ctx, s.owner, repo)
release, resp, err := s.repoCli.GetLatestRelease(ctx, s.owner, repo)
if err != nil {
if resp != nil && resp.StatusCode == http.StatusNotFound {
return nil, fmt.Errorf("%s: %w", repo, ErrReleaseNotFound)
Expand All @@ -104,3 +113,65 @@ func (s *GitHubService) GetLatestRelease(repo string) (*github.RepositoryRelease
}
return release, nil
}

// GetMergedPRsAfterLatestRelease gets pull requests which are merged after the latest release
func (s *GitHubService) GetMergedPRsAfterLatestRelease(repo string) ([]*github.PullRequest, error) {
release, err := s.getLatestRelease(repo)
if err != nil {
return nil, fmt.Errorf("get latest release: %w", err)
}
prs, err := s.getMergedPRsAfter(repo, release.CreatedAt.Time)
if err != nil {
return nil, fmt.Errorf("get pull requests: %w", err)
}
return prs, nil
}

func (s *GitHubService) getMergedPRsAfter(repo string, after time.Time) ([]*github.PullRequest, error) {
opt := &github.PullRequestListOptions{
State: "closed",
Base: baseBranch,
Sort: "updated",
Direction: "desc",
ListOptions: github.ListOptions{PerPage: listPerPage},
}

var prList []*github.PullRequest
for {
ctx := context.Background()
prs, resp, err := s.prCli.List(ctx, s.owner, repo, opt)
if err != nil {
return nil, fmt.Errorf("call listing pull requests API: %w", err)
}

extractedPR, done := extractMergedPRsAfter(prs, after)
prList = append(prList, extractedPR...)
if done {
break
}

if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}

return prList, nil
}

// extractMergedPRsAfter extract merged PRs after a given time
// Return PRs and boolean whether we got all PRs we want
func extractMergedPRsAfter(prs []*github.PullRequest, after time.Time) ([]*github.PullRequest, bool) {
var prList []*github.PullRequest
done := false
for _, pr := range prs {
if pr.MergedAt != nil && pr.MergedAt.After(after) {
prList = append(prList, pr)
}
if pr.UpdatedAt != nil && !pr.UpdatedAt.After(after) {
done = true
break
}
}
return prList, done
}
Loading