Skip to content

Commit

Permalink
feat: add conventional commit breaking change support
Browse files Browse the repository at this point in the history
Conventional Commit standard allows for "!" immediately following type
and preceding scope to indicate a breaking change. Conform fails against
this commit style, so this change allows such commit messages to pass
policy check.

Signed-off-by: Joey Espinosa <[email protected]>
  • Loading branch information
particledecay authored and andrewrynhard committed Apr 30, 2021
1 parent 0e3a28c commit c23e2fc
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 7 deletions.
19 changes: 12 additions & 7 deletions internal/policy/commit/check_conventional_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Conventional struct {

// HeaderRegex is the regular expression used for Conventional Commits
// 1.0.0-beta.1.
var HeaderRegex = regexp.MustCompile(`^(\w*)(\(([^)]+)\))?:\s{1}(.*)($|\n{2})`)
var HeaderRegex = regexp.MustCompile(`^(\w*)(\!)?(\(([^)]+)\))?:\s{1}(.*)($|\n{2})`)

const (
// TypeFeat is a commit of the type fix patches a bug in your codebase
Expand Down Expand Up @@ -66,17 +66,22 @@ func (c Commit) ValidateConventionalCommit() policy.Check {
check := &ConventionalCommitCheck{}
groups := parseHeader(c.msg)

if len(groups) != 6 {
if len(groups) != 7 {
check.errors = append(check.errors, errors.Errorf("Invalid conventional commits format: %q", c.msg))

return check
}

// conventional commit sections
ccType := groups[1]
ccScope := groups[4]
ccDesc := groups[5]

c.Conventional.Types = append(c.Conventional.Types, TypeFeat, TypeFix)
typeIsValid := false

for _, t := range c.Conventional.Types {
if t == groups[1] {
if t == ccType {
typeIsValid = true
}
}
Expand All @@ -88,12 +93,12 @@ func (c Commit) ValidateConventionalCommit() policy.Check {
}

// Scope is optional.
if groups[3] != "" {
if ccScope != "" {
scopeIsValid := false

for _, scope := range c.Conventional.Scopes {
re := regexp.MustCompile(scope)
if re.Match([]byte(groups[3])) {
if re.Match([]byte(ccScope)) {
scopeIsValid = true

break
Expand All @@ -112,11 +117,11 @@ func (c Commit) ValidateConventionalCommit() policy.Check {
c.Conventional.DescriptionLength = 72
}

if len(groups[4]) <= c.Conventional.DescriptionLength && len(groups[4]) != 0 {
if len(ccDesc) <= c.Conventional.DescriptionLength && len(ccDesc) != 0 {
return check
}

check.errors = append(check.errors, errors.Errorf("Invalid description: %s", groups[4]))
check.errors = append(check.errors, errors.Errorf("Invalid description: %s", ccDesc))

return check
}
Expand Down
22 changes: 22 additions & 0 deletions internal/policy/commit/commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ func TestConventionalCommitPolicy(t *testing.T) {
CreateCommit: createValidCommit,
ExpectValid: true,
},
{
Name: "Breaking",
CreateCommit: createBreakingCommit,
ExpectValid: true,
},
{
Name: "InvalidBreaking",
CreateCommit: createInvalidBreakingCommit,
ExpectValid: false,
},
{
Name: "Invalid",
CreateCommit: createInvalidCommit,
Expand Down Expand Up @@ -332,6 +342,18 @@ func createValidCommit() error {
return err
}

func createBreakingCommit() error {
_, err := exec.Command("git", "-c", "user.name='test'", "-c", "user.email='[email protected]'", "commit", "-m", "feat!: description").Output()

return err
}

func createInvalidBreakingCommit() error {
_, err := exec.Command("git", "-c", "user.name='test'", "-c", "user.email='[email protected]'", "commit", "-m", "feat$: description").Output()

return err
}

func createInvalidCommit() error {
_, err := exec.Command("git", "-c", "user.name='test'", "-c", "user.email='[email protected]'", "commit", "-m", "invalid commit").Output()

Expand Down

0 comments on commit c23e2fc

Please sign in to comment.