mirror of
https://github.com/thegeeklab/git-sv.git
synced 2024-11-28 16:40:36 +00:00
Merge pull request #19 from bvieira/#17
Feature: add next version on changelog
This commit is contained in:
commit
591e00ec51
@ -183,7 +183,7 @@ Commands like `commit-log` and `commit-notes` has a range option. Supported rang
|
|||||||
|
|
||||||
By default, it's used [--date=short](https://git-scm.com/docs/git-log#Documentation/git-log.txt---dateltformatgt) at `git log`, all dates returned from it will be in `YYYY-MM-DD` format.
|
By default, it's used [--date=short](https://git-scm.com/docs/git-log#Documentation/git-log.txt---dateltformatgt) at `git log`, all dates returned from it will be in `YYYY-MM-DD` format.
|
||||||
|
|
||||||
Range `tag` will use `git describe` to get the last tag available if `start` is empty, the others types won't use the existing tags. It's recommended to always use a start limit in a old repository with a lot of commits. This behavior was maintained to not break the retrocompatibility.
|
Range `tag` will use `git for-each-ref refs/tags` to get the last tag available if `start` is empty, the others types won't use the existing tags. It's recommended to always use a start limit in a old repository with a lot of commits. This behavior was maintained to not break the retrocompatibility.
|
||||||
|
|
||||||
Range `date` use git log `--since` and `--until`. It's possible to use all supported formats from [git log](https://git-scm.com/docs/git-log#Documentation/git-log.txt---sinceltdategt). If `end` is in `YYYY-MM-DD` format, `sv` will add a day on git log command to make the end date inclusive.
|
Range `date` use git log `--since` and `--until`. It's possible to use all supported formats from [git log](https://git-scm.com/docs/git-log#Documentation/git-log.txt---sinceltdategt). If `end` is in `YYYY-MM-DD` format, `sv` will add a day on git log command to make the end date inclusive.
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ func configShowHandler(cfg Config) func(c *cli.Context) error {
|
|||||||
|
|
||||||
func currentVersionHandler(git sv.Git) func(c *cli.Context) error {
|
func currentVersionHandler(git sv.Git) func(c *cli.Context) error {
|
||||||
return func(c *cli.Context) error {
|
return func(c *cli.Context) error {
|
||||||
describe := git.Describe()
|
lastTag := git.LastTag()
|
||||||
|
|
||||||
currentVer, err := sv.ToVersion(describe)
|
currentVer, err := sv.ToVersion(lastTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("error parsing version: %s from git tag, message: %v", lastTag, err)
|
||||||
}
|
}
|
||||||
fmt.Printf("%d.%d.%d\n", currentVer.Major(), currentVer.Minor(), currentVer.Patch())
|
fmt.Printf("%d.%d.%d\n", currentVer.Major(), currentVer.Minor(), currentVer.Patch())
|
||||||
return nil
|
return nil
|
||||||
@ -54,19 +54,19 @@ func currentVersionHandler(git sv.Git) func(c *cli.Context) error {
|
|||||||
|
|
||||||
func nextVersionHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) func(c *cli.Context) error {
|
func nextVersionHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) func(c *cli.Context) error {
|
||||||
return func(c *cli.Context) error {
|
return func(c *cli.Context) error {
|
||||||
describe := git.Describe()
|
lastTag := git.LastTag()
|
||||||
|
|
||||||
currentVer, err := sv.ToVersion(describe)
|
currentVer, err := sv.ToVersion(lastTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error parsing version: %s from describe, message: %v", describe, err)
|
return fmt.Errorf("error parsing version: %s from git tag, message: %v", lastTag, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commits, err := git.Log(sv.NewLogRange(sv.TagRange, describe, ""))
|
commits, err := git.Log(sv.NewLogRange(sv.TagRange, lastTag, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting git log, message: %v", err)
|
return fmt.Errorf("error getting git log, message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nextVer := semverProcessor.NextVersion(currentVer, commits)
|
nextVer, _ := semverProcessor.NextVersion(currentVer, commits)
|
||||||
fmt.Printf("%d.%d.%d\n", nextVer.Major(), nextVer.Minor(), nextVer.Patch())
|
fmt.Printf("%d.%d.%d\n", nextVer.Major(), nextVer.Minor(), nextVer.Patch())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ func getTagCommits(git sv.Git, tag string) ([]sv.GitCommitLog, error) {
|
|||||||
func logRange(git sv.Git, rangeFlag, startFlag, endFlag string) (sv.LogRange, error) {
|
func logRange(git sv.Git, rangeFlag, startFlag, endFlag string) (sv.LogRange, error) {
|
||||||
switch rangeFlag {
|
switch rangeFlag {
|
||||||
case string(sv.TagRange):
|
case string(sv.TagRange):
|
||||||
return sv.NewLogRange(sv.TagRange, str(startFlag, git.Describe()), endFlag), nil
|
return sv.NewLogRange(sv.TagRange, str(startFlag, git.LastTag()), endFlag), nil
|
||||||
case string(sv.DateRange):
|
case string(sv.DateRange):
|
||||||
return sv.NewLogRange(sv.DateRange, startFlag, endFlag), nil
|
return sv.NewLogRange(sv.DateRange, startFlag, endFlag), nil
|
||||||
case string(sv.HashRange):
|
case string(sv.HashRange):
|
||||||
@ -164,7 +164,8 @@ func releaseNotesHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor,
|
|||||||
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, semverProcessor, tag)
|
||||||
} else {
|
} else {
|
||||||
rnVersion, date, commits, err = getNextVersionInfo(git, semverProcessor)
|
// TODO: should generate release notes if version was not updated?
|
||||||
|
rnVersion, _, date, commits, err = getNextVersionInfo(git, semverProcessor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -223,37 +224,38 @@ func find(tag string, tags []sv.GitTag) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNextVersionInfo(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) (semver.Version, time.Time, []sv.GitCommitLog, error) {
|
func getNextVersionInfo(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) (semver.Version, bool, time.Time, []sv.GitCommitLog, error) {
|
||||||
describe := git.Describe()
|
lastTag := git.LastTag()
|
||||||
|
|
||||||
currentVer, err := sv.ToVersion(describe)
|
currentVer, err := sv.ToVersion(lastTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return semver.Version{}, time.Time{}, nil, fmt.Errorf("error parsing version: %s from describe, message: %v", describe, err)
|
return semver.Version{}, false, time.Time{}, nil, fmt.Errorf("error parsing version: %s from git tag, message: %v", lastTag, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commits, err := git.Log(sv.NewLogRange(sv.TagRange, describe, ""))
|
commits, err := git.Log(sv.NewLogRange(sv.TagRange, lastTag, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return semver.Version{}, time.Time{}, nil, fmt.Errorf("error getting git log, message: %v", err)
|
return semver.Version{}, false, time.Time{}, nil, fmt.Errorf("error getting git log, message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return semverProcessor.NextVersion(currentVer, commits), time.Now(), commits, nil
|
version, updated := semverProcessor.NextVersion(currentVer, commits)
|
||||||
|
return version, updated, time.Now(), commits, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tagHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) func(c *cli.Context) error {
|
func tagHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor) func(c *cli.Context) error {
|
||||||
return func(c *cli.Context) error {
|
return func(c *cli.Context) error {
|
||||||
describe := git.Describe()
|
lastTag := git.LastTag()
|
||||||
|
|
||||||
currentVer, err := sv.ToVersion(describe)
|
currentVer, err := sv.ToVersion(lastTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error parsing version: %s from describe, message: %v", describe, err)
|
return fmt.Errorf("error parsing version: %s from git tag, message: %v", lastTag, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commits, err := git.Log(sv.NewLogRange(sv.TagRange, describe, ""))
|
commits, err := git.Log(sv.NewLogRange(sv.TagRange, lastTag, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting git log, message: %v", err)
|
return fmt.Errorf("error getting git log, message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nextVer := semverProcessor.NextVersion(currentVer, commits)
|
nextVer, _ := semverProcessor.NextVersion(currentVer, commits)
|
||||||
fmt.Printf("%d.%d.%d\n", nextVer.Major(), nextVer.Minor(), nextVer.Patch())
|
fmt.Printf("%d.%d.%d\n", nextVer.Major(), nextVer.Minor(), nextVer.Patch())
|
||||||
|
|
||||||
if err := git.Tag(nextVer); err != nil {
|
if err := git.Tag(nextVer); err != nil {
|
||||||
@ -344,6 +346,17 @@ func changelogHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnP
|
|||||||
|
|
||||||
size := c.Int("size")
|
size := c.Int("size")
|
||||||
all := c.Bool("all")
|
all := c.Bool("all")
|
||||||
|
addNextVersion := c.Bool("add-next-version")
|
||||||
|
|
||||||
|
if addNextVersion {
|
||||||
|
rnVersion, updated, date, commits, uerr := getNextVersionInfo(git, semverProcessor)
|
||||||
|
if uerr != nil {
|
||||||
|
return uerr
|
||||||
|
}
|
||||||
|
if updated {
|
||||||
|
releaseNotes = append(releaseNotes, rnProcessor.Create(&rnVersion, date, commits))
|
||||||
|
}
|
||||||
|
}
|
||||||
for i, tag := range tags {
|
for i, tag := range tags {
|
||||||
if !all && i >= size {
|
if !all && i >= size {
|
||||||
break
|
break
|
||||||
@ -361,7 +374,7 @@ func changelogHandler(git sv.Git, semverProcessor sv.SemVerCommitsProcessor, rnP
|
|||||||
|
|
||||||
currentVer, err := sv.ToVersion(tag.Name)
|
currentVer, err := sv.ToVersion(tag.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error parsing version: %s from describe, message: %v", tag.Name, err)
|
return fmt.Errorf("error parsing version: %s from git tag, message: %v", tag.Name, err)
|
||||||
}
|
}
|
||||||
releaseNotes = append(releaseNotes, rnProcessor.Create(¤tVer, tag.Date, commits))
|
releaseNotes = append(releaseNotes, rnProcessor.Create(¤tVer, tag.Date, commits))
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ func main() {
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.IntFlag{Name: "size", Value: 10, Aliases: []string{"n"}, Usage: "get changelog from last 'n' tags"},
|
&cli.IntFlag{Name: "size", Value: 10, Aliases: []string{"n"}, Usage: "get changelog from last 'n' tags"},
|
||||||
&cli.BoolFlag{Name: "all", Usage: "ignore size parameter, get changelog for every tag"},
|
&cli.BoolFlag{Name: "all", Usage: "ignore size parameter, get changelog for every tag"},
|
||||||
|
&cli.BoolFlag{Name: "add-next-version", Usage: "add next version on change log (commits since last tag, but only if there is a new version to release)"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@ const (
|
|||||||
|
|
||||||
// Git commands
|
// Git commands
|
||||||
type Git interface {
|
type Git interface {
|
||||||
Describe() string
|
LastTag() string
|
||||||
Log(lr LogRange) ([]GitCommitLog, error)
|
Log(lr LogRange) ([]GitCommitLog, error)
|
||||||
Commit(header, body, footer string) error
|
Commit(header, body, footer string) error
|
||||||
Tag(version semver.Version) error
|
Tag(version semver.Version) error
|
||||||
@ -78,9 +78,9 @@ func NewGit(messageProcessor MessageProcessor, cfg TagConfig) *GitImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe runs git describe, it no tag found, return empty
|
// LastTag get last tag, if no tag found, return empty
|
||||||
func (GitImpl) Describe() string {
|
func (GitImpl) LastTag() string {
|
||||||
cmd := exec.Command("git", "describe", "--abbrev=0", "--tags")
|
cmd := exec.Command("git", "for-each-ref", "refs/tags", "--sort", "-creatordate", "--format", "%(refname:short)", "--count", "1")
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
12
sv/semver.go
12
sv/semver.go
@ -26,7 +26,7 @@ func ToVersion(value string) (semver.Version, error) {
|
|||||||
|
|
||||||
// SemVerCommitsProcessor interface
|
// SemVerCommitsProcessor interface
|
||||||
type SemVerCommitsProcessor interface {
|
type SemVerCommitsProcessor interface {
|
||||||
NextVersion(version semver.Version, commits []GitCommitLog) semver.Version
|
NextVersion(version semver.Version, commits []GitCommitLog) (semver.Version, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SemVerCommitsProcessorImpl process versions using commit log
|
// SemVerCommitsProcessorImpl process versions using commit log
|
||||||
@ -50,7 +50,7 @@ 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 {
|
func (p SemVerCommitsProcessorImpl) NextVersion(version semver.Version, commits []GitCommitLog) (semver.Version, bool) {
|
||||||
var versionToUpdate = none
|
var versionToUpdate = none
|
||||||
for _, commit := range commits {
|
for _, commit := range commits {
|
||||||
if v := p.versionTypeToUpdate(commit); v > versionToUpdate {
|
if v := p.versionTypeToUpdate(commit); v > versionToUpdate {
|
||||||
@ -60,13 +60,13 @@ func (p SemVerCommitsProcessorImpl) NextVersion(version semver.Version, commits
|
|||||||
|
|
||||||
switch versionToUpdate {
|
switch versionToUpdate {
|
||||||
case major:
|
case major:
|
||||||
return version.IncMajor()
|
return version.IncMajor(), true
|
||||||
case minor:
|
case minor:
|
||||||
return version.IncMinor()
|
return version.IncMinor(), true
|
||||||
case patch:
|
case patch:
|
||||||
return version.IncPatch()
|
return version.IncPatch(), true
|
||||||
default:
|
default:
|
||||||
return version
|
return version, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,21 +14,26 @@ func TestSemVerCommitsProcessorImpl_NextVersion(t *testing.T) {
|
|||||||
version semver.Version
|
version semver.Version
|
||||||
commits []GitCommitLog
|
commits []GitCommitLog
|
||||||
want semver.Version
|
want semver.Version
|
||||||
|
wantUpdated bool
|
||||||
}{
|
}{
|
||||||
{"no update", true, version("0.0.0"), []GitCommitLog{}, version("0.0.0")},
|
{"no update", true, version("0.0.0"), []GitCommitLog{}, version("0.0.0"), false},
|
||||||
{"no update on unknown type", true, version("0.0.0"), []GitCommitLog{commitlog("a", map[string]string{})}, version("0.0.0")},
|
{"no update on unknown type", true, version("0.0.0"), []GitCommitLog{commitlog("a", map[string]string{})}, version("0.0.0"), false},
|
||||||
{"no update on unmapped known type", false, version("0.0.0"), []GitCommitLog{commitlog("none", map[string]string{})}, version("0.0.0")},
|
{"no update on unmapped known type", false, version("0.0.0"), []GitCommitLog{commitlog("none", map[string]string{})}, version("0.0.0"), false},
|
||||||
{"update patch on unknown type", false, version("0.0.0"), []GitCommitLog{commitlog("a", map[string]string{})}, version("0.0.1")},
|
{"update patch on unknown type", false, version("0.0.0"), []GitCommitLog{commitlog("a", map[string]string{})}, version("0.0.1"), true},
|
||||||
{"patch update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{})}, version("0.0.1")},
|
{"patch update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{})}, version("0.0.1"), true},
|
||||||
{"minor update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("minor", map[string]string{})}, version("0.1.0")},
|
{"minor update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("minor", map[string]string{})}, version("0.1.0"), true},
|
||||||
{"major update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("major", map[string]string{})}, version("1.0.0")},
|
{"major update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("major", map[string]string{})}, version("1.0.0"), true},
|
||||||
{"breaking change update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("patch", map[string]string{"breaking-change": "break"})}, version("1.0.0")},
|
{"breaking change update", false, version("0.0.0"), []GitCommitLog{commitlog("patch", map[string]string{}), commitlog("patch", map[string]string{"breaking-change": "break"})}, version("1.0.0"), true},
|
||||||
}
|
}
|
||||||
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 := NewSemVerCommitsProcessor(VersioningConfig{UpdateMajor: []string{"major"}, UpdateMinor: []string{"minor"}, UpdatePatch: []string{"patch"}, IgnoreUnknown: tt.ignoreUnknown}, CommitMessageConfig{Types: []string{"major", "minor", "patch", "none"}})
|
p := NewSemVerCommitsProcessor(VersioningConfig{UpdateMajor: []string{"major"}, UpdateMinor: []string{"minor"}, UpdatePatch: []string{"patch"}, IgnoreUnknown: tt.ignoreUnknown}, CommitMessageConfig{Types: []string{"major", "minor", "patch", "none"}})
|
||||||
if got := p.NextVersion(tt.version, tt.commits); !reflect.DeepEqual(got, tt.want) {
|
got, gotUpdated := p.NextVersion(tt.version, tt.commits)
|
||||||
t.Errorf("SemVerCommitsProcessorImpl.NextVersion() = %v, want %v", got, tt.want)
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("SemVerCommitsProcessorImpl.NextVersion() Version = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
if tt.wantUpdated != gotUpdated {
|
||||||
|
t.Errorf("SemVerCommitsProcessorImpl.NextVersion() Updated = %v, want %v", gotUpdated, tt.wantUpdated)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user