Skip to content

Commit

Permalink
Merge pull request #6 from p1ass/add-bump-version-function
Browse files Browse the repository at this point in the history
Add function that bumps version according to the rule of semantic versioning
  • Loading branch information
p1ass authored Nov 12, 2019
2 parents f2415da + 093514c commit 401cadf
Show file tree
Hide file tree
Showing 2 changed files with 268 additions and 0 deletions.
84 changes: 84 additions & 0 deletions semver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package mikku

import (
"fmt"
"regexp"
"strconv"
"strings"
)

const (
semVerPrefix = "v"
)

const (
majorIdx = iota
minorIdx
patchIdx
)

type bumpType int

const (
major bumpType = iota + 1
minor
patch
version
)

var semVerReg = regexp.MustCompile(`^v([0-9]+)\.([0-9]+)\.([0-9]+)`)

func validSemver(ver string) bool {
return semVerReg.Match([]byte(ver))
}

func bumpVersion(tag string, typ bumpType) (string, error) {
tag = strings.TrimPrefix(tag, semVerPrefix)
splitTag := strings.Split(tag, ".")

versions, err := strsToInts(splitTag)
if err != nil {
return "", fmt.Errorf("strsToInts: %w", err)
}

switch typ {
case major:
versions[majorIdx]++
versions[minorIdx] = 0
versions[patchIdx] = 0
case minor:
versions[minorIdx]++
versions[patchIdx] = 0
case patch:
versions[patchIdx]++
default:
return "", fmt.Errorf("invalid bump type: %w", err)
}
return createSemanticVersion(versions), nil
}

func strsToInts(strs []string) ([]int, error) {
ints := make([]int, len(strs))

for idx, s := range strs {
converted, err := strconv.Atoi(s)
if err != nil {
return nil, fmt.Errorf("convert string to int: %w", err)
}
ints[idx] = converted
}
return ints, nil
}

func createSemanticVersion(versions []int) string {
sm := semVerPrefix

sm += strconv.Itoa(versions[0])

for _, v := range versions[1:] {
sm += "."
sm += strconv.Itoa(v)
}

return sm
}
184 changes: 184 additions & 0 deletions semver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package mikku

import (
"testing"

"github.com/google/go-cmp/cmp"
)

func Test_validSemver(t *testing.T) {
t.Parallel()

tests := []struct {
name string
ver string
want bool
}{
{
name: "v1.2.3",
ver: "v1.2.3",
want: true,
},
{
name: "v0.0.0",
ver: "v0.0.0",
want: true,
},
{
name: "v.2.3",
ver: "v.3.3",
want: false,
},
{
name: "v1..3",
ver: "v1..3",
want: false,
},
{
name: "v1.2.",
ver: "v1.2.",
want: false,
},
{
name: "1.2.3",
ver: "1.2.3",
want: false,
},
{
name: "v1.2.a",
ver: "1.2.a",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := validSemver(tt.ver); got != tt.want {
t.Errorf("validSemver() = %v, want %v", got, tt.want)
}
})
}
}

func Test_bumpVersion(t *testing.T) {
t.Parallel()

tests := []struct {
name string
tag string
typ bumpType
want string
wantErr bool
}{
{
name: "major bump",
tag: "v1.2.3",
typ: major,
want: "v2.0.0",
wantErr: false,
},
{
name: "minor bump",
tag: "v1.2.3",
typ: minor,
want: "v1.3.0",
wantErr: false,
},
{
name: "patch bump",
tag: "v1.2.3",
typ: patch,
want: "v1.2.4",
wantErr: false,
},
{
name: "not semver tag",
tag: "v1.2.a",
typ: patch,
want: "",
wantErr: true,
},
{
name: "no prefix tag",
tag: "1.2.3",
typ: patch,
want: "v1.2.4",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := bumpVersion(tt.tag, tt.typ)
if (err != nil) != tt.wantErr {
t.Errorf("bumpVersion() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("bumpVersion() = %v, want %v", got, tt.want)
}
})
}
}

func Test_createSemanticVersion(t *testing.T) {
t.Parallel()

tests := []struct {
name string
versions []int
want string
}{
{
name: "v1.0.0",
versions: []int{1, 0, 0},
want: "v1.0.0",
},
{
name: "v0.2.0",
versions: []int{0, 2, 0},
want: "v0.2.0",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := createSemanticVersion(tt.versions); got != tt.want {
t.Errorf("createSemanticVersion() = %v, want %v", got, tt.want)
}
})
}
}

func Test_strsToInts(t *testing.T) {
t.Parallel()

tests := []struct {
name string
strs []string
want []int
wantErr bool
}{
{
name: "1.0.0",
strs: []string{"1", "0", "0"},
want: []int{1, 0, 0},
wantErr: false,
},
{
name: "invalid string",
strs: []string{"1", "0", "invalid"},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := strsToInts(tt.strs)
if (err != nil) != tt.wantErr {
t.Errorf("strsToInts() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !cmp.Equal(got, tt.want) {
t.Errorf("strsToInts() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 401cadf

Please sign in to comment.