diff --git a/pkg/analyzer/commit_analyzer.go b/pkg/analyzer/commit_analyzer.go index 76cecc55608703969422549a930f4afabc7cdbc7..7b1779892695e077a8d55334d061a7030c613b72 100644 --- a/pkg/analyzer/commit_analyzer.go +++ b/pkg/analyzer/commit_analyzer.go @@ -23,6 +23,29 @@ func extractMentions(re *regexp.Regexp, s string) string { return strings.Join(ret, ",") } +func matchesBreakingPattern(c *semrel.Commit) bool { + return breakingPattern.MatchString(strings.Join(c.Raw, "\n")) +} + +func setTypeAndChange(c *semrel.Commit) { + found := commitPattern.FindAllStringSubmatch(c.Raw[0], -1) + if len(found) < 1 { + // commit message does not match pattern + return + } + + c.Type = strings.ToLower(found[0][1]) + c.Scope = found[0][2] + c.Message = found[0][4] + + c.Change = &semrel.Change{ + // either uses the `!` convention or has a breaking change section + Major: found[0][3] == "!" || matchesBreakingPattern(c), + Minor: c.Type == "feat", + Patch: c.Type == "fix", + } +} + type DefaultCommitAnalyzer struct{} func (da *DefaultCommitAnalyzer) Init(_ map[string]string) error { @@ -47,30 +70,7 @@ func (da *DefaultCommitAnalyzer) analyzeSingleCommit(rawCommit *semrel.RawCommit c.Annotations["mentioned_issues"] = extractMentions(mentionedIssuesPattern, rawCommit.RawMessage) c.Annotations["mentioned_users"] = extractMentions(mentionedUsersPattern, rawCommit.RawMessage) - found := commitPattern.FindAllStringSubmatch(c.Raw[0], -1) - if len(found) < 1 { - return c - } - c.Type = strings.ToLower(found[0][1]) - c.Scope = found[0][2] - breakingChange := found[0][3] - c.Message = found[0][4] - - isMajorChange := breakingPattern.MatchString(rawCommit.RawMessage) - isMinorChange := c.Type == "feat" - isPatchChange := c.Type == "fix" - - if len(breakingChange) > 0 { - isMajorChange = true - isMinorChange = false - isPatchChange = false - } - - c.Change = &semrel.Change{ - Major: isMajorChange, - Minor: isMinorChange, - Patch: isPatchChange, - } + setTypeAndChange(c) return c } diff --git a/pkg/analyzer/commit_analyzer_test.go b/pkg/analyzer/commit_analyzer_test.go index 14c356f24cec71c4abb937ec6dada2d9bdca7301..d397fee7b52bb5bc0c3e4c6525374e2008a84f10 100644 --- a/pkg/analyzer/commit_analyzer_test.go +++ b/pkg/analyzer/commit_analyzer_test.go @@ -9,18 +9,6 @@ import ( "github.com/stretchr/testify/require" ) -func compareCommit(c *semrel.Commit, t, s string, change *semrel.Change) bool { - if c.Type != t || c.Scope != s { - return false - } - if c.Change.Major != change.Major || - c.Change.Minor != change.Minor || - c.Change.Patch != change.Patch { - return false - } - return true -} - func createRawCommit(sha, message string) *semrel.RawCommit { return &semrel.RawCommit{ SHA: sha, @@ -77,13 +65,13 @@ func TestDefaultAnalyzer(t *testing.T) { createRawCommit("e", "feat!: modified login endpoint"), "feat", "", - &semrel.Change{Major: true, Minor: false, Patch: false}, + &semrel.Change{Major: true, Minor: true, Patch: false}, }, { createRawCommit("f", "fix!: fixed a typo"), "fix", "", - &semrel.Change{Major: true, Minor: false, Patch: false}, + &semrel.Change{Major: true, Minor: false, Patch: true}, }, { createRawCommit("g", "refactor(parser)!: drop support for Node 6\n\nBREAKING CHANGE: refactor to use JavaScript features not available in Node 6."), @@ -103,71 +91,81 @@ func TestDefaultAnalyzer(t *testing.T) { "", &semrel.Change{Major: false, Minor: false, Patch: false}, }, + { + createRawCommit("i", "feat(deps): update deps\n\nBREAKING CHANGE: update to new version of dep"), + "feat", + "deps", + &semrel.Change{Major: true, Minor: true, Patch: false}, + }, } defaultAnalyzer := &DefaultCommitAnalyzer{} for _, tc := range testCases { t.Run(fmt.Sprintf("AnalyzeCommitMessage: %s", tc.RawCommit.RawMessage), func(t *testing.T) { - require.True(t, compareCommit(defaultAnalyzer.analyzeSingleCommit(tc.RawCommit), tc.Type, tc.Scope, tc.Change)) + analyzedCommit := defaultAnalyzer.analyzeSingleCommit(tc.RawCommit) + require.Equal(t, tc.Type, analyzedCommit.Type, "Type") + require.Equal(t, tc.Scope, analyzedCommit.Scope, "Scope") + require.Equal(t, tc.Change.Major, analyzedCommit.Change.Major, "Major") + require.Equal(t, tc.Change.Minor, analyzedCommit.Change.Minor, "Minor") + require.Equal(t, tc.Change.Patch, analyzedCommit.Change.Patch, "Patch") }) } } func TestCommitPattern(t *testing.T) { testCases := []struct { - rawMessage string - wanted []string + message string + wanted []string }{ { - rawMessage: "feat: new feature", - wanted: []string{"feat", "", "", "new feature"}, + message: "feat: new feature", + wanted: []string{"feat", "", "", "new feature"}, }, { - rawMessage: "feat!: new feature", - wanted: []string{"feat", "", "!", "new feature"}, + message: "feat!: new feature", + wanted: []string{"feat", "", "!", "new feature"}, }, { - rawMessage: "feat(api): new feature", - wanted: []string{"feat", "api", "", "new feature"}, + message: "feat(api): new feature", + wanted: []string{"feat", "api", "", "new feature"}, }, { - rawMessage: "feat(api): a(b): c:", - wanted: []string{"feat", "api", "", "a(b): c:"}, + message: "feat(api): a(b): c:", + wanted: []string{"feat", "api", "", "a(b): c:"}, }, { - rawMessage: "feat(new cool-api): feature", - wanted: []string{"feat", "new cool-api", "", "feature"}, + message: "feat(new cool-api): feature", + wanted: []string{"feat", "new cool-api", "", "feature"}, }, { - rawMessage: "feat(😅): cool", - wanted: []string{"feat", "😅", "", "cool"}, + message: "feat(😅): cool", + wanted: []string{"feat", "😅", "", "cool"}, }, { - rawMessage: "this-is-also(valid): cool", - wanted: []string{"this-is-also", "valid", "", "cool"}, + message: "this-is-also(valid): cool", + wanted: []string{"this-is-also", "valid", "", "cool"}, }, { - rawMessage: "🚀(🦄): emojis!", - wanted: []string{"🚀", "🦄", "", "emojis!"}, + message: "🚀(🦄): emojis!", + wanted: []string{"🚀", "🦄", "", "emojis!"}, }, // invalid messages { - rawMessage: "feat (new api): feature", - wanted: nil, + message: "feat (new api): feature", + wanted: nil, }, { - rawMessage: "feat((x)): test", - wanted: nil, + message: "feat((x)): test", + wanted: nil, }, { - rawMessage: "feat:test", - wanted: nil, + message: "feat:test", + wanted: nil, }, } for _, tc := range testCases { - t.Run(fmt.Sprintf("CommitPattern: %s", tc.rawMessage), func(t *testing.T) { - rawMessageLines := strings.Split(tc.rawMessage, "\n") - found := commitPattern.FindAllStringSubmatch(rawMessageLines[0], -1) + t.Run(fmt.Sprintf("CommitPattern: %s", tc.message), func(t *testing.T) { + found := commitPattern.FindAllStringSubmatch(tc.message, -1) if len(tc.wanted) == 0 { require.Len(t, found, 0) return