Updates and priority changes (#62)

Reviewed-on: https://gitea.com/gitea/changelog/pulls/62
Reviewed-by: 6543 <6543@obermui.de>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: John Olheiser <john+gitea@jolheiser.com>
Co-committed-by: John Olheiser <john+gitea@jolheiser.com>
This commit is contained in:
John Olheiser 2022-06-22 09:27:24 +08:00 committed by Lunny Xiao
parent f3ee0e5726
commit 57e620da5b
14 changed files with 169 additions and 266 deletions

View File

@ -13,18 +13,18 @@ trigger:
steps:
- name: build
pull: always
image: golang:1.17
image: golang:1.18
environment:
GOPROXY: https://goproxy.cn,direct
GOPROXY: https://goproxy.io,direct
commands:
- go test -race ./...
- go build
- name: check
pull: always
image: golang:1.17
image: golang:1.18
environment:
GOPROXY: https://goproxy.cn,direct
GOPROXY: https://goproxy.io,direct
commands:
- make lint
@ -70,7 +70,7 @@ steps:
pull: always
image: techknowlogick/xgo:latest
environment:
GOPROXY: https://goproxy.cn,direct
GOPROXY: https://goproxy.io,direct
commands:
- export PATH=$PATH:$GOPATH/bin
- make release

View File

@ -10,12 +10,11 @@ linters:
- gocritic
- gocyclo
- gofmt
- golint
- gosimple
- govet
- maligned
- misspell
- prealloc
- revive
- staticcheck
- structcheck
- typecheck

View File

@ -15,27 +15,23 @@ else
LONG_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
endif
LDFLAGS := $(LDFLAGS) -X "main.Version=$(LONG_VERSION)"
LDFLAGS := $(LDFLAGS) -X "code.gitea.io/changelog/cmd.Version=$(LONG_VERSION)"
.PHONY: build
build: generate
build:
$(GO) build -ldflags '-s -w $(LDFLAGS)'
.PHONY: generate
generate:
$(GO) generate ./...
.PHONY: test
test:
$(GO) test -race -v ./...
.PHONY: lint
lint:
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
export BINARY="golangci-lint"; \
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.37.0; \
fi
golangci-lint run --timeout 5m
$(GO) run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2 run --timeout 5m
.PHONY: fmt
fmt:
go fmt ./...
$(GO) fmt ./...
.PHONY: release
release: release-dirs check-xgo release-windows release-linux release-darwin release-copy release-compress release-check

View File

@ -15,7 +15,7 @@ Download a pre-built binary from our [downloads page](https://dl.gitea.io/change
## Configuration
See the [changelog.example.yml](changelog.example.yml) example file.
See the [changelog.example.yml](config/changelog.example.yml) example file.
## Usage
@ -31,7 +31,6 @@ changelog -m=1.11.0 -c=/path/to/my_config_file contributors
## Building
```
go generate ./...
go build
```

View File

@ -1,44 +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.
//go:build ignore
// +build ignore
package main
import (
"fmt"
"io/ioutil"
"os"
)
const (
exampleFile = "changelog.example.yml"
writeFile = "config/config_default.go"
tmpl = `// 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 config
func init() {
DefaultConfig = []byte(` + "`" + `%s` + "`" + `)
}
`
)
func main() {
bytes, err := ioutil.ReadFile(exampleFile)
if err != nil {
fmt.Printf("Could not read from %s. Are you in the root directory of the project?", exampleFile)
os.Exit(1)
}
data := fmt.Sprintf(tmpl, string(bytes))
if err := ioutil.WriteFile(writeFile, []byte(data), os.ModePerm); err != nil {
fmt.Printf("Could not write to %s.", writeFile)
os.Exit(1)
}
}

View File

@ -1,4 +1,4 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Copyright 2018 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.
@ -7,18 +7,82 @@ package cmd
import (
"os"
"path/filepath"
"github.com/urfave/cli/v2"
)
var (
MilestoneFlag string
TagFlag string
ConfigPathFlag string
TokenFlag string
DetailsFlag bool
AfterFlag int64
IssuesFlag bool
// Version of changelog
Version = "development"
milestoneFlag string
tagFlag string
configPathFlag string
tokenFlag string
detailsFlag bool
afterFlag int64
issuesFlag bool
)
// New returns a new changelog App
func New() *cli.App {
app := &cli.App{
Name: "changelog",
Usage: "Changelog tools for Gitea",
Version: Version,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "milestone",
Aliases: []string{"m"},
Usage: "Targeted milestone",
Destination: &milestoneFlag,
},
&cli.StringFlag{
Name: "tag",
Aliases: []string{"T"},
Usage: "Git tag for milestone url, if not set milestone is used",
Destination: &tagFlag,
},
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Specify a config file",
Value: getDefaultConfigFile(),
Destination: &configPathFlag,
},
&cli.StringFlag{
Name: "token",
Aliases: []string{"t"},
Usage: "Access token for private repositories/instances",
Destination: &tokenFlag,
},
&cli.BoolFlag{
Name: "details",
Aliases: []string{"d"},
Usage: "Generate detail lists instead of long lists",
Destination: &detailsFlag,
},
&cli.Int64Flag{
Name: "after",
Aliases: []string{"a"},
Usage: "Only select PRs after a given index (continuing a previous changelog)",
Destination: &afterFlag,
},
&cli.BoolFlag{
Name: "issues",
Aliases: []string{"i"},
Usage: "Generate changelog from issues (otherwise from pulls)",
Destination: &issuesFlag,
},
},
Commands: []*cli.Command{
Generate,
Contributors,
Init,
},
}
return app
}
func getDefaultConfigFile() string {
pwd, err := os.Getwd()
if err != nil {

View File

@ -20,17 +20,13 @@ var Contributors = &cli.Command{
Action: runContributors,
}
func runContributors(cmd *cli.Context) error {
if ConfigPathFlag == "" {
ConfigPathFlag = getDefaultConfigFile()
}
cfg, err := config.New(ConfigPathFlag)
func runContributors(_ *cli.Context) error {
cfg, err := config.New(configPathFlag)
if err != nil {
return err
}
s, err := service.New(cfg.Service, cfg.Repo, cfg.BaseURL, MilestoneFlag, TagFlag, TokenFlag, IssuesFlag)
s, err := service.New(cfg.Service, cfg.Repo, cfg.BaseURL, milestoneFlag, tagFlag, tokenFlag, issuesFlag)
if err != nil {
return err
}

View File

@ -7,6 +7,7 @@ package cmd
import (
"fmt"
"regexp"
"strings"
"code.gitea.io/changelog/config"
"code.gitea.io/changelog/service"
@ -14,30 +15,19 @@ import (
"github.com/urfave/cli/v2"
)
var (
Generate = &cli.Command{
Name: "generate",
Usage: "Generates a changelog for a special milestone",
Action: runGenerate,
}
labels = make(map[string]string)
entries = make(map[string][]service.Entry)
defaultGroup string
)
var Generate = &cli.Command{
Name: "generate",
Usage: "Generates a changelog for a special milestone",
Action: runGenerate,
}
func runGenerate(cmd *cli.Context) error {
if ConfigPathFlag == "" {
ConfigPathFlag = getDefaultConfigFile()
}
cfg, err := config.New(ConfigPathFlag)
func runGenerate(_ *cli.Context) error {
cfg, err := config.New(configPathFlag)
if err != nil {
return err
}
processGroups(cfg.Groups)
s, err := service.New(cfg.Service, cfg.Repo, cfg.BaseURL, MilestoneFlag, TagFlag, TokenFlag, IssuesFlag)
s, err := service.New(cfg.Service, cfg.Repo, cfg.BaseURL, milestoneFlag, tagFlag, tokenFlag, issuesFlag)
if err != nil {
return err
}
@ -47,7 +37,17 @@ func runGenerate(cmd *cli.Context) error {
return err
}
processPRs(prs, cfg.SkipRegex)
var defaultGroup string
for _, g := range cfg.Groups {
if g.Default {
defaultGroup = g.Name
}
}
if defaultGroup == "" {
defaultGroup = cfg.Groups[len(cfg.Groups)-1].Name
}
entries := processPRs(prs, cfg.NameLabels(), defaultGroup, cfg.SkipRegex)
fmt.Println(title)
fmt.Println()
@ -56,7 +56,7 @@ func runGenerate(cmd *cli.Context) error {
continue
}
if DetailsFlag {
if detailsFlag {
fmt.Println("<details><summary>" + g.Name + "</summary>")
fmt.Println()
for _, entry := range entries[g.Name] {
@ -74,44 +74,32 @@ func runGenerate(cmd *cli.Context) error {
return nil
}
func processGroups(groups []config.Group) {
for _, g := range groups {
entries[g.Name] = []service.Entry{}
for _, l := range g.Labels {
labels[l] = g.Name
}
if g.Default {
defaultGroup = g.Name
}
}
if defaultGroup == "" {
defaultGroup = groups[len(groups)-1].Name
}
}
func processPRs(prs []service.Entry, skip *regexp.Regexp) {
func processPRs(prs []service.Entry, order []config.NameLabel, defaultGroup string, skip *regexp.Regexp) map[string][]service.Entry {
entries := make(map[string][]service.Entry)
PRLoop: // labels in Go, let's get old school
for _, pr := range prs {
if pr.Index < AfterFlag {
if pr.Index < afterFlag {
continue
}
var label string
for _, lb := range pr.Labels {
if skip != nil && skip.MatchString(lb.Name) {
continue PRLoop
}
}
section := processSection(pr, order, defaultGroup)
entries[section] = append(entries[section], pr)
}
return entries
}
if g, ok := labels[lb.Name]; ok && len(label) == 0 {
label = g
func processSection(pr service.Entry, order []config.NameLabel, defaultGroup string) string {
for _, o := range order {
for _, lb := range pr.Labels {
if strings.EqualFold(o.Label, lb.Name) {
return o.Name
}
}
if len(label) > 0 {
entries[label] = append(entries[label], pr)
} else {
entries[defaultGroup] = append(entries[defaultGroup], pr)
}
}
return defaultGroup
}

View File

@ -32,7 +32,7 @@ var (
nameFlag string
)
func runInit(cmd *cli.Context) error {
func runInit(_ *cli.Context) error {
if _, err := os.Stat(nameFlag); err == nil {
return fmt.Errorf("file '%s' already exists", nameFlag)
}

View File

@ -5,12 +5,14 @@
package config
import (
_ "embed"
"io/ioutil"
"regexp"
"gopkg.in/yaml.v2"
)
//go:embed changelog.example.yml
var DefaultConfig []byte
// Group is a grouping of PRs
@ -20,6 +22,24 @@ type Group struct {
Default bool `yaml:"default"`
}
// NameLabel is a Group mapping for a Label to a Name
type NameLabel struct {
Name string
Label string
}
// NameLabels returns a slice of NameLabel
func (g Group) NameLabels() []NameLabel {
nl := make([]NameLabel, 0)
for _, l := range g.Labels {
nl = append(nl, NameLabel{
Name: g.Name,
Label: l,
})
}
return nl
}
// Config is the changelog settings
type Config struct {
Repo string `yaml:"repo"`
@ -30,13 +50,20 @@ type Config struct {
SkipRegex *regexp.Regexp `yaml:"-"`
}
// NameLabels returns a slice of NameLabel for each Group, keeping them in order (priority)
func (c Config) NameLabels() []NameLabel {
nl := make([]NameLabel, 0)
for _, g := range c.Groups {
nl = append(nl, g.NameLabels()...)
}
return nl
}
// New Load a config from a path, defaulting to changelog.example.yml
func New(configPath string) (*Config, error) {
var err error
var configContent []byte
if len(configPath) == 0 {
configContent = DefaultConfig
} else {
configContent := DefaultConfig
if len(configPath) != 0 {
configContent, err = ioutil.ReadFile(configPath)
if err != nil {
return nil, err

View File

@ -1,65 +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 config
func init() {
DefaultConfig = []byte(`# The full repository name
repo: go-gitea/gitea
# Service type (gitea or github)
service: github
# Base URL for Gitea instance if using gitea service type (optional)
# Default: https://gitea.com
base-url:
# Changelog groups and which labeled PRs to add to each group
groups:
-
name: BREAKING
labels:
- kind/breaking
-
name: FEATURES
labels:
- kind/feature
-
name: BUGFIXES
labels:
- kind/bug
-
name: ENHANCEMENTS
labels:
- kind/enhancement
- kind/refactor
- kind/ui
-
name: SECURITY
labels:
- kind/security
-
name: TESTING
labels:
- kind/testing
-
name: TRANSLATION
labels:
- kind/translation
-
name: BUILD
labels:
- kind/build
- kind/lint
-
name: DOCS
labels:
- kind/docs
-
name: MISC
default: true
# regex indicating which labels to skip for the changelog
skip-labels: skip-changelog|backport\/.+`)
}

13
go.mod
View File

@ -1,12 +1,19 @@
module code.gitea.io/changelog
go 1.13
go 1.18
require (
code.gitea.io/sdk/gitea v0.14.0
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/google/go-github/v32 v32.1.0
github.com/urfave/cli/v2 v2.2.0
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect
gopkg.in/yaml.v2 v2.3.0
)
require (
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/hashicorp/go-version v1.2.1 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect
)

66
main.go
View File

@ -4,79 +4,15 @@
package main
//go:generate go run changelog.example.go
//go:generate go fmt ./...
import (
"fmt"
"os"
"code.gitea.io/changelog/cmd"
"github.com/urfave/cli/v2"
)
var (
// Version of changelog
Version = "development"
)
func main() {
app := &cli.App{
Name: "changelog",
Usage: "Changelog tools for Gitea",
Version: Version,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "milestone",
Aliases: []string{"m"},
Usage: "Targeted milestone",
Destination: &cmd.MilestoneFlag,
},
&cli.StringFlag{
Name: "tag",
Aliases: []string{"T"},
Usage: "Git tag for milestone url, if not set milestone is used",
Destination: &cmd.TagFlag,
},
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Specify a config file",
Destination: &cmd.ConfigPathFlag,
},
&cli.StringFlag{
Name: "token",
Aliases: []string{"t"},
Usage: "Access token for private repositories/instances",
Destination: &cmd.TokenFlag,
},
&cli.BoolFlag{
Name: "details",
Aliases: []string{"d"},
Usage: "Generate detail lists instead of long lists",
Destination: &cmd.DetailsFlag,
},
&cli.Int64Flag{
Name: "after",
Aliases: []string{"a"},
Usage: "Only select PRs after a given index (continuing a previous changelog)",
Destination: &cmd.AfterFlag,
},
&cli.BoolFlag{
Name: "issues",
Aliases: []string{"i"},
Usage: "Generate changelog from issues (otherwise from pulls)",
Destination: &cmd.IssuesFlag,
},
},
Commands: []*cli.Command{
cmd.Generate,
cmd.Contributors,
cmd.Init,
},
}
app := cmd.New()
if err := app.Run(os.Args); err != nil {
fmt.Printf("Failed to run app with %s: %v\n", os.Args[1:], err)
}