0
0
mirror of https://github.com/thegeeklab/git-sv.git synced 2024-11-21 22:10:39 +00:00

Merge pull request #28 from bvieira/lint

CI: add golangci to github actions
This commit is contained in:
Beatriz Vieira 2021-07-31 17:56:29 -03:00 committed by GitHub
commit d76920bb5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 146 additions and 104 deletions

View File

@ -8,6 +8,16 @@ on:
jobs: jobs:
golangci:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: latest
build: build:
name: Build name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -16,7 +26,7 @@ jobs:
- name: Set up Go 1.x - name: Set up Go 1.x
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: ^1.13 go-version: ^1.16
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory

View File

@ -1,26 +1,35 @@
linters: linters:
# disable-all: true enable:
# enable: - tagliatelle
# - megacheck
# - govet
enable-all: true
disable:
- scopelint
- paralleltest
- staticcheck
- noctx
- wsl
- lll
- forbidigo
# - prealloc
# presets:
# - bugs
# - unused
# bugs|comment|complexity|error|format|import|metalinter|module|performance|sql|style|test|unused
fast: true
run: run:
skip-dirs: skip-dirs:
- build - build
- artifacts - artifacts
linters-settings:
tagliatelle:
case:
use-field-name: true
rules:
json: camel
yaml: kebab
xml: camel
bson: camel
avro: snake
mapstructure: kebab
issues:
exclude-rules:
- path: _test\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
- gochecknoglobals
- testpackage
- path: cmd/git-sv/main.go
linters:
- gochecknoglobals
- funlen

View File

@ -10,13 +10,12 @@ import (
"strings" "strings"
"github.com/bvieira/sv4git/sv" "github.com/bvieira/sv4git/sv"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"github.com/kelseyhightower/envconfig" "github.com/kelseyhightower/envconfig"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
// EnvConfig env vars for cli configuration // EnvConfig env vars for cli configuration.
type EnvConfig struct { type EnvConfig struct {
Home string `envconfig:"SV4GIT_HOME" default:""` Home string `envconfig:"SV4GIT_HOME" default:""`
} }
@ -30,7 +29,7 @@ func loadEnvConfig() EnvConfig {
return c return c
} }
// Config cli yaml config // Config cli yaml config.
type Config struct { type Config struct {
Version string `yaml:"version"` Version string `yaml:"version"`
Versioning sv.VersioningConfig `yaml:"versioning"` Versioning sv.VersioningConfig `yaml:"versioning"`
@ -77,8 +76,8 @@ func defaultConfig() Config {
Tag: sv.TagConfig{Pattern: "%d.%d.%d"}, Tag: sv.TagConfig{Pattern: "%d.%d.%d"},
ReleaseNotes: sv.ReleaseNotesConfig{Headers: map[string]string{"fix": "Bug Fixes", "feat": "Features", "breaking-change": "Breaking Changes"}}, ReleaseNotes: sv.ReleaseNotesConfig{Headers: map[string]string{"fix": "Bug Fixes", "feat": "Features", "breaking-change": "Breaking Changes"}},
Branches: sv.BranchesConfig{ Branches: sv.BranchesConfig{
PrefixRegex: "([a-z]+\\/)?", Prefix: "([a-z]+\\/)?",
SuffixRegex: "(-.*)?", Suffix: "(-.*)?",
DisableIssue: false, DisableIssue: false,
Skip: []string{"master", "main", "developer"}, Skip: []string{"master", "main", "developer"},
SkipDetached: &skipDetached, SkipDetached: &skipDetached,

View File

@ -10,9 +10,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/bvieira/sv4git/sv"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/bvieira/sv4git/sv"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@ -73,7 +72,7 @@ func nextVersionHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) f
} }
} }
func commitLogHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) func(c *cli.Context) error { func commitLogHandler(git sv.Git) func(c *cli.Context) error {
return func(c *cli.Context) error { return func(c *cli.Context) error {
var commits []sv.GitCommitLog var commits []sv.GitCommitLog
var err error var err error
@ -149,8 +148,11 @@ func commitNotesHandler(git sv.Git, rnProcessor sv.ReleaseNoteProcessor, outputF
date, _ = time.Parse("2006-01-02", commits[0].Date) date, _ = time.Parse("2006-01-02", commits[0].Date)
} }
releasenote := rnProcessor.Create(nil, date, commits) output, err := outputFormatter.FormatReleaseNote(rnProcessor.Create(nil, date, commits))
fmt.Println(outputFormatter.FormatReleaseNote(releasenote)) if err != nil {
return fmt.Errorf("could not format release notes, message: %v", err)
}
fmt.Println(output)
return nil return nil
} }
} }
@ -163,7 +165,7 @@ func releaseNotesHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor,
var err error var err error
if tag := c.String("t"); tag != "" { if tag := c.String("t"); tag != "" {
rnVersion, date, commits, err = getTagVersionInfo(git, semverProcessor, tag) rnVersion, date, commits, err = getTagVersionInfo(git, tag)
} else { } else {
// TODO: should generate release notes if version was not updated? // TODO: should generate release notes if version was not updated?
rnVersion, _, date, commits, err = getNextVersionInfo(git, semverProcessor) rnVersion, _, date, commits, err = getNextVersionInfo(git, semverProcessor)
@ -174,12 +176,16 @@ func releaseNotesHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor,
} }
releasenote := rnProcessor.Create(&rnVersion, date, commits) releasenote := rnProcessor.Create(&rnVersion, date, commits)
fmt.Println(outputFormatter.FormatReleaseNote(releasenote)) output, err := outputFormatter.FormatReleaseNote(releasenote)
if err != nil {
return fmt.Errorf("could not format release notes, message: %v", err)
}
fmt.Println(output)
return nil return nil
} }
} }
func getTagVersionInfo(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, tag string) (semver.Version, time.Time, []sv.GitCommitLog, error) { func getTagVersionInfo(git sv.Git, tag string) (semver.Version, time.Time, []sv.GitCommitLog, error) {
tagVersion, err := sv.ToVersion(tag) tagVersion, err := sv.ToVersion(tag)
if err != nil { if err != nil {
return semver.Version{}, time.Time{}, nil, fmt.Errorf("error parsing version: %s from tag, message: %v", tag, err) return semver.Version{}, time.Time{}, nil, fmt.Errorf("error parsing version: %s from tag, message: %v", tag, err)
@ -281,7 +287,7 @@ func getCommitScope(cfg Config, p sv.MessageProcessor, input string, noScope boo
return input, p.ValidateScope(input) return input, p.ValidateScope(input)
} }
func getCommitDescription(cfg Config, p sv.MessageProcessor, input string) (string, error) { func getCommitDescription(p sv.MessageProcessor, input string) (string, error) {
if input == "" { if input == "" {
return promptSubject() return promptSubject()
} }
@ -366,7 +372,7 @@ func commitHandler(cfg Config, git sv.Git, messageProcessor sv.MessageProcessor)
return err return err
} }
subject, err := getCommitDescription(cfg, messageProcessor, inputDescription) subject, err := getCommitDescription(messageProcessor, inputDescription)
if err != nil { if err != nil {
return err return err
} }
@ -443,7 +449,11 @@ func changelogHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnP
releaseNotes = append(releaseNotes, rnProcessor.Create(&currentVer, tag.Date, commits)) releaseNotes = append(releaseNotes, rnProcessor.Create(&currentVer, tag.Date, commits))
} }
fmt.Println(formatter.FormatChangelog(releaseNotes)) output, err := formatter.FormatChangelog(releaseNotes)
if err != nil {
return fmt.Errorf("could not format changelog, message: %v", err)
}
fmt.Println(output)
return nil return nil
} }
@ -455,12 +465,12 @@ func validateCommitMessageHandler(git sv.Git, messageProcessor sv.MessageProcess
detached, derr := git.IsDetached() detached, derr := git.IsDetached()
if messageProcessor.SkipBranch(branch, derr == nil && detached) { if messageProcessor.SkipBranch(branch, derr == nil && detached) {
warn("commit message validation skipped, branch in ignore list or detached...") warnf("commit message validation skipped, branch in ignore list or detached...")
return nil return nil
} }
if source := c.String("source"); source == "merge" { if source := c.String("source"); source == "merge" {
warn("commit message validation skipped, ignoring source: %s...", source) warnf("commit message validation skipped, ignoring source: %s...", source)
return nil return nil
} }
@ -477,7 +487,7 @@ func validateCommitMessageHandler(git sv.Git, messageProcessor sv.MessageProcess
msg, err := messageProcessor.Enhance(branch, commitMessage) msg, err := messageProcessor.Enhance(branch, commitMessage)
if err != nil { if err != nil {
warn("could not enhance commit message, %s", err.Error()) warnf("could not enhance commit message, %s", err.Error())
return nil return nil
} }
if msg == "" { if msg == "" {

View File

@ -2,6 +2,6 @@ package main
import "fmt" import "fmt"
func warn(format string, values ...interface{}) { func warnf(format string, values ...interface{}) {
fmt.Printf("WARN: "+format+"\n", values...) fmt.Printf("WARN: "+format+"\n", values...)
} }

View File

@ -6,11 +6,10 @@ import (
"path/filepath" "path/filepath"
"github.com/bvieira/sv4git/sv" "github.com/bvieira/sv4git/sv"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
// Version for git-sv // Version for git-sv.
var Version = "" var Version = ""
const ( const (
@ -92,7 +91,7 @@ func main() {
Aliases: []string{"cl"}, Aliases: []string{"cl"},
Usage: "list all commit logs according to range as jsons", Usage: "list all commit logs according to range as jsons",
Description: "The range filter is used based on git log filters, check https://git-scm.com/docs/git-log for more info. When flag range is \"tag\" and start is empty, last tag created will be used instead. When flag range is \"date\", if \"end\" is YYYY-MM-DD the range will be inclusive.", Description: "The range filter is used based on git log filters, check https://git-scm.com/docs/git-log for more info. When flag range is \"tag\" and start is empty, last tag created will be used instead. When flag range is \"date\", if \"end\" is YYYY-MM-DD the range will be inclusive.",
Action: commitLogHandler(git, semverProcessor), Action: commitLogHandler(git),
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.StringFlag{Name: "t", Aliases: []string{"tag"}, Usage: "get commit log from a specific tag"}, &cli.StringFlag{Name: "t", Aliases: []string{"tag"}, Usage: "get commit log from a specific tag"},
&cli.StringFlag{Name: "r", Aliases: []string{"range"}, Usage: "type of range of commits, use: tag, date or hash", Value: string(sv.TagRange)}, &cli.StringFlag{Name: "r", Aliases: []string{"range"}, Usage: "type of range of commits, use: tag, date or hash", Value: string(sv.TagRange)},
@ -165,8 +164,7 @@ func main() {
}, },
} }
apperr := app.Run(os.Args) if apperr := app.Run(os.Args); apperr != nil {
if apperr != nil {
log.Fatal(apperr) log.Fatal(apperr)
} }
} }

View File

@ -40,8 +40,8 @@ type CommitMessageIssueConfig struct {
// BranchesConfig branches preferences. // BranchesConfig branches preferences.
type BranchesConfig struct { type BranchesConfig struct {
PrefixRegex string `yaml:"prefix"` Prefix string `yaml:"prefix"`
SuffixRegex string `yaml:"suffix"` Suffix string `yaml:"suffix"`
DisableIssue bool `yaml:"disable-issue"` DisableIssue bool `yaml:"disable-issue"`
Skip []string `yaml:"skip,flow"` Skip []string `yaml:"skip,flow"`
SkipDetached *bool `yaml:"skip-detached"` SkipDetached *bool `yaml:"skip-detached"`

View File

@ -51,8 +51,8 @@ const (
// OutputFormatter output formatter interface. // OutputFormatter output formatter interface.
type OutputFormatter interface { type OutputFormatter interface {
FormatReleaseNote(releasenote ReleaseNote) string FormatReleaseNote(releasenote ReleaseNote) (string, error)
FormatChangelog(releasenotes []ReleaseNote) string FormatChangelog(releasenotes []ReleaseNote) (string, error)
} }
// OutputFormatterImpl formater for release note and changelog. // OutputFormatterImpl formater for release note and changelog.
@ -72,31 +72,35 @@ func NewOutputFormatter() *OutputFormatterImpl {
} }
// FormatReleaseNote format a release note. // FormatReleaseNote format a release note.
func (p OutputFormatterImpl) FormatReleaseNote(releasenote ReleaseNote) string { func (p OutputFormatterImpl) FormatReleaseNote(releasenote ReleaseNote) (string, error) {
var b bytes.Buffer var b bytes.Buffer
p.releasenoteTemplate.Execute(&b, releaseNoteVariables(releasenote)) if err := p.releasenoteTemplate.Execute(&b, releaseNoteVariables(releasenote)); err != nil {
return b.String() return "", err
}
return b.String(), nil
} }
// FormatChangelog format a changelog // FormatChangelog format a changelog.
func (p OutputFormatterImpl) FormatChangelog(releasenotes []ReleaseNote) string { func (p OutputFormatterImpl) FormatChangelog(releasenotes []ReleaseNote) (string, error) {
var templateVars []releaseNoteTemplateVariables templateVars := make([]releaseNoteTemplateVariables, len(releasenotes))
for _, v := range releasenotes { for i, v := range releasenotes {
templateVars = append(templateVars, releaseNoteVariables(v)) templateVars[i] = releaseNoteVariables(v)
} }
var b bytes.Buffer var b bytes.Buffer
p.changelogTemplate.Execute(&b, templateVars) if err := p.changelogTemplate.Execute(&b, templateVars); err != nil {
return b.String() return "", err
}
return b.String(), nil
} }
func releaseNoteVariables(releasenote ReleaseNote) releaseNoteTemplateVariables { func releaseNoteVariables(releasenote ReleaseNote) releaseNoteTemplateVariables {
var date = "" date := ""
if !releasenote.Date.IsZero() { if !releasenote.Date.IsZero() {
date = releasenote.Date.Format("2006-01-02") date = releasenote.Date.Format("2006-01-02")
} }
var version = "" version := ""
if releasenote.Version != nil { if releasenote.Version != nil {
version = releasenote.Version.String() version = releasenote.Version.String()
} }

View File

@ -9,10 +9,13 @@ import (
var dateChangelog = `## v1.0.0 (2020-05-01) var dateChangelog = `## v1.0.0 (2020-05-01)
` `
var emptyDateChangelog = `## v1.0.0 var emptyDateChangelog = `## v1.0.0
` `
var emptyVersionChangelog = `## 2020-05-01 var emptyVersionChangelog = `## 2020-05-01
` `
var fullChangeLog = `## v1.0.0 (2020-05-01) var fullChangeLog = `## v1.0.0 (2020-05-01)
### Features ### Features
@ -36,20 +39,26 @@ func TestOutputFormatterImpl_FormatReleaseNote(t *testing.T) {
date, _ := time.Parse("2006-01-02", "2020-05-01") date, _ := time.Parse("2006-01-02", "2020-05-01")
tests := []struct { tests := []struct {
name string name string
input ReleaseNote input ReleaseNote
want string want string
wantErr bool
}{ }{
{"with date", emptyReleaseNote("1.0.0", date.Truncate(time.Minute)), dateChangelog}, {"with date", emptyReleaseNote("1.0.0", date.Truncate(time.Minute)), dateChangelog, false},
{"without date", emptyReleaseNote("1.0.0", time.Time{}.Truncate(time.Minute)), emptyDateChangelog}, {"without date", emptyReleaseNote("1.0.0", time.Time{}.Truncate(time.Minute)), emptyDateChangelog, false},
{"without version", emptyReleaseNote("", date.Truncate(time.Minute)), emptyVersionChangelog}, {"without version", emptyReleaseNote("", date.Truncate(time.Minute)), emptyVersionChangelog, false},
{"full changelog", fullReleaseNote("1.0.0", date.Truncate(time.Minute)), fullChangeLog}, {"full changelog", fullReleaseNote("1.0.0", date.Truncate(time.Minute)), fullChangeLog, false},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := NewOutputFormatter().FormatReleaseNote(tt.input); got != tt.want { got, err := NewOutputFormatter().FormatReleaseNote(tt.input)
if got != tt.want {
t.Errorf("OutputFormatterImpl.FormatReleaseNote() = %v, want %v", got, tt.want) t.Errorf("OutputFormatterImpl.FormatReleaseNote() = %v, want %v", got, tt.want)
} }
if (err != nil) != tt.wantErr {
t.Errorf("OutputFormatterImpl.FormatReleaseNote() error = %v, wantErr %v", err, tt.wantErr)
}
}) })
} }
} }

View File

@ -18,7 +18,7 @@ const (
endLine = "~~" endLine = "~~"
) )
// Git commands // Git commands.
type Git interface { type Git interface {
LastTag() string LastTag() string
Log(lr LogRange) ([]GitCommitLog, error) Log(lr LogRange) ([]GitCommitLog, error)
@ -29,48 +29,48 @@ type Git interface {
IsDetached() (bool, error) IsDetached() (bool, error)
} }
// GitCommitLog description of a single commit log // GitCommitLog description of a single commit log.
type GitCommitLog struct { type GitCommitLog struct {
Date string `json:"date,omitempty"` Date string `json:"date,omitempty"`
Hash string `json:"hash,omitempty"` Hash string `json:"hash,omitempty"`
Message CommitMessage `json:"message,omitempty"` Message CommitMessage `json:"message,omitempty"`
} }
// GitTag git tag info // GitTag git tag info.
type GitTag struct { type GitTag struct {
Name string Name string
Date time.Time Date time.Time
} }
// LogRangeType type of log range // LogRangeType type of log range.
type LogRangeType string type LogRangeType string
// constants for log range type // constants for log range type.
const ( const (
TagRange LogRangeType = "tag" TagRange LogRangeType = "tag"
DateRange = "date" DateRange LogRangeType = "date"
HashRange = "hash" HashRange LogRangeType = "hash"
) )
// LogRange git log range // LogRange git log range.
type LogRange struct { type LogRange struct {
rangeType LogRangeType rangeType LogRangeType
start string start string
end string end string
} }
// NewLogRange LogRange constructor // NewLogRange LogRange constructor.
func NewLogRange(t LogRangeType, start, end string) LogRange { func NewLogRange(t LogRangeType, start, end string) LogRange {
return LogRange{rangeType: t, start: start, end: end} return LogRange{rangeType: t, start: start, end: end}
} }
// GitImpl git command implementation // GitImpl git command implementation.
type GitImpl struct { type GitImpl struct {
messageProcessor MessageProcessor messageProcessor MessageProcessor
tagCfg TagConfig tagCfg TagConfig
} }
// NewGit constructor // NewGit constructor.
func NewGit(messageProcessor MessageProcessor, cfg TagConfig) *GitImpl { func NewGit(messageProcessor MessageProcessor, cfg TagConfig) *GitImpl {
return &GitImpl{ return &GitImpl{
messageProcessor: messageProcessor, messageProcessor: messageProcessor,
@ -78,7 +78,7 @@ func NewGit(messageProcessor MessageProcessor, cfg TagConfig) *GitImpl {
} }
} }
// LastTag get last tag, if no tag found, return empty // LastTag get last tag, if no tag found, return empty.
func (GitImpl) LastTag() string { func (GitImpl) LastTag() string {
cmd := exec.Command("git", "for-each-ref", "refs/tags", "--sort", "-creatordate", "--format", "%(refname:short)", "--count", "1") cmd := exec.Command("git", "for-each-ref", "refs/tags", "--sort", "-creatordate", "--format", "%(refname:short)", "--count", "1")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
@ -88,7 +88,7 @@ func (GitImpl) LastTag() string {
return strings.TrimSpace(strings.Trim(string(out), "\n")) return strings.TrimSpace(strings.Trim(string(out), "\n"))
} }
// Log return git log // Log return git log.
func (g GitImpl) Log(lr LogRange) ([]GitCommitLog, error) { func (g GitImpl) Log(lr LogRange) ([]GitCommitLog, error) {
format := "--pretty=format:\"%ad" + logSeparator + "%h" + logSeparator + "%s" + logSeparator + "%b" + endLine + "\"" format := "--pretty=format:\"%ad" + logSeparator + "%h" + logSeparator + "%s" + logSeparator + "%b" + endLine + "\""
params := []string{"log", "--date=short", format} params := []string{"log", "--date=short", format}
@ -114,7 +114,7 @@ func (g GitImpl) Log(lr LogRange) ([]GitCommitLog, error) {
return parseLogOutput(g.messageProcessor, string(out)), nil return parseLogOutput(g.messageProcessor, string(out)), nil
} }
// Commit runs git commit // Commit runs git commit.
func (g GitImpl) Commit(header, body, footer string) error { func (g GitImpl) Commit(header, body, footer string) error {
cmd := exec.Command("git", "commit", "-m", header, "-m", "", "-m", body, "-m", "", "-m", footer) cmd := exec.Command("git", "commit", "-m", header, "-m", "", "-m", body, "-m", "", "-m", footer)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
@ -122,7 +122,7 @@ func (g GitImpl) Commit(header, body, footer string) error {
return cmd.Run() return cmd.Run()
} }
// Tag create a git tag // Tag create a git tag.
func (g GitImpl) Tag(version semver.Version) error { func (g GitImpl) Tag(version semver.Version) error {
tag := fmt.Sprintf(g.tagCfg.Pattern, version.Major(), version.Minor(), version.Patch()) tag := fmt.Sprintf(g.tagCfg.Pattern, version.Major(), version.Minor(), version.Patch())
tagMsg := fmt.Sprintf("Version %d.%d.%d", version.Major(), version.Minor(), version.Patch()) tagMsg := fmt.Sprintf("Version %d.%d.%d", version.Major(), version.Minor(), version.Patch())
@ -136,7 +136,7 @@ func (g GitImpl) Tag(version semver.Version) error {
return pushCommand.Run() return pushCommand.Run()
} }
// Tags list repository tags // Tags list repository tags.
func (g GitImpl) Tags() ([]GitTag, error) { func (g GitImpl) Tags() ([]GitTag, error) {
cmd := exec.Command("git", "for-each-ref", "--sort", "creatordate", "--format", "%(creatordate:iso8601)#%(refname:short)", "refs/tags") cmd := exec.Command("git", "for-each-ref", "--sort", "creatordate", "--format", "%(creatordate:iso8601)#%(refname:short)", "refs/tags")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
@ -146,7 +146,7 @@ func (g GitImpl) Tags() ([]GitTag, error) {
return parseTagsOutput(string(out)) return parseTagsOutput(string(out))
} }
// Branch get git branch // Branch get git branch.
func (GitImpl) Branch() string { func (GitImpl) Branch() string {
cmd := exec.Command("git", "symbolic-ref", "--short", "HEAD") cmd := exec.Command("git", "symbolic-ref", "--short", "HEAD")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()

View File

@ -23,7 +23,7 @@ type CommitMessage struct {
Metadata map[string]string `json:"metadata,omitempty"` Metadata map[string]string `json:"metadata,omitempty"`
} }
// NewCommitMessage commit message constructor // NewCommitMessage commit message constructor.
func NewCommitMessage(ctype, scope, description, body, issue, breakingChanges string) CommitMessage { func NewCommitMessage(ctype, scope, description, body, issue, breakingChanges string) CommitMessage {
metadata := make(map[string]string) metadata := make(map[string]string)
if issue != "" { if issue != "" {
@ -58,7 +58,7 @@ type MessageProcessor interface {
Parse(subject, body string) CommitMessage Parse(subject, body string) CommitMessage
} }
// NewMessageProcessor MessageProcessorImpl constructor // NewMessageProcessor MessageProcessorImpl constructor.
func NewMessageProcessor(mcfg CommitMessageConfig, bcfg BranchesConfig) *MessageProcessorImpl { func NewMessageProcessor(mcfg CommitMessageConfig, bcfg BranchesConfig) *MessageProcessorImpl {
return &MessageProcessorImpl{ return &MessageProcessorImpl{
messageCfg: mcfg, messageCfg: mcfg,
@ -82,7 +82,7 @@ func (p MessageProcessorImpl) Validate(message string) error {
subject, body := splitCommitMessageContent(message) subject, body := splitCommitMessageContent(message)
msg := p.Parse(subject, body) msg := p.Parse(subject, body)
if !regexp.MustCompile("^[a-z+]+(\\(.+\\))?!?: .+$").MatchString(subject) { if !regexp.MustCompile(`^[a-z+]+(\(.+\))?!?: .+$`).MatchString(subject) {
return fmt.Errorf("subject [%s] should be valid according with conventional commits", subject) return fmt.Errorf("subject [%s] should be valid according with conventional commits", subject)
} }
@ -125,7 +125,7 @@ func (p MessageProcessorImpl) ValidateDescription(description string) error {
// Enhance add metadata on commit message. // Enhance add metadata on commit message.
func (p MessageProcessorImpl) Enhance(branch string, message string) (string, error) { func (p MessageProcessorImpl) Enhance(branch string, message string) (string, error) {
if p.branchesCfg.DisableIssue || p.messageCfg.IssueFooterConfig().Key == "" || hasIssueID(message, p.messageCfg.IssueFooterConfig()) { if p.branchesCfg.DisableIssue || p.messageCfg.IssueFooterConfig().Key == "" || hasIssueID(message, p.messageCfg.IssueFooterConfig()) {
return "", nil //enhance disabled return "", nil // enhance disabled
} }
issue, err := p.IssueID(branch) issue, err := p.IssueID(branch)
@ -160,7 +160,7 @@ func (p MessageProcessorImpl) IssueID(branch string) (string, error) {
return "", nil return "", nil
} }
rstr := fmt.Sprintf("^%s(%s)%s$", p.branchesCfg.PrefixRegex, p.messageCfg.Issue.Regex, p.branchesCfg.SuffixRegex) rstr := fmt.Sprintf("^%s(%s)%s$", p.branchesCfg.Prefix, p.messageCfg.Issue.Regex, p.branchesCfg.Suffix)
r, err := regexp.Compile(rstr) r, err := regexp.Compile(rstr)
if err != nil { if err != nil {
return "", fmt.Errorf("could not compile issue regex: %s, error: %v", rstr, err.Error()) return "", fmt.Errorf("could not compile issue regex: %s, error: %v", rstr, err.Error())
@ -229,7 +229,7 @@ func (p MessageProcessorImpl) Parse(subject, body string) CommitMessage {
} }
func parseSubjectMessage(message string) (string, string, string, bool) { func parseSubjectMessage(message string) (string, string, string, bool) {
regex := regexp.MustCompile("([a-z]+)(\\((.*)\\))?(!)?: (.*)") regex := regexp.MustCompile(`([a-z]+)(\((.*)\))?(!)?: (.*)`)
result := regex.FindStringSubmatch(message) result := regex.FindStringSubmatch(message)
if len(result) != 6 { if len(result) != 6 {
return "", "", message, false return "", "", message, false

View File

@ -55,14 +55,14 @@ var ccfgWithScope = CommitMessageConfig{
func newBranchCfg(skipDetached bool) BranchesConfig { func newBranchCfg(skipDetached bool) BranchesConfig {
return BranchesConfig{ return BranchesConfig{
PrefixRegex: "([a-z]+\\/)?", Prefix: "([a-z]+\\/)?",
SuffixRegex: "(-.*)?", Suffix: "(-.*)?",
Skip: []string{"develop", "master"}, Skip: []string{"develop", "master"},
SkipDetached: &skipDetached, SkipDetached: &skipDetached,
} }
} }
// messages samples start // messages samples start.
var fullMessage = `fix: correct minor typos in code var fullMessage = `fix: correct minor typos in code
see the issue for details see the issue for details
@ -71,6 +71,7 @@ on typos fixed.
Reviewed-by: Z Reviewed-by: Z
Refs #133` Refs #133`
var fullMessageWithJira = `fix: correct minor typos in code var fullMessageWithJira = `fix: correct minor typos in code
see the issue for details see the issue for details
@ -80,6 +81,7 @@ on typos fixed.
Reviewed-by: Z Reviewed-by: Z
Refs #133 Refs #133
jira: JIRA-456` jira: JIRA-456`
var fullMessageRefs = `fix: correct minor typos in code var fullMessageRefs = `fix: correct minor typos in code
see the issue for details see the issue for details
@ -87,11 +89,13 @@ see the issue for details
on typos fixed. on typos fixed.
Refs #133` Refs #133`
var subjectAndBodyMessage = `fix: correct minor typos in code var subjectAndBodyMessage = `fix: correct minor typos in code
see the issue for details see the issue for details
on typos fixed.` on typos fixed.`
var subjectAndFooterMessage = `refactor!: drop support for Node 6 var subjectAndFooterMessage = `refactor!: drop support for Node 6
BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.` BREAKING CHANGE: refactor to use JavaScript features not available in Node 6.`
@ -470,7 +474,6 @@ func Test_splitCommitMessageContent(t *testing.T) {
} }
} }
//commitType, scope, description, hasBreakingChange
func Test_parseSubjectMessage(t *testing.T) { func Test_parseSubjectMessage(t *testing.T) {
tests := []struct { tests := []struct {
name string name string

View File

@ -55,7 +55,7 @@ type ReleaseNote struct {
BreakingChanges BreakingChangeSection BreakingChanges BreakingChangeSection
} }
// BreakingChangeSection breaking change section // BreakingChangeSection breaking change section.
type BreakingChangeSection struct { type BreakingChangeSection struct {
Name string Name string
Messages []string Messages []string

View File

@ -11,7 +11,7 @@ const (
major major
) )
// ToVersion parse string to semver.Version // ToVersion parse string to semver.Version.
func ToVersion(value string) (semver.Version, error) { func ToVersion(value string) (semver.Version, error) {
version := value version := value
if version == "" { if version == "" {
@ -24,12 +24,12 @@ func ToVersion(value string) (semver.Version, error) {
return *v, nil return *v, nil
} }
// SemVerCommitsProcessor interface // SemVerCommitsProcessor interface.
type SemVerCommitsProcessor interface { type SemVerCommitsProcessor interface {
NextVersion(version semver.Version, commits []GitCommitLog) (semver.Version, bool) NextVersion(version semver.Version, commits []GitCommitLog) (semver.Version, bool)
} }
// SemVerCommitsProcessorImpl process versions using commit log // SemVerCommitsProcessorImpl process versions using commit log.
type SemVerCommitsProcessorImpl struct { type SemVerCommitsProcessorImpl struct {
MajorVersionTypes map[string]struct{} MajorVersionTypes map[string]struct{}
MinorVersionTypes map[string]struct{} MinorVersionTypes map[string]struct{}
@ -38,7 +38,7 @@ type SemVerCommitsProcessorImpl struct {
IncludeUnknownTypeAsPatch bool IncludeUnknownTypeAsPatch bool
} }
// NewSemVerCommitsProcessor SemanticVersionCommitsProcessorImpl constructor // NewSemVerCommitsProcessor SemanticVersionCommitsProcessorImpl constructor.
func NewSemVerCommitsProcessor(vcfg VersioningConfig, mcfg CommitMessageConfig) *SemVerCommitsProcessorImpl { func NewSemVerCommitsProcessor(vcfg VersioningConfig, mcfg CommitMessageConfig) *SemVerCommitsProcessorImpl {
return &SemVerCommitsProcessorImpl{ return &SemVerCommitsProcessorImpl{
IncludeUnknownTypeAsPatch: !vcfg.IgnoreUnknown, IncludeUnknownTypeAsPatch: !vcfg.IgnoreUnknown,
@ -49,9 +49,9 @@ func NewSemVerCommitsProcessor(vcfg VersioningConfig, mcfg CommitMessageConfig)
} }
} }
// NextVersion calculates next version based on commit log // NextVersion calculates next version based on commit log.
func (p SemVerCommitsProcessorImpl) NextVersion(version semver.Version, commits []GitCommitLog) (semver.Version, bool) { func (p SemVerCommitsProcessorImpl) NextVersion(version semver.Version, commits []GitCommitLog) (semver.Version, bool) {
var versionToUpdate = none versionToUpdate := none
for _, commit := range commits { for _, commit := range commits {
if v := p.versionTypeToUpdate(commit); v > versionToUpdate { if v := p.versionTypeToUpdate(commit); v > versionToUpdate {
versionToUpdate = v versionToUpdate = v