Skip to content

Commit

Permalink
feat!: gate v0 increment prevention
Browse files Browse the repository at this point in the history
closes #153
  • Loading branch information
caarlos0 committed May 3, 2024
1 parent a2b6361 commit 7cf187a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 56 deletions.
44 changes: 27 additions & 17 deletions internal/svu/svu.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ var (
)

type Options struct {
Cmd string
Pattern string
Prefix string
StripPrefix bool
PreRelease string
Build string
Directory string
TagMode string
ForcePatchIncrement bool
Cmd string
Pattern string
Prefix string
StripPrefix bool
PreRelease string
Build string
Directory string
TagMode string
ForcePatchIncrement bool
PreventMajorIncrementOnV0 bool
}

func Version(opts Options) (string, error) {
Expand All @@ -50,7 +51,16 @@ func Version(opts Options) (string, error) {
return "", fmt.Errorf("could not get current version from tag: '%s': %w", tag, err)
}

result, err := nextVersion(string(opts.Cmd), current, tag, opts.PreRelease, opts.Build, opts.Directory, opts.ForcePatchIncrement)
result, err := nextVersion(
string(opts.Cmd),
current,
tag,
opts.PreRelease,
opts.Build,
opts.Directory,
opts.PreventMajorIncrementOnV0,
opts.ForcePatchIncrement,
)
if err != nil {
return "", fmt.Errorf("could not get next tag: '%s': %w", tag, err)
}
Expand All @@ -61,12 +71,12 @@ func Version(opts Options) (string, error) {
return opts.Prefix + result.String(), nil
}

func nextVersion(cmd string, current *semver.Version, tag, preRelease, build, directory string, force bool) (semver.Version, error) {
func nextVersion(cmd string, current *semver.Version, tag, preRelease, build, directory string, preventMajorIncrementOnV0, forcePatchIncrement bool) (semver.Version, error) {
if cmd == CurrentCmd {
return *current, nil
}

if force {
if forcePatchIncrement {
c, err := current.SetMetadata("")
if err != nil {
return c, err
Expand All @@ -82,7 +92,7 @@ func nextVersion(cmd string, current *semver.Version, tag, preRelease, build, di
var err error
switch cmd {
case NextCmd, PreReleaseCmd:
result, err = findNextWithGitLog(current, tag, directory, force)
result, err = findNextWithGitLog(current, tag, directory, preventMajorIncrementOnV0, forcePatchIncrement)
case MajorCmd:
result = current.IncMajor()
case MinorCmd:
Expand Down Expand Up @@ -172,13 +182,13 @@ func getCurrentVersion(tag, prefix string) (*semver.Version, error) {
return current, err
}

func findNextWithGitLog(current *semver.Version, tag string, directory string, forcePatchIncrement bool) (semver.Version, error) {
func findNextWithGitLog(current *semver.Version, tag string, directory string, preventMajorIncrementOnV0, forcePatchIncrement bool) (semver.Version, error) {
log, err := git.Changelog(tag, directory)
if err != nil {
return semver.Version{}, fmt.Errorf("failed to get changelog: %w", err)
}

return findNext(current, forcePatchIncrement, log), nil
return findNext(current, preventMajorIncrementOnV0, forcePatchIncrement, log), nil
}

func isBreaking(log string) bool {
Expand All @@ -193,9 +203,9 @@ func isPatch(log string) bool {
return patch.MatchString(log)
}

func findNext(current *semver.Version, forcePatchIncrement bool, log string) semver.Version {
func findNext(current *semver.Version, preventMajorIncrementOnV0, forcePatchIncrement bool, log string) semver.Version {
if isBreaking(log) {
if current.Major() == 0 {
if current.Major() == 0 && preventMajorIncrementOnV0 {
return current.IncMinor()
}
return current.IncMajor()
Expand Down
61 changes: 31 additions & 30 deletions internal/svu/svu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,17 @@ func TestFindNext(t *testing.T) {
version2 := semver.MustParse("v2.4.12")
version3 := semver.MustParse("v3.4.5-beta34+ads")
for expected, next := range map[string]semver.Version{
"v0.4.5": findNext(version0a, false, "chore: should do nothing"),
"v0.4.6": findNext(version0a, false, "fix: inc patch"),
"v0.5.0": findNext(version0a, false, "feat: inc minor"),
"v0.6.0": findNext(version0b, false, "feat!: inc minor"),
"v1.2.3": findNext(version1, false, "chore: should do nothing"),
"v1.2.4": findNext(version1, true, "chore: is forcing patch, so should inc patch"),
"v1.3.0": findNext(version1, false, "feat: inc major"),
"v2.0.0": findNext(version1, true, "chore!: hashbang incs major"),
"v3.0.0": findNext(version2, false, "feat: something\nBREAKING CHANGE: increases major"),
"v3.5.0": findNext(version3, false, "feat: inc major"),
"v0.4.5": findNext(version0a, false, false, "chore: should do nothing"),
"v0.4.6": findNext(version0a, false, false, "fix: inc patch"),
"v0.5.0": findNext(version0a, false, false, "feat: inc minor"),
"v1.0.0": findNext(version0b, false, false, "feat!: inc minor"),
"v0.6.0": findNext(version0b, true, false, "feat!: inc minor"),
"v1.2.3": findNext(version1, false, false, "chore: should do nothing"),
"v1.2.4": findNext(version1, false, true, "chore: is forcing patch, so should inc patch"),
"v1.3.0": findNext(version1, false, false, "feat: inc major"),
"v2.0.0": findNext(version1, false, true, "chore!: hashbang incs major"),
"v3.0.0": findNext(version2, false, false, "feat: something\nBREAKING CHANGE: increases major"),
"v3.5.0": findNext(version3, false, false, "feat: inc major"),
} {
t.Run(expected, func(t *testing.T) {
is.New(t).True(semver.MustParse(expected).Equal(&next)) // expected and next version should match
Expand All @@ -106,13 +107,13 @@ func TestCmd(t *testing.T) {
cmd := CurrentCmd
t.Run("version has meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false, false)
is.NoErr(err)
is.Equal("1.2.3-pre+123", v.String())
})
t.Run("version is clean", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("v1.2.3"), "v1.2.3", "doesnt matter", "nope", "", true)
v, err := nextVersion(cmd, semver.MustParse("v1.2.3"), "v1.2.3", "doesnt matter", "nope", "", false, true)
is.NoErr(err)
is.Equal("1.2.3", v.String())
})
Expand All @@ -122,25 +123,25 @@ func TestCmd(t *testing.T) {
cmd := MinorCmd
t.Run("no meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false, false)
is.NoErr(err)
is.Equal("1.3.0", v.String())
})
t.Run("build", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false, false)
is.NoErr(err)
is.Equal("1.3.0+124", v.String())
})
t.Run("prerel", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false, false)
is.NoErr(err)
is.Equal("1.3.0-alpha.1", v.String())
})
t.Run("all meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false, false)
is.NoErr(err)
is.Equal("1.3.0-alpha.2+125", v.String())
})
Expand All @@ -150,49 +151,49 @@ func TestCmd(t *testing.T) {
cmd := PatchCmd
t.Run("no meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "", "", false)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "", "", false, false)
is.NoErr(err)
is.Equal("1.2.4", v.String())
})
t.Run("previous had meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", false)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", false, false)
is.NoErr(err)
is.Equal("1.2.3", v.String())
})
t.Run("previous had meta, force", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", true)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", false, true)
is.NoErr(err)
is.Equal("1.2.4", v.String())
})
t.Run("previous had meta, force, add meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", true)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", false, true)
is.NoErr(err)
is.Equal("1.2.4-alpha.2+10", v.String())
})
t.Run("previous had meta, change it", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", false)
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", false, false)
is.NoErr(err)
is.Equal("1.2.3-alpha.2+10", v.String())
})
t.Run("build", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "124", "", false)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "124", "", false, false)
is.NoErr(err)
is.Equal("1.2.4+124", v.String())
})
t.Run("prerel", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.1", "", "", false)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.1", "", "", false, false)
is.NoErr(err)
is.Equal("1.2.4-alpha.1", v.String())
})
t.Run("all meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.2", "125", "", false)
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.2", "125", "", false, false)
is.NoErr(err)
is.Equal("1.2.4-alpha.2+125", v.String())
})
Expand All @@ -202,25 +203,25 @@ func TestCmd(t *testing.T) {
cmd := MajorCmd
t.Run("no meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false, false)
is.NoErr(err)
is.Equal("2.0.0", v.String())
})
t.Run("build", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false, false)
is.NoErr(err)
is.Equal("2.0.0+124", v.String())
})
t.Run("prerel", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false, false)
is.NoErr(err)
is.Equal("2.0.0-alpha.1", v.String())
})
t.Run("all meta", func(t *testing.T) {
is := is.New(t)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false)
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false, false)
is.NoErr(err)
is.Equal("2.0.0-alpha.2+125", v.String())
})
Expand All @@ -229,12 +230,12 @@ func TestCmd(t *testing.T) {
t.Run("errors", func(t *testing.T) {
t.Run("invalid build", func(t *testing.T) {
is := is.New(t)
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "", "+125", "", false)
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "", "+125", "", false, false)
is.True(err != nil)
})
t.Run("invalid prerelease", func(t *testing.T) {
is := is.New(t)
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "+aaa", "", "", false)
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "+aaa", "", "", false, false)
is.True(err != nil)
})
})
Expand Down
22 changes: 13 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ var (
forcePatchIncrement = nextCmd.Flag("force-patch-increment", "forces a patch version increment regardless of the commit message content").
Default("false").
Bool()
preventMajorIncrementOnV0 = nextCmd.Flag("no-increment-v0", "prevent major version increments when its still v0").
Default("false").
Bool()
)

func main() {
Expand All @@ -42,15 +45,16 @@ func main() {
cmd := kingpin.MustParse(app.Parse(os.Args[1:]))

version, err := svu.Version(svu.Options{
Cmd: cmd,
Pattern: *pattern,
Prefix: *prefix,
StripPrefix: *stripPrefix,
PreRelease: *preRelease,
Build: *build,
Directory: *directory,
TagMode: *tagMode,
ForcePatchIncrement: *forcePatchIncrement,
Cmd: cmd,
Pattern: *pattern,
Prefix: *prefix,
StripPrefix: *stripPrefix,
PreRelease: *preRelease,
Build: *build,
Directory: *directory,
TagMode: *tagMode,
ForcePatchIncrement: *forcePatchIncrement,
PreventMajorIncrementOnV0: *preventMajorIncrementOnV0,
})
app.FatalIfError(err, "")
fmt.Println(version)
Expand Down

0 comments on commit 7cf187a

Please sign in to comment.