All checks were successful
Lint Pull Request / Lint Pr Title (pull_request) Successful in 9s
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package validation
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
func ValidateConventionalCommit(commit string) error {
|
|
// Regex to match the commit format
|
|
// type(scope)!: description
|
|
// or
|
|
// type!: description
|
|
// or
|
|
// type: description
|
|
re := regexp.MustCompile(`^(?P<type>[a-z]+)(?P<scope>\([a-z]+\))?(?P<breaking>!)?: (?P<description>[a-z].+)$`)
|
|
match := re.FindStringSubmatch(commit)
|
|
|
|
if len(match) == 0 {
|
|
return fmt.Errorf("Invalid PR title")
|
|
}
|
|
|
|
typeIndex := re.SubexpIndex("type")
|
|
scopeIndex := re.SubexpIndex("scope")
|
|
breakingIndex := re.SubexpIndex("breaking")
|
|
descriptionIndex := re.SubexpIndex("description")
|
|
|
|
commitType := match[typeIndex]
|
|
scope := match[scopeIndex]
|
|
breaking := match[breakingIndex]
|
|
description := match[descriptionIndex]
|
|
|
|
// Type MUST be lowercase
|
|
if commitType != strings.ToLower(commitType) {
|
|
return fmt.Errorf("type must be lowercase")
|
|
}
|
|
|
|
// Description MUST start with lowercase
|
|
if description != strings.ToLower(description) {
|
|
return fmt.Errorf("description must start with lowercase")
|
|
}
|
|
|
|
// Scope MUST be lowercase
|
|
if scope != "" && scope != strings.ToLower(scope) {
|
|
return fmt.Errorf("scope must be lowercase")
|
|
}
|
|
|
|
// Check for breaking change indicator
|
|
hasBreakingChangeFooter := strings.Contains(commit, "BREAKING CHANGE:")
|
|
if breaking == "!" && hasBreakingChangeFooter {
|
|
return fmt.Errorf("breaking change indicator and footer are mutually exclusive")
|
|
}
|
|
|
|
lines := strings.Split(commit, "\n")
|
|
if len(lines) > 1 {
|
|
body := strings.Join(lines[1:], "\n")
|
|
// Check if body is separated from description by a blank line
|
|
if !strings.HasPrefix(body, "\n") {
|
|
return fmt.Errorf("body must be separated from description by a blank line")
|
|
}
|
|
}
|
|
|
|
// Check for footers
|
|
footerRegex := regexp.MustCompile(`(?m)^(?P<token>[A-Za-z-]+|BREAKING CHANGE): (?P<value>.*)$`)
|
|
footerMatches := footerRegex.FindAllStringSubmatch(commit, -1)
|
|
|
|
for _, footerMatch := range footerMatches {
|
|
tokenIndex := footerRegex.SubexpIndex("token")
|
|
token := footerMatch[tokenIndex]
|
|
|
|
// BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE
|
|
if token == "BREAKING-CHANGE" {
|
|
continue
|
|
}
|
|
|
|
// Token MUST use - in place of whitespace characters, except for BREAKING CHANGE
|
|
if token != "BREAKING CHANGE" && strings.Contains(token, " ") {
|
|
return fmt.Errorf("footer token must use - in place of whitespace characters")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|