feat: show time of each commit as the default (#12)
* feat(git): add author time * feat(git): add author info * refactor: use commit option to generate convertional commit * feat: add author date to convention commit * refactor(changelog): replace t time var with when Co-authored-by: Tran Hau <ngtranhau@gmail.com>main
parent
3ea63124fc
commit
552034123d
|
@ -19,7 +19,7 @@ const (
|
|||
thirdLevel = 3
|
||||
)
|
||||
|
||||
func GenerateMarkdown(commits []convention.Commit, scopes map[string]struct{}, version string, t time.Time) []markdown.Node {
|
||||
func GenerateMarkdown(commits []convention.Commit, scopes map[string]struct{}, version string, when time.Time) []markdown.Node {
|
||||
if len(commits) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func GenerateMarkdown(commits []convention.Commit, scopes map[string]struct{}, v
|
|||
// Adding title, version to nodes
|
||||
nodes = append([]markdown.Node{
|
||||
markdown.NewHeader(firstLevel, title),
|
||||
markdown.NewHeader(secondLevel, getVersionHeader(version, t)),
|
||||
markdown.NewHeader(secondLevel, getVersionHeader(version, when)),
|
||||
}, nodes...)
|
||||
|
||||
return nodes
|
||||
|
@ -90,7 +90,7 @@ func ParseMarkdown(data string) []markdown.Node {
|
|||
return nodes
|
||||
}
|
||||
|
||||
func getVersionHeader(version string, t time.Time) string {
|
||||
year, month, day := t.Date()
|
||||
func getVersionHeader(version string, when time.Time) string {
|
||||
year, month, day := when.Date()
|
||||
return fmt.Sprintf("%s (%d-%d-%d)", version, year, month, day)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func TestGenerateMarkdown(t *testing.T) {
|
|||
commits []convention.Commit
|
||||
scopes map[string]struct{}
|
||||
version string
|
||||
t time.Time
|
||||
when time.Time
|
||||
}{
|
||||
{
|
||||
name: "empty old data",
|
||||
|
@ -34,7 +34,7 @@ func TestGenerateMarkdown(t *testing.T) {
|
|||
},
|
||||
},
|
||||
version: "v1.0.0",
|
||||
t: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
|
||||
when: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
|
||||
},
|
||||
{
|
||||
name: "many commits",
|
||||
|
@ -73,7 +73,7 @@ func TestGenerateMarkdown(t *testing.T) {
|
|||
},
|
||||
},
|
||||
version: "v1.0.0",
|
||||
t: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
|
||||
when: time.Date(2020, 1, 18, 0, 0, 0, 0, time.Local),
|
||||
},
|
||||
{
|
||||
name: "ignore commits outside scope",
|
||||
|
@ -115,14 +115,14 @@ func TestGenerateMarkdown(t *testing.T) {
|
|||
"a": struct{}{},
|
||||
},
|
||||
version: "v1.0.0",
|
||||
t: time.Date(2020, 3, 22, 0, 0, 0, 0, time.Local),
|
||||
when: time.Date(2020, 3, 22, 0, 0, 0, 0, time.Local),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
g := goldie.New(t)
|
||||
got := GenerateMarkdown(tc.commits, tc.scopes, tc.version, tc.t)
|
||||
got := GenerateMarkdown(tc.commits, tc.scopes, tc.version, tc.when)
|
||||
g.Assert(t, t.Name(), []byte(markdown.GenerateText(got)))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package convention
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/haunt98/changeloguru/pkg/git"
|
||||
)
|
||||
|
||||
|
@ -13,12 +9,6 @@ import (
|
|||
// [optional body]
|
||||
// [optional footer(s)]
|
||||
|
||||
var (
|
||||
headerRegex = regexp.MustCompile(`(?P<type>[a-zA-Z]+)(?P<scope>\([a-zA-Z]+\))?(?P<attention>!)?:\s(?P<description>.+)`)
|
||||
|
||||
ErrEmptyCommit = errors.New("empty commit")
|
||||
)
|
||||
|
||||
// Commit represens conventional commit
|
||||
type Commit struct {
|
||||
// Commit as is
|
||||
|
@ -29,27 +19,21 @@ type Commit struct {
|
|||
}
|
||||
|
||||
// NewCommit return conventional commit from git commit
|
||||
func NewCommit(c git.Commit) (result Commit, err error) {
|
||||
// Preprocess
|
||||
message := strings.TrimSpace(c.Message)
|
||||
messages := strings.Split(message, "\n")
|
||||
if len(messages) == 0 {
|
||||
err = ErrEmptyCommit
|
||||
return
|
||||
func NewCommit(c git.Commit) (Commit, error) {
|
||||
return NewCommitWithOptions(
|
||||
GetRawHeader(c),
|
||||
GetTypeAndScope(c),
|
||||
AddAuthorDate(c),
|
||||
)
|
||||
}
|
||||
|
||||
// Use regex to detect
|
||||
result.RawHeader = strings.TrimSpace(messages[0])
|
||||
if !headerRegex.MatchString(result.RawHeader) {
|
||||
result.Type = MiscType
|
||||
// NewCommitWithOptions return conventional commit with custom option
|
||||
func NewCommitWithOptions(opts ...OptionFn) (result Commit, err error) {
|
||||
for _, opt := range opts {
|
||||
if err = opt(&result); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
headerSubmatches := headerRegex.FindStringSubmatch(result.RawHeader)
|
||||
result.Type = strings.ToLower(headerSubmatches[1])
|
||||
result.Scope = strings.ToLower(headerSubmatches[2])
|
||||
result.Scope = strings.TrimLeft(result.Scope, "(")
|
||||
result.Scope = strings.TrimRight(result.Scope, ")")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package convention
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/haunt98/changeloguru/pkg/git"
|
||||
"github.com/sebdah/goldie/v2"
|
||||
|
@ -50,6 +51,15 @@ func TestNewCommit(t *testing.T) {
|
|||
Message: "random git message",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Misc with author date",
|
||||
c: git.Commit{
|
||||
Message: "random git message",
|
||||
Author: git.Author{
|
||||
When: time.Date(2020, 4, 1, 0, 0, 0, 0, time.Local),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package convention
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/haunt98/changeloguru/pkg/git"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrEmptyCommit = errors.New("empty commit")
|
||||
|
||||
headerRegex = regexp.MustCompile(`(?P<type>[a-zA-Z]+)(?P<scope>\([a-zA-Z]+\))?(?P<attention>!)?:\s(?P<description>.+)`)
|
||||
)
|
||||
|
||||
type OptionFn func(*Commit) error
|
||||
|
||||
func GetRawHeader(gitCommit git.Commit) OptionFn {
|
||||
return func(c *Commit) error {
|
||||
message := strings.TrimSpace(gitCommit.Message)
|
||||
messages := strings.Split(message, "\n")
|
||||
if len(messages) == 0 {
|
||||
return ErrEmptyCommit
|
||||
}
|
||||
|
||||
c.RawHeader = messages[0]
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetTypeAndScope(gitCommit git.Commit) OptionFn {
|
||||
return func(c *Commit) error {
|
||||
if !headerRegex.MatchString(c.RawHeader) {
|
||||
c.Type = MiscType
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
headerSubmatches := headerRegex.FindStringSubmatch(c.RawHeader)
|
||||
c.Type = strings.ToLower(headerSubmatches[1])
|
||||
c.Scope = strings.ToLower(headerSubmatches[2])
|
||||
c.Scope = strings.TrimLeft(c.Scope, "(")
|
||||
c.Scope = strings.TrimRight(c.Scope, ")")
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func AddAuthorDate(gitCommit git.Commit) OptionFn {
|
||||
return func(c *Commit) error {
|
||||
year, month, day := gitCommit.Author.When.Date()
|
||||
c.RawHeader = fmt.Sprintf("%s (%d-%d-%d)", c.RawHeader, year, month, day)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RawHeader": "docs: correct spelling of CHANGELOG",
|
||||
"RawHeader": "docs: correct spelling of CHANGELOG (1-1-1)",
|
||||
"Type": "docs",
|
||||
"Scope": ""
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RawHeader": "refactor!: drop support for Node 6",
|
||||
"RawHeader": "refactor!: drop support for Node 6 (1-1-1)",
|
||||
"Type": "refactor",
|
||||
"Scope": ""
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RawHeader": "feat(lang): add polish language",
|
||||
"RawHeader": "feat(lang): add polish language (1-1-1)",
|
||||
"Type": "feat",
|
||||
"Scope": "lang"
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RawHeader": "random git message",
|
||||
"RawHeader": "random git message (1-1-1)",
|
||||
"Type": "misc",
|
||||
"Scope": ""
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"RawHeader": "random git message (2020-4-1)",
|
||||
"Type": "misc",
|
||||
"Scope": ""
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RawHeader": "Docs: correct spelling of CHANGELOG",
|
||||
"RawHeader": "Docs: correct spelling of CHANGELOG (1-1-1)",
|
||||
"Type": "docs",
|
||||
"Scope": ""
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"RawHeader": "REFACTOR!: drop support for Node 6",
|
||||
"RawHeader": "REFACTOR!: drop support for Node 6 (1-1-1)",
|
||||
"Type": "refactor",
|
||||
"Scope": ""
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package git
|
||||
|
||||
import "time"
|
||||
|
||||
type Author struct {
|
||||
Name string
|
||||
Email string
|
||||
When time.Time
|
||||
}
|
|
@ -1,15 +1,23 @@
|
|||
package git
|
||||
|
||||
import "github.com/go-git/go-git/v5/plumbing/object"
|
||||
import (
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
)
|
||||
|
||||
// Commit stores all git-commit information
|
||||
type Commit struct {
|
||||
Message string
|
||||
Author Author
|
||||
}
|
||||
|
||||
// Convert from git-commit
|
||||
func newCommit(commit *object.Commit) Commit {
|
||||
return Commit{
|
||||
Message: commit.Message,
|
||||
Author: Author{
|
||||
Name: commit.Author.Name,
|
||||
Email: commit.Author.Email,
|
||||
When: commit.Author.When,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue