Skip to content

Commit 7cf187a

Browse files
committedMay 3, 2024··
feat!: gate v0 increment prevention
closes #153
1 parent a2b6361 commit 7cf187a

File tree

3 files changed

+71
-56
lines changed

3 files changed

+71
-56
lines changed
 

‎internal/svu/svu.go

+27-17
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ var (
2828
)
2929

3030
type Options struct {
31-
Cmd string
32-
Pattern string
33-
Prefix string
34-
StripPrefix bool
35-
PreRelease string
36-
Build string
37-
Directory string
38-
TagMode string
39-
ForcePatchIncrement bool
31+
Cmd string
32+
Pattern string
33+
Prefix string
34+
StripPrefix bool
35+
PreRelease string
36+
Build string
37+
Directory string
38+
TagMode string
39+
ForcePatchIncrement bool
40+
PreventMajorIncrementOnV0 bool
4041
}
4142

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

53-
result, err := nextVersion(string(opts.Cmd), current, tag, opts.PreRelease, opts.Build, opts.Directory, opts.ForcePatchIncrement)
54+
result, err := nextVersion(
55+
string(opts.Cmd),
56+
current,
57+
tag,
58+
opts.PreRelease,
59+
opts.Build,
60+
opts.Directory,
61+
opts.PreventMajorIncrementOnV0,
62+
opts.ForcePatchIncrement,
63+
)
5464
if err != nil {
5565
return "", fmt.Errorf("could not get next tag: '%s': %w", tag, err)
5666
}
@@ -61,12 +71,12 @@ func Version(opts Options) (string, error) {
6171
return opts.Prefix + result.String(), nil
6272
}
6373

64-
func nextVersion(cmd string, current *semver.Version, tag, preRelease, build, directory string, force bool) (semver.Version, error) {
74+
func nextVersion(cmd string, current *semver.Version, tag, preRelease, build, directory string, preventMajorIncrementOnV0, forcePatchIncrement bool) (semver.Version, error) {
6575
if cmd == CurrentCmd {
6676
return *current, nil
6777
}
6878

69-
if force {
79+
if forcePatchIncrement {
7080
c, err := current.SetMetadata("")
7181
if err != nil {
7282
return c, err
@@ -82,7 +92,7 @@ func nextVersion(cmd string, current *semver.Version, tag, preRelease, build, di
8292
var err error
8393
switch cmd {
8494
case NextCmd, PreReleaseCmd:
85-
result, err = findNextWithGitLog(current, tag, directory, force)
95+
result, err = findNextWithGitLog(current, tag, directory, preventMajorIncrementOnV0, forcePatchIncrement)
8696
case MajorCmd:
8797
result = current.IncMajor()
8898
case MinorCmd:
@@ -172,13 +182,13 @@ func getCurrentVersion(tag, prefix string) (*semver.Version, error) {
172182
return current, err
173183
}
174184

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

181-
return findNext(current, forcePatchIncrement, log), nil
191+
return findNext(current, preventMajorIncrementOnV0, forcePatchIncrement, log), nil
182192
}
183193

184194
func isBreaking(log string) bool {
@@ -193,9 +203,9 @@ func isPatch(log string) bool {
193203
return patch.MatchString(log)
194204
}
195205

196-
func findNext(current *semver.Version, forcePatchIncrement bool, log string) semver.Version {
206+
func findNext(current *semver.Version, preventMajorIncrementOnV0, forcePatchIncrement bool, log string) semver.Version {
197207
if isBreaking(log) {
198-
if current.Major() == 0 {
208+
if current.Major() == 0 && preventMajorIncrementOnV0 {
199209
return current.IncMinor()
200210
}
201211
return current.IncMajor()

‎internal/svu/svu_test.go

+31-30
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,17 @@ func TestFindNext(t *testing.T) {
8383
version2 := semver.MustParse("v2.4.12")
8484
version3 := semver.MustParse("v3.4.5-beta34+ads")
8585
for expected, next := range map[string]semver.Version{
86-
"v0.4.5": findNext(version0a, false, "chore: should do nothing"),
87-
"v0.4.6": findNext(version0a, false, "fix: inc patch"),
88-
"v0.5.0": findNext(version0a, false, "feat: inc minor"),
89-
"v0.6.0": findNext(version0b, false, "feat!: inc minor"),
90-
"v1.2.3": findNext(version1, false, "chore: should do nothing"),
91-
"v1.2.4": findNext(version1, true, "chore: is forcing patch, so should inc patch"),
92-
"v1.3.0": findNext(version1, false, "feat: inc major"),
93-
"v2.0.0": findNext(version1, true, "chore!: hashbang incs major"),
94-
"v3.0.0": findNext(version2, false, "feat: something\nBREAKING CHANGE: increases major"),
95-
"v3.5.0": findNext(version3, false, "feat: inc major"),
86+
"v0.4.5": findNext(version0a, false, false, "chore: should do nothing"),
87+
"v0.4.6": findNext(version0a, false, false, "fix: inc patch"),
88+
"v0.5.0": findNext(version0a, false, false, "feat: inc minor"),
89+
"v1.0.0": findNext(version0b, false, false, "feat!: inc minor"),
90+
"v0.6.0": findNext(version0b, true, false, "feat!: inc minor"),
91+
"v1.2.3": findNext(version1, false, false, "chore: should do nothing"),
92+
"v1.2.4": findNext(version1, false, true, "chore: is forcing patch, so should inc patch"),
93+
"v1.3.0": findNext(version1, false, false, "feat: inc major"),
94+
"v2.0.0": findNext(version1, false, true, "chore!: hashbang incs major"),
95+
"v3.0.0": findNext(version2, false, false, "feat: something\nBREAKING CHANGE: increases major"),
96+
"v3.5.0": findNext(version3, false, false, "feat: inc major"),
9697
} {
9798
t.Run(expected, func(t *testing.T) {
9899
is.New(t).True(semver.MustParse(expected).Equal(&next)) // expected and next version should match
@@ -106,13 +107,13 @@ func TestCmd(t *testing.T) {
106107
cmd := CurrentCmd
107108
t.Run("version has meta", func(t *testing.T) {
108109
is := is.New(t)
109-
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false)
110+
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false, false)
110111
is.NoErr(err)
111112
is.Equal("1.2.3-pre+123", v.String())
112113
})
113114
t.Run("version is clean", func(t *testing.T) {
114115
is := is.New(t)
115-
v, err := nextVersion(cmd, semver.MustParse("v1.2.3"), "v1.2.3", "doesnt matter", "nope", "", true)
116+
v, err := nextVersion(cmd, semver.MustParse("v1.2.3"), "v1.2.3", "doesnt matter", "nope", "", false, true)
116117
is.NoErr(err)
117118
is.Equal("1.2.3", v.String())
118119
})
@@ -122,25 +123,25 @@ func TestCmd(t *testing.T) {
122123
cmd := MinorCmd
123124
t.Run("no meta", func(t *testing.T) {
124125
is := is.New(t)
125-
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false)
126+
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false, false)
126127
is.NoErr(err)
127128
is.Equal("1.3.0", v.String())
128129
})
129130
t.Run("build", func(t *testing.T) {
130131
is := is.New(t)
131-
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false)
132+
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false, false)
132133
is.NoErr(err)
133134
is.Equal("1.3.0+124", v.String())
134135
})
135136
t.Run("prerel", func(t *testing.T) {
136137
is := is.New(t)
137-
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false)
138+
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false, false)
138139
is.NoErr(err)
139140
is.Equal("1.3.0-alpha.1", v.String())
140141
})
141142
t.Run("all meta", func(t *testing.T) {
142143
is := is.New(t)
143-
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false)
144+
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false, false)
144145
is.NoErr(err)
145146
is.Equal("1.3.0-alpha.2+125", v.String())
146147
})
@@ -150,49 +151,49 @@ func TestCmd(t *testing.T) {
150151
cmd := PatchCmd
151152
t.Run("no meta", func(t *testing.T) {
152153
is := is.New(t)
153-
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "", "", false)
154+
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "", "", false, false)
154155
is.NoErr(err)
155156
is.Equal("1.2.4", v.String())
156157
})
157158
t.Run("previous had meta", func(t *testing.T) {
158159
is := is.New(t)
159-
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", false)
160+
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", false, false)
160161
is.NoErr(err)
161162
is.Equal("1.2.3", v.String())
162163
})
163164
t.Run("previous had meta, force", func(t *testing.T) {
164165
is := is.New(t)
165-
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", true)
166+
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3", "", "", "", false, true)
166167
is.NoErr(err)
167168
is.Equal("1.2.4", v.String())
168169
})
169170
t.Run("previous had meta, force, add meta", func(t *testing.T) {
170171
is := is.New(t)
171-
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", true)
172+
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", false, true)
172173
is.NoErr(err)
173174
is.Equal("1.2.4-alpha.2+10", v.String())
174175
})
175176
t.Run("previous had meta, change it", func(t *testing.T) {
176177
is := is.New(t)
177-
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", false)
178+
v, err := nextVersion(cmd, semver.MustParse("1.2.3-alpha.1+1"), "v1.2.3-alpha.1+1", "alpha.2", "10", "", false, false)
178179
is.NoErr(err)
179180
is.Equal("1.2.3-alpha.2+10", v.String())
180181
})
181182
t.Run("build", func(t *testing.T) {
182183
is := is.New(t)
183-
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "124", "", false)
184+
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "", "124", "", false, false)
184185
is.NoErr(err)
185186
is.Equal("1.2.4+124", v.String())
186187
})
187188
t.Run("prerel", func(t *testing.T) {
188189
is := is.New(t)
189-
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.1", "", "", false)
190+
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.1", "", "", false, false)
190191
is.NoErr(err)
191192
is.Equal("1.2.4-alpha.1", v.String())
192193
})
193194
t.Run("all meta", func(t *testing.T) {
194195
is := is.New(t)
195-
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.2", "125", "", false)
196+
v, err := nextVersion(cmd, semver.MustParse("1.2.3"), "v1.2.3", "alpha.2", "125", "", false, false)
196197
is.NoErr(err)
197198
is.Equal("1.2.4-alpha.2+125", v.String())
198199
})
@@ -202,25 +203,25 @@ func TestCmd(t *testing.T) {
202203
cmd := MajorCmd
203204
t.Run("no meta", func(t *testing.T) {
204205
is := is.New(t)
205-
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false)
206+
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "", "", false, false)
206207
is.NoErr(err)
207208
is.Equal("2.0.0", v.String())
208209
})
209210
t.Run("build", func(t *testing.T) {
210211
is := is.New(t)
211-
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false)
212+
v, err := nextVersion(cmd, ver(), "v1.2.3", "", "124", "", false, false)
212213
is.NoErr(err)
213214
is.Equal("2.0.0+124", v.String())
214215
})
215216
t.Run("prerel", func(t *testing.T) {
216217
is := is.New(t)
217-
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false)
218+
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.1", "", "", false, false)
218219
is.NoErr(err)
219220
is.Equal("2.0.0-alpha.1", v.String())
220221
})
221222
t.Run("all meta", func(t *testing.T) {
222223
is := is.New(t)
223-
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false)
224+
v, err := nextVersion(cmd, ver(), "v1.2.3", "alpha.2", "125", "", false, false)
224225
is.NoErr(err)
225226
is.Equal("2.0.0-alpha.2+125", v.String())
226227
})
@@ -229,12 +230,12 @@ func TestCmd(t *testing.T) {
229230
t.Run("errors", func(t *testing.T) {
230231
t.Run("invalid build", func(t *testing.T) {
231232
is := is.New(t)
232-
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "", "+125", "", false)
233+
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "", "+125", "", false, false)
233234
is.True(err != nil)
234235
})
235236
t.Run("invalid prerelease", func(t *testing.T) {
236237
is := is.New(t)
237-
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "+aaa", "", "", false)
238+
_, err := nextVersion(MinorCmd, semver.MustParse("1.2.3"), "v1.2.3", "+aaa", "", "", false, false)
238239
is.True(err != nil)
239240
})
240241
})

‎main.go

+13-9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ var (
3232
forcePatchIncrement = nextCmd.Flag("force-patch-increment", "forces a patch version increment regardless of the commit message content").
3333
Default("false").
3434
Bool()
35+
preventMajorIncrementOnV0 = nextCmd.Flag("no-increment-v0", "prevent major version increments when its still v0").
36+
Default("false").
37+
Bool()
3538
)
3639

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

4447
version, err := svu.Version(svu.Options{
45-
Cmd: cmd,
46-
Pattern: *pattern,
47-
Prefix: *prefix,
48-
StripPrefix: *stripPrefix,
49-
PreRelease: *preRelease,
50-
Build: *build,
51-
Directory: *directory,
52-
TagMode: *tagMode,
53-
ForcePatchIncrement: *forcePatchIncrement,
48+
Cmd: cmd,
49+
Pattern: *pattern,
50+
Prefix: *prefix,
51+
StripPrefix: *stripPrefix,
52+
PreRelease: *preRelease,
53+
Build: *build,
54+
Directory: *directory,
55+
TagMode: *tagMode,
56+
ForcePatchIncrement: *forcePatchIncrement,
57+
PreventMajorIncrementOnV0: *preventMajorIncrementOnV0,
5458
})
5559
app.FatalIfError(err, "")
5660
fmt.Println(version)

0 commit comments

Comments
 (0)
Please sign in to comment.