0
0
mirror of https://github.com/thegeeklab/git-sv.git synced 2024-11-24 21:20:40 +00:00

feat: use skip-detached to skip validation on detached branches

issue: #11
This commit is contained in:
Beatriz Vieira 2021-03-04 00:42:51 -03:00
parent 831f3a3723
commit 48620a776d
8 changed files with 80 additions and 16 deletions

View File

@ -97,6 +97,7 @@ branches: # git branches config
- master - master
- main - main
- developer - developer
skip-detached: false # set true if a detached branch should be ignored on commit message validation
commit-message: commit-message:
types: # supported commit types types: # supported commit types

View File

@ -62,6 +62,7 @@ func loadConfig(filepath string) (Config, error) {
} }
func defaultConfig() Config { func defaultConfig() Config {
skipDetached := false
return Config{ return Config{
Version: "1.0", Version: "1.0",
Versioning: sv.VersioningConfig{ Versioning: sv.VersioningConfig{
@ -77,6 +78,7 @@ func defaultConfig() Config {
SuffixRegex: "(-.*)?", SuffixRegex: "(-.*)?",
DisableIssue: false, DisableIssue: false,
Skip: []string{"master", "main", "developer"}, Skip: []string{"master", "main", "developer"},
SkipDetached: &skipDetached,
}, },
CommitMessage: sv.CommitMessageConfig{ CommitMessage: sv.CommitMessageConfig{
Types: []string{"build", "ci", "chore", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"}, Types: []string{"build", "ci", "chore", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"},

View File

@ -371,8 +371,10 @@ func changelogHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnP
func validateCommitMessageHandler(git sv.Git, messageProcessor sv.MessageProcessor) func(c *cli.Context) error { func validateCommitMessageHandler(git sv.Git, messageProcessor sv.MessageProcessor) func(c *cli.Context) error {
return func(c *cli.Context) error { return func(c *cli.Context) error {
branch := git.Branch() branch := git.Branch()
if messageProcessor.SkipBranch(branch) { detached, derr := git.IsDetached()
warn("commit message validation skipped, branch in ignore list...")
if messageProcessor.SkipBranch(branch, derr == nil && detached) {
warn("commit message validation skipped, branch in ignore list or detached...")
return nil return nil
} }

View File

@ -4,6 +4,7 @@ import (
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"sv4git/sv" "sv4git/sv"
"github.com/imdario/mergo" "github.com/imdario/mergo"
@ -27,7 +28,7 @@ func main() {
if envCfg.Home != "" { if envCfg.Home != "" {
if homeCfg, err := loadConfig(filepath.Join(envCfg.Home, configFilename)); err == nil { if homeCfg, err := loadConfig(filepath.Join(envCfg.Home, configFilename)); err == nil {
if merr := mergo.Merge(&cfg, homeCfg, mergo.WithOverride); merr != nil { if merr := mergo.Merge(&cfg, homeCfg, mergo.WithOverride, mergo.WithTransformers(&nullTransformer{})); merr != nil {
log.Fatal(merr) log.Fatal(merr)
} }
} }
@ -39,7 +40,7 @@ func main() {
} }
if repoCfg, err := loadConfig(filepath.Join(repoPath, repoConfigFilename)); err == nil { if repoCfg, err := loadConfig(filepath.Join(repoPath, repoConfigFilename)); err == nil {
if merr := mergo.Merge(&cfg, repoCfg, mergo.WithOverride); merr != nil { if merr := mergo.Merge(&cfg, repoCfg, mergo.WithOverride, mergo.WithTransformers(&nullTransformer{})); merr != nil {
log.Fatal(merr) log.Fatal(merr)
} }
if len(repoCfg.ReleaseNotes.Headers) > 0 { // mergo is merging maps, headers will be overwritten if len(repoCfg.ReleaseNotes.Headers) > 0 { // mergo is merging maps, headers will be overwritten
@ -159,3 +160,18 @@ func main() {
log.Fatal(apperr) log.Fatal(apperr)
} }
} }
type nullTransformer struct {
}
func (t *nullTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ.Kind() == reflect.Ptr {
return func(dst, src reflect.Value) error {
if dst.CanSet() && !src.IsNil() {
dst.Set(src)
}
return nil
}
}
return nil
}

View File

@ -43,6 +43,7 @@ type BranchesConfig struct {
SuffixRegex string `yaml:"suffix"` SuffixRegex string `yaml:"suffix"`
DisableIssue bool `yaml:"disable-issue"` DisableIssue bool `yaml:"disable-issue"`
Skip []string `yaml:"skip"` Skip []string `yaml:"skip"`
SkipDetached *bool `yaml:"skip-detached"`
} }
// ==== Versioning ==== // ==== Versioning ====

View File

@ -3,6 +3,7 @@ package sv
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"errors"
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
@ -25,6 +26,7 @@ type Git interface {
Tag(version semver.Version) error Tag(version semver.Version) error
Tags() ([]GitTag, error) Tags() ([]GitTag, error)
Branch() string Branch() string
IsDetached() (bool, error)
} }
// GitCommitLog description of a single commit log // GitCommitLog description of a single commit log
@ -154,6 +156,19 @@ func (GitImpl) Branch() string {
return strings.TrimSpace(strings.Trim(string(out), "\n")) return strings.TrimSpace(strings.Trim(string(out), "\n"))
} }
// IsDetached check if is detached.
func (GitImpl) IsDetached() (bool, error) {
cmd := exec.Command("git", "symbolic-ref", "-q", "HEAD")
out, err := cmd.CombinedOutput()
if output := string(out); err != nil { //-q: do not issue an error message if the <name> is not a symbolic ref, but a detached HEAD; instead exit with non-zero status silently.
if output == "" {
return true, nil
}
return false, errors.New(output)
}
return false, nil
}
func parseTagsOutput(input string) ([]GitTag, error) { func parseTagsOutput(input string) ([]GitTag, error) {
scanner := bufio.NewScanner(strings.NewReader(input)) scanner := bufio.NewScanner(strings.NewReader(input))
var result []GitTag var result []GitTag

View File

@ -47,7 +47,7 @@ func (m CommitMessage) BreakingMessage() string {
// MessageProcessor interface. // MessageProcessor interface.
type MessageProcessor interface { type MessageProcessor interface {
SkipBranch(branch string) bool SkipBranch(branch string, detached bool) bool
Validate(message string) error Validate(message string) error
Enhance(branch string, message string) (string, error) Enhance(branch string, message string) (string, error)
IssueID(branch string) (string, error) IssueID(branch string) (string, error)
@ -70,8 +70,8 @@ type MessageProcessorImpl struct {
} }
// SkipBranch check if branch should be ignored. // SkipBranch check if branch should be ignored.
func (p MessageProcessorImpl) SkipBranch(branch string) bool { func (p MessageProcessorImpl) SkipBranch(branch string, detached bool) bool {
return contains(branch, p.branchesCfg.Skip) return contains(branch, p.branchesCfg.Skip) || (p.branchesCfg.SkipDetached != nil && *p.branchesCfg.SkipDetached && detached)
} }
// Validate commit message. // Validate commit message.

View File

@ -25,10 +25,13 @@ var ccfgWithScope = CommitMessageConfig{
Issue: CommitMessageIssueConfig{Regex: "[A-Z]+-[0-9]+"}, Issue: CommitMessageIssueConfig{Regex: "[A-Z]+-[0-9]+"},
} }
var bcfg = BranchesConfig{ func newBranchCfg(skipDetached bool) BranchesConfig {
PrefixRegex: "([a-z]+\\/)?", return BranchesConfig{
SuffixRegex: "(-.*)?", PrefixRegex: "([a-z]+\\/)?",
Skip: []string{"develop", "master"}, SuffixRegex: "(-.*)?",
Skip: []string{"develop", "master"},
SkipDetached: &skipDetached,
}
} }
// messages samples start // messages samples start
@ -67,6 +70,30 @@ BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.`
// multiline samples end // multiline samples end
func TestMessageProcessorImpl_SkipBranch(t *testing.T) {
tests := []struct {
name string
bcfg BranchesConfig
branch string
detached bool
want bool
}{
{"normal branch", newBranchCfg(false), "JIRA-123", false, false},
{"dont ignore detached branch", newBranchCfg(false), "JIRA-123", true, false},
{"ignore branch on skip list", newBranchCfg(false), "master", false, true},
{"ignore detached branch", newBranchCfg(true), "JIRA-123", true, true},
{"null skip detached", BranchesConfig{Skip: []string{}}, "JIRA-123", true, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := NewMessageProcessor(ccfg, tt.bcfg)
if got := p.SkipBranch(tt.branch, tt.detached); got != tt.want {
t.Errorf("MessageProcessorImpl.SkipBranch() = %v, want %v", got, tt.want)
}
})
}
}
func TestMessageProcessorImpl_Validate(t *testing.T) { func TestMessageProcessorImpl_Validate(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -94,7 +121,7 @@ func TestMessageProcessorImpl_Validate(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
p := NewMessageProcessor(tt.cfg, bcfg) p := NewMessageProcessor(tt.cfg, newBranchCfg(false))
if err := p.Validate(tt.message); (err != nil) != tt.wantErr { if err := p.Validate(tt.message); (err != nil) != tt.wantErr {
t.Errorf("MessageProcessorImpl.Validate() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("MessageProcessorImpl.Validate() error = %v, wantErr %v", err, tt.wantErr)
} }
@ -103,7 +130,7 @@ func TestMessageProcessorImpl_Validate(t *testing.T) {
} }
func TestMessageProcessorImpl_Enhance(t *testing.T) { func TestMessageProcessorImpl_Enhance(t *testing.T) {
p := NewMessageProcessor(ccfg, bcfg) p := NewMessageProcessor(ccfg, newBranchCfg(false))
tests := []struct { tests := []struct {
name string name string
@ -136,7 +163,7 @@ func TestMessageProcessorImpl_Enhance(t *testing.T) {
} }
func TestMessageProcessorImpl_IssueID(t *testing.T) { func TestMessageProcessorImpl_IssueID(t *testing.T) {
p := NewMessageProcessor(ccfg, bcfg) p := NewMessageProcessor(ccfg, newBranchCfg(false))
tests := []struct { tests := []struct {
name string name string
@ -248,7 +275,7 @@ Jira: JIRA-999
Refs #123` Refs #123`
func TestMessageProcessorImpl_Parse(t *testing.T) { func TestMessageProcessorImpl_Parse(t *testing.T) {
p := NewMessageProcessor(ccfg, bcfg) p := NewMessageProcessor(ccfg, newBranchCfg(false))
tests := []struct { tests := []struct {
name string name string
@ -275,7 +302,7 @@ func TestMessageProcessorImpl_Parse(t *testing.T) {
} }
func TestMessageProcessorImpl_Format(t *testing.T) { func TestMessageProcessorImpl_Format(t *testing.T) {
p := NewMessageProcessor(ccfg, bcfg) p := NewMessageProcessor(ccfg, newBranchCfg(false))
tests := []struct { tests := []struct {
name string name string