mirror of
https://github.com/thegeeklab/git-sv.git
synced 2024-11-21 22:10:39 +00:00
refactor: create branches config
BREAKING CHANGE: remove BRANCH_ISSUE_REGEX varenv
This commit is contained in:
parent
0e7438b3a9
commit
f6debee45e
@ -20,7 +20,8 @@ type Config struct {
|
||||
CommitMessageTypes []string `envconfig:"COMMIT_MESSAGE_TYPES" default:"build,ci,chore,docs,feat,fix,perf,refactor,revert,style,test"`
|
||||
IssueKeyName string `envconfig:"ISSUE_KEY_NAME" default:"jira"`
|
||||
IssueRegex string `envconfig:"ISSUE_REGEX" default:"[A-Z]+-[0-9]+"`
|
||||
BranchIssueRegex string `envconfig:"BRANCH_ISSUE_REGEX" default:"^([a-z]+\\/)?([A-Z]+-[0-9]+)(-.*)?"` //TODO breaking change: use issue regex instead of duplicating issue regex
|
||||
BranchIssuePrefixRegex string `envconfig:"BRANCH_ISSUE_PREFIX_REGEX" default:"([a-z]+\\/)?"`
|
||||
BranchIssueSuffixRegex string `envconfig:"BRANCH_ISSUE_SUFFIX_REGEX" default:"(-.*)?"`
|
||||
}
|
||||
|
||||
func loadConfig() Config {
|
||||
|
@ -21,13 +21,20 @@ func main() {
|
||||
Types: cfg.CommitMessageTypes,
|
||||
Scope: sv.CommitMessageScopeConfig{},
|
||||
Footer: map[string]sv.CommitMessageFooterConfig{
|
||||
"issue": {Key: cfg.IssueIDPrefixes[0], KeySynonyms: cfg.IssueIDPrefixes[1:], Regex: cfg.IssueRegex},
|
||||
"issue": {Key: cfg.IssueIDPrefixes[0], KeySynonyms: cfg.IssueIDPrefixes[1:]},
|
||||
"breaking-change": {Key: cfg.BreakingChangePrefixes[0], KeySynonyms: cfg.BreakingChangePrefixes[1:]},
|
||||
},
|
||||
Issue: sv.CommitMessageIssueConfig{Regex: cfg.IssueRegex},
|
||||
}
|
||||
branchesConfig := sv.BranchesConfig{
|
||||
Skip: cfg.ValidateMessageSkipBranches,
|
||||
ExpectIssue: true,
|
||||
PrefixRegex: cfg.BranchIssuePrefixRegex,
|
||||
SuffixRegex: cfg.BranchIssueSuffixRegex,
|
||||
}
|
||||
////
|
||||
|
||||
messageProcessor := sv.NewMessageProcessor(commitMessageCfg, cfg.ValidateMessageSkipBranches, cfg.BranchIssueRegex)
|
||||
messageProcessor := sv.NewMessageProcessor(commitMessageCfg, branchesConfig)
|
||||
git := sv.NewGit(messageProcessor, cfg.TagPattern)
|
||||
semverProcessor := sv.NewSemVerCommitsProcessor(cfg.IncludeUnknownTypeAsPatch, cfg.MajorVersionTypes, cfg.MinorVersionTypes, cfg.PatchVersionTypes)
|
||||
releasenotesProcessor := sv.NewReleaseNoteProcessor(cfg.ReleaseNotesTags)
|
||||
|
15
sv/config.go
15
sv/config.go
@ -5,6 +5,7 @@ type CommitMessageConfig struct {
|
||||
Types []string
|
||||
Scope CommitMessageScopeConfig
|
||||
Footer map[string]CommitMessageFooterConfig
|
||||
Issue CommitMessageIssueConfig
|
||||
}
|
||||
|
||||
// IssueConfig config for issue.
|
||||
@ -33,6 +34,18 @@ type CommitMessageScopeConfig struct {
|
||||
type CommitMessageFooterConfig struct {
|
||||
Key string
|
||||
KeySynonyms []string
|
||||
Regex string
|
||||
UseHash bool
|
||||
}
|
||||
|
||||
// CommitMessageIssueConfig issue preferences.
|
||||
type CommitMessageIssueConfig struct {
|
||||
Regex string
|
||||
}
|
||||
|
||||
// BranchesConfig branches preferences.
|
||||
type BranchesConfig struct {
|
||||
PrefixRegex string
|
||||
SuffixRegex string
|
||||
ExpectIssue bool
|
||||
Skip []string
|
||||
}
|
||||
|
@ -56,41 +56,39 @@ type MessageProcessor interface {
|
||||
}
|
||||
|
||||
// NewMessageProcessor MessageProcessorImpl constructor
|
||||
func NewMessageProcessor(cfg CommitMessageConfig, skipBranches []string, branchIssueRegex string) *MessageProcessorImpl {
|
||||
func NewMessageProcessor(mcfg CommitMessageConfig, bcfg BranchesConfig) *MessageProcessorImpl {
|
||||
return &MessageProcessorImpl{
|
||||
cfg: cfg,
|
||||
skipBranches: skipBranches,
|
||||
branchIssueRegex: branchIssueRegex,
|
||||
messageCfg: mcfg,
|
||||
branchesCfg: bcfg,
|
||||
}
|
||||
}
|
||||
|
||||
// MessageProcessorImpl process validate message hook.
|
||||
type MessageProcessorImpl struct {
|
||||
cfg CommitMessageConfig
|
||||
skipBranches []string
|
||||
branchIssueRegex string
|
||||
messageCfg CommitMessageConfig
|
||||
branchesCfg BranchesConfig
|
||||
}
|
||||
|
||||
// SkipBranch check if branch should be ignored.
|
||||
func (p MessageProcessorImpl) SkipBranch(branch string) bool {
|
||||
return contains(branch, p.skipBranches)
|
||||
return contains(branch, p.branchesCfg.Skip)
|
||||
}
|
||||
|
||||
// Validate commit message.
|
||||
func (p MessageProcessorImpl) Validate(message string) error {
|
||||
valid, err := regexp.MatchString("^("+strings.Join(p.cfg.Types, "|")+")(\\(.+\\))?!?: .*$", firstLine(message))
|
||||
valid, err := regexp.MatchString("^("+strings.Join(p.messageCfg.Types, "|")+")(\\(.+\\))?!?: .*$", firstLine(message))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !valid {
|
||||
return fmt.Errorf("message should contain type: %v, and should be valid according with conventional commits", p.cfg.Types)
|
||||
return fmt.Errorf("message should contain type: %v, and should be valid according with conventional commits", p.messageCfg.Types)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enhance add metadata on commit message.
|
||||
func (p MessageProcessorImpl) Enhance(branch string, message string) (string, error) {
|
||||
if p.branchIssueRegex == "" || p.cfg.IssueConfig().Key == "" || hasIssueID(message, p.cfg.IssueConfig().Key) {
|
||||
if !p.branchesCfg.ExpectIssue || p.messageCfg.IssueConfig().Key == "" || hasIssueID(message, p.messageCfg.IssueConfig().Key) {
|
||||
return "", nil //enhance disabled
|
||||
}
|
||||
|
||||
@ -102,9 +100,9 @@ func (p MessageProcessorImpl) Enhance(branch string, message string) (string, er
|
||||
return "", fmt.Errorf("could not find issue id using configured regex")
|
||||
}
|
||||
|
||||
footer := fmt.Sprintf("%s: %s", p.cfg.IssueConfig().Key, issue)
|
||||
footer := fmt.Sprintf("%s: %s", p.messageCfg.IssueConfig().Key, issue)
|
||||
|
||||
if !hasFooter(message, p.cfg.Footer[breakingKey].Key) {
|
||||
if !hasFooter(message, p.messageCfg.Footer[breakingKey].Key) {
|
||||
return "\n" + footer, nil
|
||||
}
|
||||
|
||||
@ -113,9 +111,10 @@ func (p MessageProcessorImpl) Enhance(branch string, message string) (string, er
|
||||
|
||||
// IssueID try to extract issue id from branch, return empty if not found.
|
||||
func (p MessageProcessorImpl) IssueID(branch string) (string, error) {
|
||||
r, err := regexp.Compile(p.branchIssueRegex)
|
||||
rstr := fmt.Sprintf("^%s(%s)%s$", p.branchesCfg.PrefixRegex, p.messageCfg.Issue.Regex, p.branchesCfg.SuffixRegex)
|
||||
r, err := regexp.Compile(rstr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not compile issue regex: %s, error: %v", p.branchIssueRegex, err.Error())
|
||||
return "", fmt.Errorf("could not compile issue regex: %s, error: %v", rstr, err.Error())
|
||||
}
|
||||
|
||||
groups := r.FindStringSubmatch(branch)
|
||||
@ -137,13 +136,13 @@ func (p MessageProcessorImpl) Format(msg CommitMessage) (string, string, string)
|
||||
|
||||
var footer strings.Builder
|
||||
if msg.BreakingMessage() != "" {
|
||||
footer.WriteString(fmt.Sprintf("%s: %s", p.cfg.BreakingChangeConfig().Key, msg.BreakingMessage()))
|
||||
footer.WriteString(fmt.Sprintf("%s: %s", p.messageCfg.BreakingChangeConfig().Key, msg.BreakingMessage()))
|
||||
}
|
||||
if issue, exists := msg.Metadata[issueKey]; exists {
|
||||
if footer.Len() > 0 {
|
||||
footer.WriteString("\n")
|
||||
}
|
||||
footer.WriteString(fmt.Sprintf("%s: %s", p.cfg.IssueConfig().Key, issue))
|
||||
footer.WriteString(fmt.Sprintf("%s: %s", p.messageCfg.IssueConfig().Key, issue))
|
||||
}
|
||||
|
||||
return header.String(), msg.Body, footer.String()
|
||||
@ -154,7 +153,7 @@ func (p MessageProcessorImpl) Parse(subject, body string) CommitMessage {
|
||||
commitType, scope, description, hasBreakingChange := parseSubjectMessage(subject)
|
||||
|
||||
metadata := make(map[string]string)
|
||||
for key, mdCfg := range p.cfg.Footer {
|
||||
for key, mdCfg := range p.messageCfg.Footer {
|
||||
prefixes := append([]string{mdCfg.Key}, mdCfg.KeySynonyms...)
|
||||
for _, prefix := range prefixes {
|
||||
if tagValue := extractFooterMetadata(prefix, body, mdCfg.UseHash); tagValue != "" {
|
||||
|
@ -5,20 +5,23 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var cfg = CommitMessageConfig{
|
||||
var ccfg = CommitMessageConfig{
|
||||
Types: []string{"feat", "fix"},
|
||||
Scope: CommitMessageScopeConfig{},
|
||||
Footer: map[string]CommitMessageFooterConfig{
|
||||
"issue": {Key: "jira", KeySynonyms: []string{"Jira"}, Regex: "[A-Z]+-[0-9]+"},
|
||||
"issue": {Key: "jira", KeySynonyms: []string{"Jira"}},
|
||||
"breaking-change": {Key: "BREAKING CHANGE", KeySynonyms: []string{"BREAKING CHANGES"}},
|
||||
"refs": {Key: "Refs", UseHash: true},
|
||||
},
|
||||
Issue: CommitMessageIssueConfig{Regex: "[A-Z]+-[0-9]+"},
|
||||
}
|
||||
|
||||
const (
|
||||
branchIssueRegex = "^([a-z]+\\/)?([A-Z]+-[0-9]+)(-.*)?"
|
||||
issueRegex = "[A-Z]+-[0-9]+"
|
||||
)
|
||||
var bcfg = BranchesConfig{
|
||||
ExpectIssue: true,
|
||||
PrefixRegex: "([a-z]+\\/)?",
|
||||
SuffixRegex: "(-.*)?",
|
||||
Skip: []string{"develop", "master"},
|
||||
}
|
||||
|
||||
// messages samples start
|
||||
var fullMessage = `fix: correct minor typos in code
|
||||
@ -57,7 +60,7 @@ BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.`
|
||||
// multiline samples end
|
||||
|
||||
func TestMessageProcessorImpl_Validate(t *testing.T) {
|
||||
p := NewMessageProcessor(cfg, []string{"develop", "master"}, branchIssueRegex)
|
||||
p := NewMessageProcessor(ccfg, bcfg)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -90,7 +93,7 @@ func TestMessageProcessorImpl_Validate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageProcessorImpl_Enhance(t *testing.T) {
|
||||
p := NewMessageProcessor(cfg, []string{"develop", "master"}, branchIssueRegex)
|
||||
p := NewMessageProcessor(ccfg, bcfg)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -123,7 +126,7 @@ func TestMessageProcessorImpl_Enhance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageProcessorImpl_IssueID(t *testing.T) {
|
||||
p := NewMessageProcessor(cfg, []string{"develop", "master"}, branchIssueRegex)
|
||||
p := NewMessageProcessor(ccfg, bcfg)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -251,7 +254,7 @@ Jira: JIRA-999
|
||||
Refs #123`
|
||||
|
||||
func TestMessageProcessorImpl_Parse(t *testing.T) {
|
||||
p := NewMessageProcessor(cfg, []string{"develop", "master"}, branchIssueRegex)
|
||||
p := NewMessageProcessor(ccfg, bcfg)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -278,7 +281,7 @@ func TestMessageProcessorImpl_Parse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageProcessorImpl_Format(t *testing.T) {
|
||||
p := NewMessageProcessor(cfg, []string{"develop", "master"}, branchIssueRegex)
|
||||
p := NewMessageProcessor(ccfg, bcfg)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
Loading…
Reference in New Issue
Block a user