Merge remote-tracking branch 'origin/main' into fix-51-set-flags-after-subcommand
This commit is contained in:
commit
7f649f6174
30
.drone.yml
30
.drone.yml
|
@ -13,18 +13,18 @@ trigger:
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.13
|
image: golang:1.18
|
||||||
environment:
|
environment:
|
||||||
GOPROXY: https://goproxy.cn,direct
|
GOPROXY: https://goproxy.io,direct
|
||||||
commands:
|
commands:
|
||||||
- go test -race ./...
|
- go test -race ./...
|
||||||
- go build
|
- go build
|
||||||
|
|
||||||
- name: check
|
- name: check
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.13
|
image: golang:1.18
|
||||||
environment:
|
environment:
|
||||||
GOPROXY: https://goproxy.cn,direct
|
GOPROXY: https://goproxy.io,direct
|
||||||
commands:
|
commands:
|
||||||
- make lint
|
- make lint
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ platform:
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- master
|
- main
|
||||||
event:
|
event:
|
||||||
- push
|
- push
|
||||||
- tag
|
- tag
|
||||||
|
@ -70,22 +70,21 @@ steps:
|
||||||
pull: always
|
pull: always
|
||||||
image: techknowlogick/xgo:latest
|
image: techknowlogick/xgo:latest
|
||||||
environment:
|
environment:
|
||||||
GOPROXY: https://goproxy.cn,direct
|
GOPROXY: https://goproxy.io,direct
|
||||||
commands:
|
commands:
|
||||||
- export PATH=$PATH:$GOPATH/bin
|
- export PATH=$PATH:$GOPATH/bin
|
||||||
- make release
|
- make release
|
||||||
|
|
||||||
- name: bucket-master
|
- name: bucket-main
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/s3:1
|
image: woodpeckerci/plugin-s3:latest
|
||||||
settings:
|
settings:
|
||||||
acl: public-read
|
acl: public-read
|
||||||
bucket: releases
|
bucket: gitea-artifacts
|
||||||
endpoint: https://storage.gitea.io
|
endpoint: https://ams3.digitaloceanspaces.com
|
||||||
path_style: true
|
|
||||||
source: "dist/release/*"
|
source: "dist/release/*"
|
||||||
strip_prefix: dist/release/
|
strip_prefix: dist/release/
|
||||||
target: /changelog-tool/master
|
target: /changelog-tool/main
|
||||||
environment:
|
environment:
|
||||||
AWS_ACCESS_KEY_ID:
|
AWS_ACCESS_KEY_ID:
|
||||||
from_secret: aws_access_key_id
|
from_secret: aws_access_key_id
|
||||||
|
@ -97,12 +96,11 @@ steps:
|
||||||
|
|
||||||
- name: bucket-tag
|
- name: bucket-tag
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/s3:1
|
image: woodpeckerci/plugin-s3:latest
|
||||||
settings:
|
settings:
|
||||||
acl: public-read
|
acl: public-read
|
||||||
bucket: releases
|
bucket: gitea-artifacts
|
||||||
endpoint: https://storage.gitea.io
|
endpoint: https://ams3.digitaloceanspaces.com
|
||||||
path_style: true
|
|
||||||
source: "dist/release/*"
|
source: "dist/release/*"
|
||||||
strip_prefix: dist/release/
|
strip_prefix: dist/release/
|
||||||
target: "/changelog-tool/${DRONE_TAG##v}"
|
target: "/changelog-tool/${DRONE_TAG##v}"
|
||||||
|
|
|
@ -10,12 +10,11 @@ linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- gofmt
|
- gofmt
|
||||||
- golint
|
|
||||||
- gosimple
|
- gosimple
|
||||||
- govet
|
- govet
|
||||||
- maligned
|
|
||||||
- misspell
|
- misspell
|
||||||
- prealloc
|
- prealloc
|
||||||
|
- revive
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- structcheck
|
- structcheck
|
||||||
- typecheck
|
- typecheck
|
||||||
|
|
22
Makefile
22
Makefile
|
@ -15,27 +15,23 @@ else
|
||||||
LONG_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
LONG_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.Version=$(LONG_VERSION)"
|
LDFLAGS := $(LDFLAGS) -X "code.gitea.io/changelog/cmd.Version=$(LONG_VERSION)"
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: generate
|
build:
|
||||||
$(GO) build -ldflags '-s -w $(LDFLAGS)'
|
$(GO) build -ldflags '-s -w $(LDFLAGS)'
|
||||||
|
|
||||||
.PHONY: generate
|
.PHONY: test
|
||||||
generate:
|
test:
|
||||||
$(GO) generate ./...
|
$(GO) test -race -v ./...
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
$(GO) run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2 run --timeout 5m
|
||||||
export BINARY="golangci-lint"; \
|
|
||||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.23.1; \
|
|
||||||
fi
|
|
||||||
golangci-lint run --timeout 5m
|
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt:
|
fmt:
|
||||||
go fmt ./...
|
$(GO) fmt ./...
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: release-dirs check-xgo release-windows release-linux release-darwin release-copy release-compress release-check
|
release: release-dirs check-xgo release-windows release-linux release-darwin release-copy release-compress release-check
|
||||||
|
@ -82,6 +78,6 @@ release-check:
|
||||||
.PHONY: release-compress
|
.PHONY: release-compress
|
||||||
release-compress:
|
release-compress:
|
||||||
@hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
@hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||||
$(GO) get -u github.com/ulikunitz/xz/cmd/gxz; \
|
$(GO) install github.com/ulikunitz/xz/cmd/gxz@latest; \
|
||||||
fi
|
fi
|
||||||
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done;
|
cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done;
|
||||||
|
|
|
@ -15,7 +15,7 @@ Download a pre-built binary from our [downloads page](https://dl.gitea.io/change
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
See the [changelog.example.yml](changelog.example.yml) example file.
|
See the [changelog.example.yml](config/changelog.example.yml) example file.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ changelog -m=1.11.0 -c=/path/to/my_config_file contributors
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
```
|
```
|
||||||
go generate ./...
|
|
||||||
go build
|
go build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,43 +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.
|
|
||||||
|
|
||||||
// +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)
|
|
||||||
}
|
|
||||||
}
|
|
105
cmd/cmd.go
105
cmd/cmd.go
|
@ -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
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,17 +7,83 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
MilestoneFlag string
|
// Version of changelog
|
||||||
ConfigPathFlag string
|
Version = "development"
|
||||||
TokenFlag string
|
milestoneFlag string
|
||||||
DetailsFlag bool
|
tagFlag string
|
||||||
AfterFlag int64
|
configPathFlag string
|
||||||
IssuesFlag bool
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
copyGlobalFlags(app)
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
func getDefaultConfigFile() string {
|
func getDefaultConfigFile() string {
|
||||||
pwd, err := os.Getwd()
|
pwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -30,3 +96,28 @@ func getDefaultConfigFile() string {
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyGlobalFlags(app *cli.App) {
|
||||||
|
for _, command := range app.Commands {
|
||||||
|
originalFlagNames := make([]string, 0, len(command.Flags))
|
||||||
|
for _, flag := range command.Flags {
|
||||||
|
originalFlagNames = append(originalFlagNames, flag.Names()...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flag := range app.Flags {
|
||||||
|
found := false
|
||||||
|
flagNameLoop:
|
||||||
|
for _, name := range flag.Names() {
|
||||||
|
for _, originalName := range originalFlagNames {
|
||||||
|
if name == originalName {
|
||||||
|
found = true
|
||||||
|
break flagNameLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
command.Flags = append(command.Flags, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,17 +20,13 @@ var Contributors = &cli.Command{
|
||||||
Action: runContributors,
|
Action: runContributors,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runContributors(cmd *cli.Context) error {
|
func runContributors(_ *cli.Context) error {
|
||||||
if ConfigPathFlag == "" {
|
cfg, err := config.New(configPathFlag)
|
||||||
ConfigPathFlag = getDefaultConfigFile()
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := config.New(ConfigPathFlag)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := service.New(cfg.Service, cfg.Repo, cfg.BaseURL, MilestoneFlag, TokenFlag, IssuesFlag)
|
s, err := service.New(cfg.Service, cfg.Repo, cfg.BaseURL, milestoneFlag, tagFlag, tokenFlag, issuesFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/changelog/config"
|
"code.gitea.io/changelog/config"
|
||||||
"code.gitea.io/changelog/service"
|
"code.gitea.io/changelog/service"
|
||||||
|
@ -14,30 +15,19 @@ import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var Generate = &cli.Command{
|
||||||
Generate = &cli.Command{
|
Name: "generate",
|
||||||
Name: "generate",
|
Usage: "Generates a changelog for a special milestone",
|
||||||
Usage: "Generates a changelog for a special milestone",
|
Action: runGenerate,
|
||||||
Action: runGenerate,
|
}
|
||||||
}
|
|
||||||
labels = make(map[string]string)
|
|
||||||
entries = make(map[string][]service.Entry)
|
|
||||||
defaultGroup string
|
|
||||||
)
|
|
||||||
|
|
||||||
func runGenerate(cmd *cli.Context) error {
|
func runGenerate(_ *cli.Context) error {
|
||||||
if ConfigPathFlag == "" {
|
cfg, err := config.New(configPathFlag)
|
||||||
ConfigPathFlag = getDefaultConfigFile()
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := config.New(ConfigPathFlag)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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, TokenFlag, IssuesFlag)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -47,7 +37,17 @@ func runGenerate(cmd *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
processPRs(prs, cfg.SkipRegex)
|
var defaultGroup string
|
||||||
|
for _, g := range cfg.Groups {
|
||||||
|
if g.Default {
|
||||||
|
defaultGroup = g.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if defaultGroup == "" {
|
||||||
|
fmt.Println("<!-- WARNING - no default group found -->")
|
||||||
|
}
|
||||||
|
|
||||||
|
entries := processPRs(prs, cfg.NameLabels(), defaultGroup, cfg.SkipRegex)
|
||||||
|
|
||||||
fmt.Println(title)
|
fmt.Println(title)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
@ -56,7 +56,7 @@ func runGenerate(cmd *cli.Context) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if DetailsFlag {
|
if detailsFlag {
|
||||||
fmt.Println("<details><summary>" + g.Name + "</summary>")
|
fmt.Println("<details><summary>" + g.Name + "</summary>")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
for _, entry := range entries[g.Name] {
|
for _, entry := range entries[g.Name] {
|
||||||
|
@ -74,44 +74,35 @@ func runGenerate(cmd *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processGroups(groups []config.Group) {
|
func processPRs(prs []service.Entry, order []config.NameLabel, defaultGroup string, skip *regexp.Regexp) map[string][]service.Entry {
|
||||||
for _, g := range groups {
|
entries := make(map[string][]service.Entry)
|
||||||
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) {
|
|
||||||
PRLoop: // labels in Go, let's get old school
|
PRLoop: // labels in Go, let's get old school
|
||||||
for _, pr := range prs {
|
for _, pr := range prs {
|
||||||
if pr.Index < AfterFlag {
|
if pr.Index < afterFlag {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var label string
|
|
||||||
for _, lb := range pr.Labels {
|
for _, lb := range pr.Labels {
|
||||||
if skip != nil && skip.MatchString(lb.Name) {
|
if skip != nil && skip.MatchString(lb.Name) {
|
||||||
continue PRLoop
|
continue PRLoop
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
section := processSection(pr, order, defaultGroup)
|
||||||
|
if section == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
entries[section] = append(entries[section], pr)
|
||||||
|
}
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
if g, ok := labels[lb.Name]; ok && len(label) == 0 {
|
func processSection(pr service.Entry, order []config.NameLabel, defaultGroup string) string {
|
||||||
label = g
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ var (
|
||||||
nameFlag string
|
nameFlag string
|
||||||
)
|
)
|
||||||
|
|
||||||
func runInit(cmd *cli.Context) error {
|
func runInit(_ *cli.Context) error {
|
||||||
if _, err := os.Stat(nameFlag); err == nil {
|
if _, err := os.Stat(nameFlag); err == nil {
|
||||||
return fmt.Errorf("file '%s' already exists", nameFlag)
|
return fmt.Errorf("file '%s' already exists", nameFlag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed changelog.example.yml
|
||||||
var DefaultConfig []byte
|
var DefaultConfig []byte
|
||||||
|
|
||||||
// Group is a grouping of PRs
|
// Group is a grouping of PRs
|
||||||
|
@ -20,6 +22,24 @@ type Group struct {
|
||||||
Default bool `yaml:"default"`
|
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
|
// Config is the changelog settings
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Repo string `yaml:"repo"`
|
Repo string `yaml:"repo"`
|
||||||
|
@ -30,13 +50,20 @@ type Config struct {
|
||||||
SkipRegex *regexp.Regexp `yaml:"-"`
|
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
|
// New Load a config from a path, defaulting to changelog.example.yml
|
||||||
func New(configPath string) (*Config, error) {
|
func New(configPath string) (*Config, error) {
|
||||||
var err error
|
var err error
|
||||||
var configContent []byte
|
configContent := DefaultConfig
|
||||||
if len(configPath) == 0 {
|
if len(configPath) != 0 {
|
||||||
configContent = DefaultConfig
|
|
||||||
} else {
|
|
||||||
configContent, err = ioutil.ReadFile(configPath)
|
configContent, err = ioutil.ReadFile(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -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
13
go.mod
|
@ -1,12 +1,19 @@
|
||||||
module code.gitea.io/changelog
|
module code.gitea.io/changelog
|
||||||
|
|
||||||
go 1.13
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.14.0
|
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/google/go-github/v32 v32.1.0
|
||||||
github.com/urfave/cli/v2 v2.2.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
|
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
|
||||||
|
)
|
||||||
|
|
87
main.go
87
main.go
|
@ -4,102 +4,17 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
//go:generate go run changelog.example.go
|
|
||||||
//go:generate go fmt ./...
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"code.gitea.io/changelog/cmd"
|
"code.gitea.io/changelog/cmd"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Version of changelog
|
|
||||||
Version = "development"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := &cli.App{
|
app := cmd.New()
|
||||||
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: "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,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
copyGlobalFlags(app)
|
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
fmt.Printf("Failed to run app with %s: %v\n", os.Args[1:], err)
|
fmt.Printf("Failed to run app with %s: %v\n", os.Args[1:], err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyGlobalFlags(app *cli.App) {
|
|
||||||
for _, command := range app.Commands {
|
|
||||||
originalFlagNames := make([]string, 0, len(command.Flags))
|
|
||||||
for _, flag := range command.Flags {
|
|
||||||
originalFlagNames = append(originalFlagNames, flag.Names()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, flag := range app.Flags {
|
|
||||||
found := false
|
|
||||||
flagNameLoop:
|
|
||||||
for _, name := range flag.Names() {
|
|
||||||
for _, originalName := range originalFlagNames {
|
|
||||||
if name == originalName {
|
|
||||||
found = true
|
|
||||||
break flagNameLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
command.Flags = append(command.Flags, flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
// Gitea defines a Gitea service
|
// Gitea defines a Gitea service
|
||||||
type Gitea struct {
|
type Gitea struct {
|
||||||
Milestone string
|
Milestone string
|
||||||
|
GitTag string
|
||||||
Token string
|
Token string
|
||||||
BaseURL string
|
BaseURL string
|
||||||
Owner string
|
Owner string
|
||||||
|
@ -40,7 +41,7 @@ func (ge *Gitea) Generate() (string, []Entry, error) {
|
||||||
from = "issues"
|
from = "issues"
|
||||||
}
|
}
|
||||||
|
|
||||||
tagURL := getGiteaTagURL(client, ge.BaseURL, ge.Owner, ge.Repo, ge.Milestone, from, milestone.ID)
|
tagURL := getGiteaTagURL(client, ge.BaseURL, ge.Owner, ge.Repo, ge.Milestone, ge.GitTag, from, milestone.ID)
|
||||||
|
|
||||||
perPage := ge.perPage(client)
|
perPage := ge.perPage(client)
|
||||||
for p := 1; ; p++ {
|
for p := 1; ; p++ {
|
||||||
|
@ -81,11 +82,11 @@ func (ge *Gitea) Generate() (string, []Entry, error) {
|
||||||
return tagURL, entries, nil
|
return tagURL, entries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGiteaTagURL(c *gitea.Client, baseURL, owner, repo, mileName, from string, mileID int64) string {
|
func getGiteaTagURL(c *gitea.Client, baseURL, owner, repo, mileName, gitTag, from string, mileID int64) string {
|
||||||
if err := c.CheckServerVersionConstraint(">=1.12"); err != nil {
|
if err := c.CheckServerVersionConstraint(">=1.12"); err != nil {
|
||||||
return fmt.Sprintf("## [%s](%s/%s/%s/%s?q=&type=all&state=closed&milestone=%d) - %s", mileName, baseURL, owner, repo, from, mileID, time.Now().Format("2006-01-02"))
|
return fmt.Sprintf("## [%s](%s/%s/%s/%s?q=&type=all&state=closed&milestone=%d) - %s", mileName, baseURL, owner, repo, from, mileID, time.Now().Format("2006-01-02"))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("## [%s](%s/%s/%s/releases/tag/%s) - %s", mileName, baseURL, owner, repo, mileName, time.Now().Format("2006-01-02"))
|
return fmt.Sprintf("## [%s](%s/%s/%s/releases/tag/%s) - %s", mileName, baseURL, owner, repo, gitTag, time.Now().Format("2006-01-02"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertToEntry(issue gitea.Issue) Entry {
|
func convertToEntry(issue gitea.Issue) Entry {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
// GitHub defines a GitHub service
|
// GitHub defines a GitHub service
|
||||||
type GitHub struct {
|
type GitHub struct {
|
||||||
Milestone string
|
Milestone string
|
||||||
|
GitTag string
|
||||||
Token string
|
Token string
|
||||||
Repo string
|
Repo string
|
||||||
Issues bool
|
Issues bool
|
||||||
|
@ -22,7 +23,7 @@ type GitHub struct {
|
||||||
|
|
||||||
// Generate returns a GitHub changelog
|
// Generate returns a GitHub changelog
|
||||||
func (gh *GitHub) Generate() (string, []Entry, error) {
|
func (gh *GitHub) Generate() (string, []Entry, error) {
|
||||||
tagURL := fmt.Sprintf("## [%s](https://github.com/%s/releases/tag/v%s) - %s", gh.Milestone, gh.Repo, gh.Milestone, time.Now().Format("2006-01-02"))
|
tagURL := fmt.Sprintf("## [%s](https://github.com/%s/releases/tag/%s) - %s", gh.Milestone, gh.Repo, gh.GitTag, time.Now().Format("2006-01-02"))
|
||||||
|
|
||||||
client := github.NewClient(nil)
|
client := github.NewClient(nil)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
|
@ -12,11 +12,16 @@ import (
|
||||||
const defaultGitea = "https://gitea.com"
|
const defaultGitea = "https://gitea.com"
|
||||||
|
|
||||||
// New returns a service from a string
|
// New returns a service from a string
|
||||||
func New(serviceType, repo, baseURL, milestone, token string, issues bool) (Service, error) {
|
func New(serviceType, repo, baseURL, milestone, tag, token string, issues bool) (Service, error) {
|
||||||
|
if len(tag) == 0 {
|
||||||
|
tag = milestone
|
||||||
|
}
|
||||||
|
|
||||||
switch strings.ToLower(serviceType) {
|
switch strings.ToLower(serviceType) {
|
||||||
case "github":
|
case "github":
|
||||||
return &GitHub{
|
return &GitHub{
|
||||||
Milestone: milestone,
|
Milestone: milestone,
|
||||||
|
GitTag: tag,
|
||||||
Token: token,
|
Token: token,
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
Issues: issues,
|
Issues: issues,
|
||||||
|
@ -28,6 +33,7 @@ func New(serviceType, repo, baseURL, milestone, token string, issues bool) (Serv
|
||||||
}
|
}
|
||||||
return &Gitea{
|
return &Gitea{
|
||||||
Milestone: milestone,
|
Milestone: milestone,
|
||||||
|
GitTag: tag,
|
||||||
Token: token,
|
Token: token,
|
||||||
BaseURL: baseURL,
|
BaseURL: baseURL,
|
||||||
Owner: ownerRepo[0],
|
Owner: ownerRepo[0],
|
||||||
|
|
Loading…
Reference in New Issue