From 3d93c3a0cdc92eff027f47c19b96efd3092c186d Mon Sep 17 00:00:00 2001 From: jolheiser Date: Thu, 20 Jul 2023 10:08:48 +0000 Subject: [PATCH] Use issue list API instead of search (#78) This PR changes to using the GH issue list API rather than search, as for some reason the search results started missing several PRs... Reviewed-on: https://gitea.com/gitea/changelog/pulls/78 Co-authored-by: jolheiser Co-committed-by: jolheiser --- service/github.go | 76 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/service/github.go b/service/github.go index dd145b2..c079619 100644 --- a/service/github.go +++ b/service/github.go @@ -6,9 +6,12 @@ package service import ( "context" + "errors" "fmt" "net/http" "os" + "strconv" + "strings" "time" "github.com/google/go-github/v50/github" @@ -25,8 +28,18 @@ type GitHub struct { client *github.Client } +// OwnerRepo splits owner/repo +func (gh *GitHub) OwnerRepo() (string, string) { + parts := strings.Split(gh.Repo, "/") + if len(parts) < 2 { + return parts[0], "" + } + return parts[0], parts[1] +} + // Generate returns a GitHub changelog func (gh *GitHub) Generate() (string, []Entry, error) { + owner, repo := gh.OwnerRepo() ctx := context.Background() gh.initClient(ctx) @@ -34,16 +47,17 @@ func (gh *GitHub) Generate() (string, []Entry, error) { prs := make([]Entry, 0) - state := "merged" - if gh.Issues { - state = "closed" + milestoneNum, err := gh.milestoneNum(ctx) + if err != nil { + return "", nil, err } - query := fmt.Sprintf(`repo:%s is:%s milestone:"%s"`, gh.Repo, state, gh.Milestone) p := 1 perPage := 100 for { - result, _, err := gh.client.Search.Issues(ctx, query, &github.SearchOptions{ + result, _, err := gh.client.Issues.ListByRepo(ctx, owner, repo, &github.IssueListByRepoOptions{ + Milestone: strconv.Itoa(milestoneNum), + State: "closed", ListOptions: github.ListOptions{ Page: p, PerPage: perPage, @@ -56,7 +70,7 @@ func (gh *GitHub) Generate() (string, []Entry, error) { isPull := !(gh.Issues) - for _, pr := range result.Issues { + for _, pr := range result { if pr.IsPullRequest() == isPull { p := Entry{ Title: CleanTitle(pr.GetTitle()), @@ -75,7 +89,7 @@ func (gh *GitHub) Generate() (string, []Entry, error) { } } - if len(result.Issues) != perPage { + if len(result) != perPage { break } } @@ -86,14 +100,20 @@ func (gh *GitHub) Generate() (string, []Entry, error) { // Contributors returns a list of contributors from GitHub func (gh *GitHub) Contributors() (ContributorList, error) { ctx := context.Background() + owner, repo := gh.OwnerRepo() gh.initClient(ctx) contributorsMap := make(map[string]bool) - query := fmt.Sprintf(`repo:%s is:merged milestone:"%s"`, gh.Repo, gh.Milestone) + milestoneNum, err := gh.milestoneNum(ctx) + if err != nil { + return nil, err + } p := 1 perPage := 100 for { - result, _, err := gh.client.Search.Issues(ctx, query, &github.SearchOptions{ + result, _, err := gh.client.Issues.ListByRepo(ctx, owner, repo, &github.IssueListByRepoOptions{ + Milestone: strconv.Itoa(milestoneNum), + State: "closed", ListOptions: github.ListOptions{ Page: p, PerPage: perPage, @@ -104,11 +124,11 @@ func (gh *GitHub) Contributors() (ContributorList, error) { } p++ - for _, pr := range result.Issues { + for _, pr := range result { contributorsMap[pr.GetUser().GetLogin()] = true } - if len(result.Issues) != perPage { + if len(result) != perPage { break } } @@ -129,7 +149,6 @@ func (gh *GitHub) initClient(ctx context.Context) { if envToken, ok := os.LookupEnv("CHANGELOG_GITHUB_TOKEN"); ok && token == "" { token = envToken } - cl := http.DefaultClient if token != "" { ts := oauth2.StaticTokenSource( @@ -140,3 +159,36 @@ func (gh *GitHub) initClient(ctx context.Context) { gh.client = github.NewClient(cl) } + +func (gh *GitHub) milestoneNum(ctx context.Context) (int, error) { + owner, repo := gh.OwnerRepo() + p := 1 + perPage := 100 + for { + milestones, _, err := gh.client.Issues.ListMilestones(ctx, owner, repo, &github.MilestoneListOptions{ + State: "all", + ListOptions: github.ListOptions{ + Page: p, + PerPage: perPage, + }, + Sort: "due_on", + Direction: "desc", + }) + if err != nil { + return 0, err + } + p++ + + for _, milestone := range milestones { + if strings.EqualFold(milestone.GetTitle(), gh.Milestone) { + return milestone.GetNumber(), nil + } + } + + if len(milestones) != perPage { + break + } + } + + return 0, errors.New("no milestone found") +}