Skip to content

Commit

Permalink
Merge pull request #1 from p1ass/add-getting-merged-pr
Browse files Browse the repository at this point in the history
Add getting Merged Pull Requests function
  • Loading branch information
p1ass authored Nov 11, 2019
2 parents e9d0b46 + 27075e0 commit ef2974c
Show file tree
Hide file tree
Showing 4 changed files with 537 additions and 46 deletions.
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

0 comments on commit ef2974c

Please sign in to comment.