feat: Add support for Bitbucket

This commit is contained in:
tsuyoshiwada 2018-04-14 15:09:06 +09:00
parent 765f0c96ed
commit 21ae9e8388
8 changed files with 236 additions and 9 deletions

View file

@ -108,6 +108,10 @@ func (config *Config) normalizeStyle() {
switch config.Style {
case "github":
config.normalizeStyleOfGitHub()
case "gitlab":
config.normalizeStyleOfGitLab()
case "bitbucket":
config.normalizeStyleOfBitbucket()
}
}
@ -184,6 +188,61 @@ func (config *Config) normalizeStyleOfGitLab() {
config.Options = opts
}
// For Bitbucket
func (config *Config) normalizeStyleOfBitbucket() {
opts := config.Options
if len(opts.Issues.Prefix) == 0 {
opts.Issues.Prefix = []string{
"#",
}
}
if len(opts.Refs.Actions) == 0 {
opts.Refs.Actions = []string{
"close",
"closes",
"closed",
"closing",
"fix",
"fixed",
"fixes",
"fixing",
"resolve",
"resolves",
"resolved",
"resolving",
"eopen",
"reopens",
"reopening",
"hold",
"holds",
"holding",
"wontfix",
"invalidate",
"invalidates",
"invalidated",
"invalidating",
"addresses",
"re",
"references",
"ref",
"refs",
"see",
}
}
if opts.Merges.Pattern == "" && len(opts.Merges.PatternMaps) == 0 {
opts.Merges.Pattern = "^Merged in (.*) \\(pull request #(\\d+)\\)$"
opts.Merges.PatternMaps = []string{
"Source",
"Ref",
}
}
config.Options = opts
}
// Convert ...
func (config *Config) Convert(ctx *CLIContext) *chglog.Config {
info := config.Info

View file

@ -51,6 +51,9 @@ func (*customTemplateBuilderImpl) versionHeader(style, template string) string {
case styleGitHub, styleGitLab:
tpl = "<a name=\"{{.Tag.Name}}\"></a>\n"
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]({{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}){{else}}{{.Tag.Name}}{{end}}"
case styleBitbucket:
tpl = "<a name=\"{{.Tag.Name}}\"></a>\n"
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]({{$.Info.RepositoryURL}}/compare/{{.Tag.Name}}..{{.Tag.Previous.Name}}){{else}}{{.Tag.Name}}{{end}}"
}
// format
@ -113,7 +116,7 @@ func (t *customTemplateBuilderImpl) merges(style string) string {
var title string
switch style {
case styleGitHub:
case styleGitHub, styleBitbucket:
title = "Pull Requests"
case styleGitLab:
title = "Merge Requests"

View file

@ -47,7 +47,7 @@ func (t *kacTemplateBuilderImpl) versionHeader(style string) string {
)
switch style {
case styleGitHub, styleGitLab:
case styleGitHub, styleGitLab, styleBitbucket:
tagName = "{{if .Tag.Previous}}[{{.Tag.Name}}]{{else}}{{.Tag.Name}}{{end}}"
}
@ -85,7 +85,7 @@ func (t *kacTemplateBuilderImpl) merges(style string) string {
var title string
switch style {
case styleGitHub:
case styleGitHub, styleBitbucket:
title = "Pull Requests"
case styleGitLab:
title = "Merge Requests"
@ -114,6 +114,11 @@ func (*kacTemplateBuilderImpl) footer(style string) string {
return `{{if .Versions}}
[Unreleased]: {{.Info.RepositoryURL}}/compare/{{$latest := index .Versions 0}}{{$latest.Tag.Name}}...HEAD{{range .Versions}}{{if .Tag.Previous}}
[{{.Tag.Name}}]: {{$.Info.RepositoryURL}}/compare/{{.Tag.Previous.Name}}...{{.Tag.Name}}{{end}}{{end}}
{{end}}`
case styleBitbucket:
return `{{if .Versions}}
[Unreleased]: {{.Info.RepositoryURL}}/compare/HEAD..{{$latest := index .Versions 0}}{{$latest.Tag.Name}}{{range .Versions}}{{if .Tag.Previous}}
[{{.Tag.Name}}]: {{$.Info.RepositoryURL}}/compare/{{.Tag.Name}}..{{.Tag.Previous.Name}}{{end}}{{end}}
{{end}}`
default:
return ""

View file

@ -16,8 +16,9 @@ type ProcessorFactory struct {
func NewProcessorFactory() *ProcessorFactory {
return &ProcessorFactory{
hostRegistry: map[string]string{
"github": "github.com",
"gitlab": "gitlab.com",
"github": "github.com",
"gitlab": "gitlab.com",
"bitbucket": "bitbucket.org",
},
}
}
@ -46,6 +47,10 @@ func (factory *ProcessorFactory) Create(config *Config) (chglog.Processor, error
return &chglog.GitLabProcessor{
Host: fmt.Sprintf("%s://%s", obj.Scheme, obj.Host),
}, nil
case "bitbucket.org":
return &chglog.BitbucketProcessor{
Host: fmt.Sprintf("%s://%s", obj.Scheme, obj.Host),
}, nil
default:
return nil, nil
}

View file

@ -92,3 +92,39 @@ func TestProcessorFactoryForGitLab(t *testing.T) {
processor,
)
}
func TestProcessorFactoryForBitbucket(t *testing.T) {
assert := assert.New(t)
factory := NewProcessorFactory()
// bitbucket.org
processor, err := factory.Create(&Config{
Info: Info{
RepositoryURL: "https://bitbucket.org/owner/repo",
},
})
assert.Nil(err)
assert.Equal(
&chglog.BitbucketProcessor{
Host: "https://bitbucket.org",
},
processor,
)
// self-hosted
processor, err = factory.Create(&Config{
Style: "bitbucket",
Info: Info{
RepositoryURL: "https://original-gitserver.com/owner/repo",
},
})
assert.Nil(err)
assert.Equal(
&chglog.BitbucketProcessor{
Host: "https://original-gitserver.com",
},
processor,
)
}

View file

@ -14,12 +14,14 @@ var (
// Styles
var (
styleGitHub = "github"
styleGitLab = "gitlab"
styleNone = "none"
styles = []string{
styleGitHub = "github"
styleGitLab = "gitlab"
styleBitbucket = "bitbucket"
styleNone = "none"
styles = []string{
styleGitHub,
styleGitLab,
styleBitbucket,
styleNone,
}
)

View file

@ -120,3 +120,58 @@ func (p *GitLabProcessor) addLinks(input string) string {
return input
}
// BitbucketProcessor is optimized for CHANGELOG used in Bitbucket
//
// The following processing is performed
// - Mentions automatic link (@tsuyoshiwada -> [@tsuyoshiwada](https://bitbucket.org/tsuyoshiwada/))
// - Automatic link to references (#123 -> [#123](https://bitbucket.org/owner/repo/issues/123/))
type BitbucketProcessor struct {
Host string // Host name used for link destination. Note: You must include the protocol (e.g. "https://bitbucket.org")
config *Config
reMention *regexp.Regexp
reIssue *regexp.Regexp
}
// Bootstrap ...
func (p *BitbucketProcessor) Bootstrap(config *Config) {
p.config = config
if p.Host == "" {
p.Host = "https://bitbucket.org"
} else {
p.Host = strings.TrimRight(p.Host, "/")
}
p.reMention = regexp.MustCompile("@(\\w+)")
p.reIssue = regexp.MustCompile("(?i)#(\\d+)")
}
// ProcessCommit ...
func (p *BitbucketProcessor) ProcessCommit(commit *Commit) *Commit {
commit.Header = p.addLinks(commit.Header)
commit.Subject = p.addLinks(commit.Subject)
commit.Body = p.addLinks(commit.Body)
for _, note := range commit.Notes {
note.Body = p.addLinks(note.Body)
}
if commit.Revert != nil {
commit.Revert.Header = p.addLinks(commit.Revert.Header)
}
return commit
}
func (p *BitbucketProcessor) addLinks(input string) string {
repoURL := strings.TrimRight(p.config.Info.RepositoryURL, "/")
// mentions
input = p.reMention.ReplaceAllString(input, "[@$1]("+p.Host+"/$1/)")
// issues
input = p.reIssue.ReplaceAllString(input, "[#$1]("+repoURL+"/issues/$1/)")
return input
}

View file

@ -129,3 +129,65 @@ gh-56 hoge fuga`,
),
)
}
func TestBitbucketProcessor(t *testing.T) {
assert := assert.New(t)
config := &Config{
Info: &Info{
RepositoryURL: "https://example.com",
},
}
processor := &BitbucketProcessor{}
processor.Bootstrap(config)
assert.Equal(
&Commit{
Header: "message [@foo](https://bitbucket.org/foo/) [#123](https://example.com/issues/123/)",
Subject: "message [@foo](https://bitbucket.org/foo/) [#123](https://example.com/issues/123/)",
Body: `issue [#456](https://example.com/issues/456/)
multiline [#789](https://example.com/issues/789/)
[@foo](https://bitbucket.org/foo/), [@bar](https://bitbucket.org/bar/)`,
Notes: []*Note{
&Note{
Body: `issue1 [#11](https://example.com/issues/11/)
issue2 [#22](https://example.com/issues/22/)
gh-56 hoge fuga`,
},
},
},
processor.ProcessCommit(
&Commit{
Header: "message @foo #123",
Subject: "message @foo #123",
Body: `issue #456
multiline #789
@foo, @bar`,
Notes: []*Note{
&Note{
Body: `issue1 #11
issue2 #22
gh-56 hoge fuga`,
},
},
},
),
)
assert.Equal(
&Commit{
Revert: &Revert{
Header: "revert header [@mention](https://bitbucket.org/mention/) [#123](https://example.com/issues/123/)",
},
},
processor.ProcessCommit(
&Commit{
Revert: &Revert{
Header: "revert header @mention #123",
},
},
),
)
}