Changelog Overhaul 2 #19

Merged
zeripath merged 25 commits from jolheiser/changelog:gitea-sdk into master 2020-01-24 16:30:19 +00:00
8 changed files with 159 additions and 161 deletions
Showing only changes of commit 039e0fac27 - Show all commits

View File

@ -1,11 +0,0 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package cmd
var (
// CLI Flags
Milestone string
ConfigPath string
)

View File

@ -21,7 +21,7 @@ var Contributors = &cli.Command{
}
func runContributors(cmd *cli.Context) error {
if err := config.Load(ConfigPath); err != nil {
if err := config.Load(); err != nil {
return err
}
@ -30,7 +30,7 @@ func runContributors(cmd *cli.Context) error {
return err
}
contributors, err := s.Contributors(Milestone)
contributors, err := s.Contributors()
if err != nil {
return err
}

View File

@ -21,28 +21,65 @@ var Generate = &cli.Command{
}
func runGenerate(cmd *cli.Context) error {
if err := config.Load(ConfigPath); err != nil {
if err := config.Load(); err != nil {
return err
}
labels := make(map[string]string)
entries := make(map[string][]service.PullRequest)
var defaultGroup string
for _, g := range config.Cfg.Groups {
entries[g.Name] = []service.PullRequest{}
for _, l := range g.Labels {
labels[l] = g.Name
}
if g.Default {
defaultGroup = g.Name
}
}
if defaultGroup == "" {
defaultGroup = config.Cfg.Groups[len(config.Cfg.Groups)-1].Name
}
s, err := service.Load()
if err != nil {
return err
}
changelog, err := s.Changelog(Milestone)
title, prs, err := s.Changelog()
if err != nil {
return err
}
fmt.Printf(changelog.TagURL)
PRLoop: // labels in Go, let's get old school
for _, pr := range prs {
var label string
for _, lb := range pr.Labels {
if config.Cfg.SkipRegex != nil && config.Cfg.SkipRegex.MatchString(lb.Name) {
continue PRLoop
}
if g, ok := labels[lb.Name]; ok && len(label) == 0 {
label = g
}
}
if len(label) > 0 {
entries[label] = append(entries[label], pr)
} else {
entries[defaultGroup] = append(entries[defaultGroup], pr)
}
}
fmt.Printf(title)
for _, g := range config.Cfg.Groups {
if len(changelog.Entries[g.Name]) == 0 {
if len(entries[g.Name]) == 0 {
continue
}
fmt.Println("* " + g.Name)
for _, entry := range changelog.Entries[g.Name] {
for _, entry := range entries[g.Name] {
fmt.Printf(" * %s (#%d)\n", entry.Title, entry.Index)
}
}

View File

@ -13,6 +13,7 @@ import (
var (
defaultConfig []byte
ConfigPath string
Cfg *Config
)
@ -34,13 +35,13 @@ type Config struct {
}
// Load a config from a path, defaulting to changelog.example.yml
func Load(configPath string) error {
func Load() error {
var err error
var configContent []byte
if len(configPath) == 0 {
if len(ConfigPath) == 0 {
configContent = defaultConfig
} else {
configContent, err = ioutil.ReadFile(configPath)
configContent, err = ioutil.ReadFile(ConfigPath)
if err != nil {
return err
}

12
main.go
View File

@ -9,6 +9,8 @@ package main
import (
"code.gitea.io/changelog/cmd"
"code.gitea.io/changelog/config"
"code.gitea.io/changelog/service"
"fmt"
"os"
@ -31,13 +33,19 @@ func main() {
Aliases: []string{"m"},
Usage: "Targeted milestone",
Required: true,
Destination: &cmd.Milestone,
Destination: &service.Milestone,
},
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Specify a config file",
Destination: &cmd.ConfigPath,
Destination: &config.ConfigPath,
},
&cli.StringFlag{
Name: "token",
Aliases: []string{"t"},
Usage: "Access token for private repositories/instances",
Destination: &service.Token,
},
},
Commands: []*cli.Command{

View File

@ -22,11 +22,8 @@ import (
type Gitea struct{}
// Changelog returns a Gitea changelog
func (ge Gitea) Changelog(milestone string) (Changelog, error) {
changelog := Changelog{
// FIXME Update tag location if Gitea ever has a page specifically for tags like GitHub does
TagURL: fmt.Sprintf("## [%s](%s/%s/src/tag/v%s) - %s\n", milestone, config.Cfg.BaseURL, config.Cfg.Repo, milestone, time.Now().Format("2006-01-02")),
}
func (ge Gitea) Changelog() (string, []PullRequest, error) {
tagURL := fmt.Sprintf("## [%s](%s/%s/src/tag/v%s) - %s\n", Milestone, config.Cfg.BaseURL, config.Cfg.Repo, Milestone, time.Now().Format("2006-01-02"))
client := gitea.NewAPIClient(&gitea.Configuration{
BasePath: config.Cfg.BaseURL + "/api/v1",
@ -34,80 +31,53 @@ func (ge Gitea) Changelog(milestone string) (Changelog, error) {
UserAgent: "Gitea-Changelog/1.0.0/go",
})
labels := make(map[string]string)
entries := make(map[string][]Entry)
var defaultGroup string
for _, g := range config.Cfg.Groups {
entries[g.Name] = []Entry{}
for _, l := range g.Labels {
labels[l] = g.Name
}
if g.Default {
defaultGroup = g.Name
}
var ctx context.Context
if len(Token) > 0 {
ctx = context.WithValue(context.Background(), gitea.ContextAccessToken, Token)
} else {
ctx = context.Background()
Review

can you write the reason instead of linking to source code?

can you write the reason instead of linking to source code?
Review

Done.

Done.
}
if defaultGroup == "" {
defaultGroup = config.Cfg.Groups[len(config.Cfg.Groups)-1].Name
}
prs := make([]PullRequest, 0)
repoOwner := strings.Split(config.Cfg.Repo, "/")
repo := repoOwner[0]
owner := repoOwner[1]
owner := repoOwner[0]
repo := repoOwner[1]
milestones, _, err := client.IssueApi.IssueGetMilestonesList(context.Background(), repo, owner, nil)
milestoneID, err := getMilestoneID(client, ctx, owner, repo)
if err != nil {
return changelog, err
}
var milestoneID int64
for _, ms := range milestones {
if ms.Title == milestone {
milestoneID = ms.Id
break
}
return "", nil, err
}
p := 1
perPage := 100
for {
results, _, err := client.RepositoryApi.RepoListPullRequests(context.Background(), repo, owner, &gitea.RepoListPullRequestsOpts{
results, _, err := client.RepositoryApi.RepoListPullRequests(ctx, owner, repo, &gitea.RepoListPullRequestsOpts{
Page: optional.NewInt32(int32(p)),
State: optional.NewString("closed"),
Milestone: optional.NewInt64(milestoneID),
})
p++
if err != nil {
return changelog, err
return "", nil, err
}
p++
PRLoop: // labels in Go, let's get old school
for _, pr := range results {
if !pr.Merged {
continue
}
var label string
for _, lb := range pr.Labels {
if config.Cfg.SkipRegex != nil && config.Cfg.SkipRegex.MatchString(lb.Name) {
continue PRLoop
}
if g, ok := labels[lb.Name]; ok && len(label) == 0 {
label = g
}
}
if len(label) > 0 {
entries[label] = append(entries[label], Entry{
if pr.Merged {
p := PullRequest{
Title: pr.Title,
Index: pr.Number,
})
} else {
entries[defaultGroup] = append(entries[defaultGroup], Entry{
Title: pr.Title,
Index: pr.Number,
})
}
labels := make([]Label, len(pr.Labels))
for idx, lbl := range pr.Labels {
labels[idx] = Label{
Name: lbl.Name,
}
}
p.Labels = labels
prs = append(prs, p)
}
}
@ -116,49 +86,46 @@ func (ge Gitea) Changelog(milestone string) (Changelog, error) {
}
}
changelog.Entries = entries
return changelog, nil
return tagURL, prs, nil
}
// Contributors returns a list of contributors from Gitea
func (ge Gitea) Contributors(milestone string) ([]string, error) {
func (ge Gitea) Contributors() ([]string, error) {
client := gitea.NewAPIClient(&gitea.Configuration{
BasePath: config.Cfg.BaseURL + "/api/v1",
DefaultHeader: make(map[string]string),
UserAgent: "Gitea-Changelog/1.0.0/go",
})
contributorsMap := make(map[string]bool)
repoOwner := strings.Split(config.Cfg.Repo, "/")
repo := repoOwner[0]
owner := repoOwner[1]
milestones, _, err := client.IssueApi.IssueGetMilestonesList(context.Background(), repo, owner, nil)
if err != nil {
return nil, err
var ctx context.Context
if len(Token) > 0 {
ctx = context.WithValue(context.Background(), gitea.ContextAccessToken, Token)
} else {
ctx = context.Background()
}
var milestoneID int64
for _, ms := range milestones {
if ms.Title == milestone {
milestoneID = ms.Id
break
}
contributorsMap := make(map[string]bool)
repoOwner := strings.Split(config.Cfg.Repo, "/")
owner := repoOwner[0]
repo := repoOwner[1]
milestoneID, err := getMilestoneID(client, ctx, owner, repo)
if err != nil {
return nil, err
}
p := 1
perPage := 100
for {
results, _, err := client.RepositoryApi.RepoListPullRequests(context.Background(), repo, owner, &gitea.RepoListPullRequestsOpts{
results, _, err := client.RepositoryApi.RepoListPullRequests(ctx, owner, repo, &gitea.RepoListPullRequestsOpts{
Page: optional.NewInt32(int32(p)),
State: optional.NewString("closed"),
Milestone: optional.NewInt64(milestoneID),
})
p++
if err != nil {
return nil, err
}
p++
for _, pr := range results {
if !pr.Merged {
@ -186,3 +153,20 @@ func (ge Gitea) Contributors(milestone string) ([]string, error) {
func (ge Gitea) BaseURL() string {
return config.Cfg.BaseURL
}
func getMilestoneID(client *gitea.APIClient, ctx context.Context, owner, repo string) (int64, error) {
milestones, _, err := client.IssueApi.IssueGetMilestonesList(ctx, owner, repo, &gitea.IssueGetMilestonesListOpts{
State: optional.NewString("all"),
})
if err != nil {
return 0, err
}
for _, ms := range milestones {
if ms.Title == Milestone {
return ms.Id, nil
}
}
return 0, fmt.Errorf("no milestone found for %s", Milestone)
}

View File

@ -19,32 +19,15 @@ import (
type GitHub struct{}
// Changelog returns a GitHub changelog
func (gh GitHub) Changelog(milestone string) (Changelog, error) {
changelog := Changelog{
TagURL: fmt.Sprintf("## [%s](https://github.com/%s/releases/tag/v%s) - %s\n", milestone, config.Cfg.Repo, milestone, time.Now().Format("2006-01-02")),
}
func (gh GitHub) Changelog() (string, []PullRequest, error) {
tagURL := fmt.Sprintf("## [%s](https://github.com/%s/releases/tag/v%s) - %s\n", Milestone, config.Cfg.Repo, Milestone, time.Now().Format("2006-01-02"))
client := github.NewClient(nil)
ctx := context.Background()
labels := make(map[string]string)
entries := make(map[string][]Entry)
var defaultGroup string
for _, g := range config.Cfg.Groups {
entries[g.Name] = []Entry{}
for _, l := range g.Labels {
labels[l] = g.Name
}
if g.Default {
defaultGroup = g.Name
}
}
prs := make([]PullRequest, 0)
if defaultGroup == "" {
defaultGroup = config.Cfg.Groups[len(config.Cfg.Groups)-1].Name
}
query := fmt.Sprintf(`repo:%s is:merged milestone:"%s"`, config.Cfg.Repo, milestone)
query := fmt.Sprintf(`repo:%s is:merged milestone:"%s"`, config.Cfg.Repo, Milestone)
p := 1
perPage := 100
for {
@ -54,34 +37,27 @@ func (gh GitHub) Changelog(milestone string) (Changelog, error) {
PerPage: perPage,
},
})
p++
if err != nil {
return changelog, err
return "", nil, err
}
p++
PRLoop: // labels in Go, let's get old school
for _, pr := range result.Issues {
var label string
for _, lb := range pr.Labels {
if config.Cfg.SkipRegex != nil && config.Cfg.SkipRegex.MatchString(lb.GetName()) {
continue PRLoop
if pr.IsPullRequest() {
p := PullRequest{
Title: pr.GetTitle(),
Index: int64(pr.GetNumber()),
}
if g, ok := labels[lb.GetName()]; ok && len(label) == 0 {
label = g
labels := make([]Label, len(pr.Labels))
for idx, lbl := range pr.Labels {
labels[idx] = Label{
Name: lbl.GetName(),
}
}
}
p.Labels = labels
if len(label) > 0 {
entries[label] = append(entries[label], Entry{
Title: *pr.Title,
Index: int64(*pr.Number),
})
} else {
entries[defaultGroup] = append(entries[defaultGroup], Entry{
Title: *pr.Title,
Index: int64(*pr.Number),
})
prs = append(prs, p)
}
}
@ -90,18 +66,16 @@ func (gh GitHub) Changelog(milestone string) (Changelog, error) {
}
}
changelog.Entries = entries
return changelog, nil
return tagURL, prs, nil
}
// Contributors returns a list of contributors from GitHub
func (gh GitHub) Contributors(milestone string) ([]string, error) {
func (gh GitHub) Contributors() ([]string, error) {
client := github.NewClient(nil)
ctx := context.Background()
contributorsMap := make(map[string]bool)
query := fmt.Sprintf(`repo:%s is:merged milestone:"%s"`, config.Cfg.Repo, milestone)
query := fmt.Sprintf(`repo:%s is:merged milestone:"%s"`, config.Cfg.Repo, Milestone)
p := 1
perPage := 100
for {
@ -111,13 +85,13 @@ func (gh GitHub) Contributors(milestone string) ([]string, error) {
PerPage: perPage,
},
})
p++
if err != nil {
return nil, err
}
p++
for _, pr := range result.Issues {
contributorsMap[*pr.User.Login] = true
contributorsMap[pr.GetUser().GetLogin()] = true
}
if len(result.Issues) != perPage {

View File

@ -5,12 +5,17 @@
package service
import (
"errors"
"fmt"
"strings"
"code.gitea.io/changelog/config"
)
var (
Milestone string
Token string
)
// Parse returns a service from a string
func Load() (Service, error) {
switch strings.ToLower(config.Cfg.Service) {
@ -19,25 +24,25 @@ func Load() (Service, error) {
case "gitea":
return Gitea{}, nil
default:
return nil, errors.New("unknown service type")
return nil, fmt.Errorf("unknown service type %s", config.Cfg.Service)
}
}
// Service defines how a struct can be a Changelog Service
type Service interface {
Changelog(string) (Changelog, error)
Contributors(string) ([]string, error)
Changelog() (string, []PullRequest, error)
Contributors() ([]string, error)
BaseURL() string
}
// Entry defines a changelog entry (PR title and index)
type Entry struct {
Title string
Index int64
// Label is the minimum information needed for a PR label
type Label struct {
Name string
}
// Changelog defines a full changelog
type Changelog struct {
TagURL string
Entries map[string][]Entry
// PullRequest is the minimum information needed to make a changelog entry
type PullRequest struct {
Title string
Index int64
Labels []Label
}