feat: support conventional commits exclamation mark on breaking changes
BREAKING CHANGE: changes commit-log command json, rename subject to description, move all commit message attributes to 'message'
This commit is contained in:
parent
0df2c6facc
commit
8cf6f1eb56
11 changed files with 233 additions and 76 deletions
|
@ -12,8 +12,8 @@ type Config struct {
|
||||||
MinorVersionTypes []string `envconfig:"MINOR_VERSION_TYPES" default:"feat"`
|
MinorVersionTypes []string `envconfig:"MINOR_VERSION_TYPES" default:"feat"`
|
||||||
PatchVersionTypes []string `envconfig:"PATCH_VERSION_TYPES" default:"build,ci,chore,docs,fix,perf,refactor,style,test"`
|
PatchVersionTypes []string `envconfig:"PATCH_VERSION_TYPES" default:"build,ci,chore,docs,fix,perf,refactor,style,test"`
|
||||||
IncludeUnknownTypeAsPatch bool `envconfig:"INCLUDE_UNKNOWN_TYPE_AS_PATCH" default:"true"`
|
IncludeUnknownTypeAsPatch bool `envconfig:"INCLUDE_UNKNOWN_TYPE_AS_PATCH" default:"true"`
|
||||||
BreakingChangePrefixes []string `envconfig:"BRAKING_CHANGE_PREFIXES" default:"BREAKING CHANGE:,BREAKING CHANGES:"`
|
BreakingChangePrefixes []string `envconfig:"BRAKING_CHANGE_PREFIXES" default:"BREAKING CHANGE,BREAKING CHANGES"`
|
||||||
IssueIDPrefixes []string `envconfig:"ISSUEID_PREFIXES" default:"jira:,JIRA:,Jira:"`
|
IssueIDPrefixes []string `envconfig:"ISSUEID_PREFIXES" default:"jira,JIRA,Jira"`
|
||||||
TagPattern string `envconfig:"TAG_PATTERN" default:"%d.%d.%d"`
|
TagPattern string `envconfig:"TAG_PATTERN" default:"%d.%d.%d"`
|
||||||
ReleaseNotesTags map[string]string `envconfig:"RELEASE_NOTES_TAGS" default:"fix:Bug Fixes,feat:Features"`
|
ReleaseNotesTags map[string]string `envconfig:"RELEASE_NOTES_TAGS" default:"fix:Bug Fixes,feat:Features"`
|
||||||
ValidateMessageSkipBranches []string `envconfig:"VALIDATE_MESSAGE_SKIP_BRANCHES" default:"master,develop"`
|
ValidateMessageSkipBranches []string `envconfig:"VALIDATE_MESSAGE_SKIP_BRANCHES" default:"master,develop"`
|
||||||
|
|
|
@ -16,7 +16,18 @@ func main() {
|
||||||
|
|
||||||
cfg := loadConfig()
|
cfg := loadConfig()
|
||||||
|
|
||||||
git := sv.NewGit(cfg.BreakingChangePrefixes, cfg.IssueIDPrefixes, cfg.TagPattern)
|
// TODO: config using yaml
|
||||||
|
commitMessageCfg := sv.CommitMessageConfig{
|
||||||
|
Types: cfg.CommitMessageTypes,
|
||||||
|
Scope: sv.ScopeConfig{},
|
||||||
|
Footer: map[string]sv.FooterMetadataConfig{
|
||||||
|
"issue": {Key: cfg.IssueIDPrefixes[0], KeySynonyms: cfg.IssueIDPrefixes[1:], Regex: cfg.IssueRegex},
|
||||||
|
"breaking-change": {Key: cfg.BreakingChangePrefixes[0], KeySynonyms: cfg.BreakingChangePrefixes[1:]},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
////
|
||||||
|
|
||||||
|
git := sv.NewGit(sv.NewCommitMessageParser(commitMessageCfg), cfg.TagPattern)
|
||||||
semverProcessor := sv.NewSemVerCommitsProcessor(cfg.IncludeUnknownTypeAsPatch, cfg.MajorVersionTypes, cfg.MinorVersionTypes, cfg.PatchVersionTypes)
|
semverProcessor := sv.NewSemVerCommitsProcessor(cfg.IncludeUnknownTypeAsPatch, cfg.MajorVersionTypes, cfg.MinorVersionTypes, cfg.PatchVersionTypes)
|
||||||
releasenotesProcessor := sv.NewReleaseNoteProcessor(cfg.ReleaseNotesTags)
|
releasenotesProcessor := sv.NewReleaseNoteProcessor(cfg.ReleaseNotesTags)
|
||||||
outputFormatter := sv.NewOutputFormatter()
|
outputFormatter := sv.NewOutputFormatter()
|
||||||
|
|
121
sv/conventional_commit.go
Normal file
121
sv/conventional_commit.go
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
package sv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
breakingKey = "breaking-change"
|
||||||
|
// IssueIDKey key to issue id metadata
|
||||||
|
issueKey = "issue"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommitMessageConfig config a commit message
|
||||||
|
type CommitMessageConfig struct {
|
||||||
|
Types []string
|
||||||
|
Scope ScopeConfig
|
||||||
|
Footer map[string]FooterMetadataConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScopeConfig config scope preferences
|
||||||
|
type ScopeConfig struct {
|
||||||
|
Mandatory bool
|
||||||
|
Values []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FooterMetadataConfig config footer metadata
|
||||||
|
type FooterMetadataConfig struct {
|
||||||
|
Key string
|
||||||
|
KeySynonyms []string
|
||||||
|
Regex string
|
||||||
|
UseHash bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitMessage is a message using conventional commits.
|
||||||
|
type CommitMessage struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Scope string `json:"scope,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Body string `json:"body,omitempty"`
|
||||||
|
IsBreakingChange bool `json:"isBreakingChange,omitempty"`
|
||||||
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue return issue from metadata.
|
||||||
|
func (m CommitMessage) Issue() string {
|
||||||
|
return m.Metadata[issueKey]
|
||||||
|
}
|
||||||
|
|
||||||
|
// BreakingMessage return breaking change message from metadata.
|
||||||
|
func (m CommitMessage) BreakingMessage() string {
|
||||||
|
return m.Metadata[breakingKey]
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitMessageParser parse commit messages.
|
||||||
|
type CommitMessageParser interface {
|
||||||
|
Parse(subject, body string) CommitMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitMessageParserImpl commit message parser implementation
|
||||||
|
type CommitMessageParserImpl struct {
|
||||||
|
cfg CommitMessageConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCommitMessageParser CommitMessageParserImpl constructor
|
||||||
|
func NewCommitMessageParser(cfg CommitMessageConfig) CommitMessageParser {
|
||||||
|
return &CommitMessageParserImpl{cfg: cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parse a commit message
|
||||||
|
func (p CommitMessageParserImpl) Parse(subject, body string) CommitMessage {
|
||||||
|
commitType, scope, description, hasBreakingChange := parseSubjectMessage(subject)
|
||||||
|
|
||||||
|
metadata := make(map[string]string)
|
||||||
|
for key, mdCfg := range p.cfg.Footer {
|
||||||
|
prefixes := append([]string{mdCfg.Key}, mdCfg.KeySynonyms...)
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if tagValue := extractFooterMetadata(prefix, body, mdCfg.UseHash); tagValue != "" {
|
||||||
|
metadata[key] = tagValue
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists := metadata[breakingKey]; exists {
|
||||||
|
hasBreakingChange = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return CommitMessage{
|
||||||
|
Type: commitType,
|
||||||
|
Scope: scope,
|
||||||
|
Description: description,
|
||||||
|
Body: body,
|
||||||
|
IsBreakingChange: hasBreakingChange,
|
||||||
|
Metadata: metadata,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSubjectMessage(message string) (string, string, string, bool) {
|
||||||
|
regex := regexp.MustCompile("([a-z]+)(\\((.*)\\))?(!)?: (.*)")
|
||||||
|
result := regex.FindStringSubmatch(message)
|
||||||
|
if len(result) != 6 {
|
||||||
|
return "", "", message, false
|
||||||
|
}
|
||||||
|
return result[1], result[3], strings.TrimSpace(result[5]), result[4] == "!"
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractFooterMetadata(key, text string, useHash bool) string {
|
||||||
|
var regex *regexp.Regexp
|
||||||
|
if useHash {
|
||||||
|
regex = regexp.MustCompile(key + " (#.*)")
|
||||||
|
} else {
|
||||||
|
regex = regexp.MustCompile(key + ": (.*)")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := regex.FindStringSubmatch(text)
|
||||||
|
if len(result) < 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return result[1]
|
||||||
|
}
|
60
sv/conventional_commit_test.go
Normal file
60
sv/conventional_commit_test.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package sv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cfg = CommitMessageConfig{
|
||||||
|
Types: []string{"feat", "fix"},
|
||||||
|
Scope: ScopeConfig{},
|
||||||
|
Footer: map[string]FooterMetadataConfig{
|
||||||
|
"issue": {Key: "jira", KeySynonyms: []string{"Jira"}, Regex: "[A-Z]+-[0-9]+"},
|
||||||
|
"breaking-change": {Key: "BREAKING CHANGE", KeySynonyms: []string{"BREAKING CHANGES"}},
|
||||||
|
"refs": {Key: "Refs", UseHash: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var completeBody = `some descriptions
|
||||||
|
|
||||||
|
jira: JIRA-123
|
||||||
|
BREAKING CHANGE: this change breaks everything`
|
||||||
|
|
||||||
|
var issueOnlyBody = `some descriptions
|
||||||
|
|
||||||
|
jira: JIRA-456`
|
||||||
|
|
||||||
|
var issueSynonymsBody = `some descriptions
|
||||||
|
|
||||||
|
Jira: JIRA-789`
|
||||||
|
|
||||||
|
var hashMetadataBody = `some descriptions
|
||||||
|
|
||||||
|
Jira: JIRA-999
|
||||||
|
Refs #123`
|
||||||
|
|
||||||
|
func TestCommitMessageParserImpl_Parse(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
subject string
|
||||||
|
body string
|
||||||
|
want CommitMessage
|
||||||
|
}{
|
||||||
|
{"simple message", "feat: something awesome", "", CommitMessage{Type: "feat", Scope: "", Description: "something awesome", Body: "", IsBreakingChange: false, Metadata: map[string]string{}}},
|
||||||
|
{"message with scope", "feat(scope): something awesome", "", CommitMessage{Type: "feat", Scope: "scope", Description: "something awesome", Body: "", IsBreakingChange: false, Metadata: map[string]string{}}},
|
||||||
|
{"unmapped type", "unkn: something unknown", "", CommitMessage{Type: "unkn", Scope: "", Description: "something unknown", Body: "", IsBreakingChange: false, Metadata: map[string]string{}}},
|
||||||
|
{"jira and breaking change metadata", "feat: something new", completeBody, CommitMessage{Type: "feat", Scope: "", Description: "something new", Body: completeBody, IsBreakingChange: true, Metadata: map[string]string{issueKey: "JIRA-123", breakingKey: "this change breaks everything"}}},
|
||||||
|
{"jira only metadata", "feat: something new", issueOnlyBody, CommitMessage{Type: "feat", Scope: "", Description: "something new", Body: issueOnlyBody, IsBreakingChange: false, Metadata: map[string]string{issueKey: "JIRA-456"}}},
|
||||||
|
{"jira synonyms metadata", "feat: something new", issueSynonymsBody, CommitMessage{Type: "feat", Scope: "", Description: "something new", Body: issueSynonymsBody, IsBreakingChange: false, Metadata: map[string]string{issueKey: "JIRA-789"}}},
|
||||||
|
{"breaking change with exclamation mark", "feat!: something new", "", CommitMessage{Type: "feat", Scope: "", Description: "something new", Body: "", IsBreakingChange: true, Metadata: map[string]string{}}},
|
||||||
|
{"hash metadata", "feat: something new", hashMetadataBody, CommitMessage{Type: "feat", Scope: "", Description: "something new", Body: hashMetadataBody, IsBreakingChange: false, Metadata: map[string]string{issueKey: "JIRA-999", "refs": "#123"}}},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
p := NewCommitMessageParser(cfg)
|
||||||
|
if got := p.Parse(tt.subject, tt.body); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("CommitMessageParserImpl.Parse() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ const (
|
||||||
{{- end}}
|
{{- end}}
|
||||||
`
|
`
|
||||||
|
|
||||||
rnSectionItem = "- {{if .Scope}}**{{.Scope}}:** {{end}}{{.Subject}} ({{.Hash}}){{if .Metadata.issueid}} ({{.Metadata.issueid}}){{end}}"
|
rnSectionItem = "- {{if .Message.Scope}}**{{.Message.Scope}}:** {{end}}{{.Message.Description}} ({{.Hash}}){{if .Message.Metadata.issue}} ({{.Message.Metadata.issue}}){{end}}"
|
||||||
|
|
||||||
rnSection = `{{- if .}}
|
rnSection = `{{- if .}}
|
||||||
|
|
||||||
|
|
73
sv/git.go
73
sv/git.go
|
@ -6,7 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,11 +15,6 @@ import (
|
||||||
const (
|
const (
|
||||||
logSeparator = "##"
|
logSeparator = "##"
|
||||||
endLine = "~~"
|
endLine = "~~"
|
||||||
|
|
||||||
// BreakingChangesKey key to breaking change metadata
|
|
||||||
BreakingChangesKey = "breakingchange"
|
|
||||||
// IssueIDKey key to issue id metadata
|
|
||||||
IssueIDKey = "issueid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Git commands
|
// Git commands
|
||||||
|
@ -35,13 +29,9 @@ type Git interface {
|
||||||
|
|
||||||
// GitCommitLog description of a single commit log
|
// GitCommitLog description of a single commit log
|
||||||
type GitCommitLog struct {
|
type GitCommitLog struct {
|
||||||
Date string `json:"date,omitempty"`
|
Date string `json:"date,omitempty"`
|
||||||
Hash string `json:"hash,omitempty"`
|
Hash string `json:"hash,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Message CommitMessage `json:"message,omitempty"`
|
||||||
Scope string `json:"scope,omitempty"`
|
|
||||||
Subject string `json:"subject,omitempty"`
|
|
||||||
Body string `json:"body,omitempty"`
|
|
||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GitTag git tag info
|
// GitTag git tag info
|
||||||
|
@ -74,15 +64,15 @@ func NewLogRange(t LogRangeType, start, end string) LogRange {
|
||||||
|
|
||||||
// GitImpl git command implementation
|
// GitImpl git command implementation
|
||||||
type GitImpl struct {
|
type GitImpl struct {
|
||||||
messageMetadata map[string][]string
|
messageParser CommitMessageParser
|
||||||
tagPattern string
|
tagPattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGit constructor
|
// NewGit constructor
|
||||||
func NewGit(breakinChangePrefixes, issueIDPrefixes []string, tagPattern string) *GitImpl {
|
func NewGit(messageParser CommitMessageParser, tagPattern string) *GitImpl {
|
||||||
return &GitImpl{
|
return &GitImpl{
|
||||||
messageMetadata: map[string][]string{BreakingChangesKey: breakinChangePrefixes, IssueIDKey: issueIDPrefixes},
|
messageParser: messageParser,
|
||||||
tagPattern: tagPattern,
|
tagPattern: tagPattern,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +109,7 @@ func (g GitImpl) Log(lr LogRange) ([]GitCommitLog, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, combinedOutputErr(err, out)
|
return nil, combinedOutputErr(err, out)
|
||||||
}
|
}
|
||||||
return parseLogOutput(g.messageMetadata, string(out)), nil
|
return parseLogOutput(g.messageParser, string(out)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit runs git commit
|
// Commit runs git commit
|
||||||
|
@ -177,61 +167,28 @@ func parseTagsOutput(input string) ([]GitTag, error) {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLogOutput(messageMetadata map[string][]string, log string) []GitCommitLog {
|
func parseLogOutput(messageParser CommitMessageParser, log string) []GitCommitLog {
|
||||||
scanner := bufio.NewScanner(strings.NewReader(log))
|
scanner := bufio.NewScanner(strings.NewReader(log))
|
||||||
scanner.Split(splitAt([]byte(endLine)))
|
scanner.Split(splitAt([]byte(endLine)))
|
||||||
var logs []GitCommitLog
|
var logs []GitCommitLog
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
if text := strings.TrimSpace(strings.Trim(scanner.Text(), "\"")); text != "" {
|
if text := strings.TrimSpace(strings.Trim(scanner.Text(), "\"")); text != "" {
|
||||||
logs = append(logs, parseCommitLog(messageMetadata, text))
|
logs = append(logs, parseCommitLog(messageParser, text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return logs
|
return logs
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCommitLog(messageMetadata map[string][]string, commit string) GitCommitLog {
|
func parseCommitLog(messageParser CommitMessageParser, commit string) GitCommitLog {
|
||||||
content := strings.Split(strings.Trim(commit, "\""), logSeparator)
|
content := strings.Split(strings.Trim(commit, "\""), logSeparator)
|
||||||
commitType, scope, subject := parseCommitLogMessage(content[2])
|
|
||||||
|
|
||||||
metadata := make(map[string]string)
|
|
||||||
for key, prefixes := range messageMetadata {
|
|
||||||
for _, prefix := range prefixes {
|
|
||||||
if tagValue := extractTag(prefix, content[3]); tagValue != "" {
|
|
||||||
metadata[key] = tagValue
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GitCommitLog{
|
return GitCommitLog{
|
||||||
Date: content[0],
|
Date: content[0],
|
||||||
Hash: content[1],
|
Hash: content[1],
|
||||||
Type: commitType,
|
Message: messageParser.Parse(content[2], content[3]),
|
||||||
Scope: scope,
|
|
||||||
Subject: subject,
|
|
||||||
Body: content[3],
|
|
||||||
Metadata: metadata,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCommitLogMessage(message string) (string, string, string) {
|
|
||||||
regex := regexp.MustCompile("([a-z]+)(\\((.*)\\))?: (.*)")
|
|
||||||
result := regex.FindStringSubmatch(message)
|
|
||||||
if len(result) != 5 {
|
|
||||||
return "", "", message
|
|
||||||
}
|
|
||||||
return result[1], result[3], strings.TrimSpace(result[4])
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractTag(tag, text string) string {
|
|
||||||
regex := regexp.MustCompile(tag + " (.*)")
|
|
||||||
result := regex.FindStringSubmatch(text)
|
|
||||||
if len(result) < 2 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return result[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitAt(b []byte) func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
func splitAt(b []byte) func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||||
dataLen := len(data)
|
dataLen := len(data)
|
||||||
|
|
|
@ -12,10 +12,17 @@ func version(v string) semver.Version {
|
||||||
}
|
}
|
||||||
|
|
||||||
func commitlog(t string, metadata map[string]string) GitCommitLog {
|
func commitlog(t string, metadata map[string]string) GitCommitLog {
|
||||||
|
breaking := false
|
||||||
|
if _, found := metadata[breakingKey]; found {
|
||||||
|
breaking = true
|
||||||
|
}
|
||||||
return GitCommitLog{
|
return GitCommitLog{
|
||||||
Type: t,
|
Message: CommitMessage{
|
||||||
Subject: "subject text",
|
Type: t,
|
||||||
Metadata: metadata,
|
Description: "subject text",
|
||||||
|
IsBreakingChange: breaking,
|
||||||
|
Metadata: metadata,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,16 +26,17 @@ func (p ReleaseNoteProcessorImpl) Create(version *semver.Version, date time.Time
|
||||||
sections := make(map[string]ReleaseNoteSection)
|
sections := make(map[string]ReleaseNoteSection)
|
||||||
var breakingChanges []string
|
var breakingChanges []string
|
||||||
for _, commit := range commits {
|
for _, commit := range commits {
|
||||||
if name, exists := p.tags[commit.Type]; exists {
|
if name, exists := p.tags[commit.Message.Type]; exists {
|
||||||
section, sexists := sections[commit.Type]
|
section, sexists := sections[commit.Message.Type]
|
||||||
if !sexists {
|
if !sexists {
|
||||||
section = ReleaseNoteSection{Name: name}
|
section = ReleaseNoteSection{Name: name}
|
||||||
}
|
}
|
||||||
section.Items = append(section.Items, commit)
|
section.Items = append(section.Items, commit)
|
||||||
sections[commit.Type] = section
|
sections[commit.Message.Type] = section
|
||||||
}
|
}
|
||||||
if value, exists := commit.Metadata[BreakingChangesKey]; exists {
|
if commit.Message.BreakingMessage() != "" {
|
||||||
breakingChanges = append(breakingChanges, value)
|
// TODO: if no message found, should use description instead?
|
||||||
|
breakingChanges = append(breakingChanges, commit.Message.BreakingMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ func TestReleaseNoteProcessorImpl_Create(t *testing.T) {
|
||||||
name: "breaking changes tag",
|
name: "breaking changes tag",
|
||||||
version: semver.MustParse("1.0.0"),
|
version: semver.MustParse("1.0.0"),
|
||||||
date: date,
|
date: date,
|
||||||
commits: []GitCommitLog{commitlog("t1", map[string]string{}), commitlog("unmapped", map[string]string{"breakingchange": "breaks"})},
|
commits: []GitCommitLog{commitlog("t1", map[string]string{}), commitlog("unmapped", map[string]string{"breaking-change": "breaks"})},
|
||||||
want: releaseNote(semver.MustParse("1.0.0"), date, map[string]ReleaseNoteSection{"t1": newReleaseNoteSection("Tag 1", []GitCommitLog{commitlog("t1", map[string]string{})})}, []string{"breaks"}),
|
want: releaseNote(semver.MustParse("1.0.0"), date, map[string]ReleaseNoteSection{"t1": newReleaseNoteSection("Tag 1", []GitCommitLog{commitlog("t1", map[string]string{})})}, []string{"breaks"}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,16 +69,16 @@ func (p SemVerCommitsProcessorImpl) NextVersion(version semver.Version, commits
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p SemVerCommitsProcessorImpl) versionTypeToUpdate(commit GitCommitLog) versionType {
|
func (p SemVerCommitsProcessorImpl) versionTypeToUpdate(commit GitCommitLog) versionType {
|
||||||
if _, exists := commit.Metadata[BreakingChangesKey]; exists {
|
if commit.Message.IsBreakingChange {
|
||||||
return major
|
return major
|
||||||
}
|
}
|
||||||
if _, exists := p.MajorVersionTypes[commit.Type]; exists {
|
if _, exists := p.MajorVersionTypes[commit.Message.Type]; exists {
|
||||||
return major
|
return major
|
||||||
}
|
}
|
||||||
if _, exists := p.MinorVersionTypes[commit.Type]; exists {
|
if _, exists := p.MinorVersionTypes[commit.Message.Type]; exists {
|
||||||
return minor
|
return minor
|
||||||
}
|
}
|
||||||
if _, exists := p.PatchVersionTypes[commit.Type]; exists {
|
if _, exists := p.PatchVersionTypes[commit.Message.Type]; exists {
|
||||||
return patch
|
return patch
|
||||||
}
|
}
|
||||||
if p.IncludeUnknownTypeAsPatch {
|
if p.IncludeUnknownTypeAsPatch {
|
||||||
|
|
|
@ -21,7 +21,7 @@ func TestSemVerCommitsProcessorImpl_NextVersion(t *testing.T) {
|
||||||
{"patch update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{})}, version("0.0.1")},
|
{"patch update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{})}, version("0.0.1")},
|
||||||
{"minor update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("minor", map[string]string{})}, version("0.1.0")},
|
{"minor update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("minor", map[string]string{})}, version("0.1.0")},
|
||||||
{"major update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("major", map[string]string{})}, version("1.0.0")},
|
{"major update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("major", map[string]string{})}, version("1.0.0")},
|
||||||
{"breaking change update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("patch", map[string]string{"breakingchange": "break"})}, version("1.0.0")},
|
{"breaking change update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("patch", map[string]string{"breaking-change": "break"})}, version("1.0.0")},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue