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:
commit
d76920bb5c
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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(¤tVer, tag.Date, commits))
|
releaseNotes = append(releaseNotes, rnProcessor.Create(¤tVer, 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 == "" {
|
||||||
|
@ -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...)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"`
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
sv/git.go
34
sv/git.go
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
12
sv/semver.go
12
sv/semver.go
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user