github.com/kubeshop/testkube@v1.17.23/pkg/semver/version.go (about) 1 package semver 2 3 import ( 4 "fmt" 5 "regexp" 6 "sort" 7 "strconv" 8 "strings" 9 10 "github.com/Masterminds/semver" 11 ) 12 13 const ( 14 // Major version 15 Major = "major" 16 // Minor version 17 Minor = "minor" 18 // Patch version 19 Patch = "patch" 20 ) 21 22 // NextPrerelease returns pre-release version e.g. current -> 0.10.1; nextPrerelease -> 0.10.2-beta001 23 func NextPrerelease(currentVersion string) (string, error) { 24 version, err := semver.NewVersion(currentVersion) 25 if err != nil { 26 return "", err 27 } 28 29 if version.Prerelease() != "" { 30 version = bumpPrerelease(version) 31 return version.String(), nil 32 } 33 34 return "", nil 35 36 } 37 38 // IsPrerelease detects if release is prerelease 39 func IsPrerelease(currentVersion string) bool { 40 version, err := semver.NewVersion(currentVersion) 41 if err != nil { 42 return false 43 } 44 45 return version.Prerelease() != "" 46 47 } 48 49 // Next returns next generated semver based on version position 50 func Next(currentVersion, kind string) (string, error) { 51 err := validateVersionPostion(kind) 52 if err != nil { 53 return "", err 54 } 55 56 version, err := semver.NewVersion(currentVersion) 57 if err != nil { 58 return "", err 59 } 60 var inc semver.Version 61 62 switch kind { 63 case Major: 64 inc = version.IncMajor() 65 case Minor: 66 inc = version.IncMinor() 67 case Patch: 68 inc = version.IncPatch() 69 default: 70 return "", fmt.Errorf("invalid position" + kind) 71 } 72 73 return inc.String(), nil 74 } 75 76 // bumpPrerelease bumps number in versions like 0.0.1-alpha2 or 0.0.3-omega4 77 func bumpPrerelease(version *semver.Version) *semver.Version { 78 prerelease := version.Prerelease() 79 r := regexp.MustCompile("[0-9]+$") 80 81 matches := r.FindStringSubmatch(prerelease) 82 if len(matches) == 1 { 83 num, err := strconv.Atoi(matches[0]) 84 if err == nil { 85 num = num + 1 86 prerelease = strings.Replace(prerelease, matches[0], fmt.Sprintf("%03d", num), -1) 87 v, _ := version.SetPrerelease(prerelease) 88 return &v 89 90 } 91 } 92 93 return version 94 } 95 96 // Lt checks if version1 is less-than version2, returns error in case of invalid version string 97 func Lt(version1, version2 string) (bool, error) { 98 v1, err := semver.NewVersion(version1) 99 if err != nil { 100 return false, err 101 } 102 v2, err := semver.NewVersion(version2) 103 if err != nil { 104 return false, err 105 } 106 107 return v1.LessThan(v2), nil 108 } 109 110 // Lte checks if version1 is less-than or equal version2, returns error in case of invalid version string 111 func Lte(version1, version2 string) (bool, error) { 112 ok, err := Lt(version1, version2) 113 if err != nil { 114 return false, err 115 } 116 117 return ok || version1 == version2, nil 118 } 119 120 func validateVersionPostion(kind string) error { 121 if kind == Major || kind == Minor || kind == Patch { 122 return nil 123 } 124 125 return fmt.Errorf("invalid version kind: %s: use one of major|minor|patch", kind) 126 } 127 128 // GetNewest returns greatest version from passed versions list 129 func GetNewest(versions []string) string { 130 semversions := []*semver.Version{} 131 for _, ver := range versions { 132 v, err := semver.NewVersion(ver) 133 134 if err == nil { 135 semversions = append(semversions, v) 136 } 137 } 138 139 sort.Slice(semversions, func(i, j int) bool { 140 return semversions[j].LessThan(semversions[i]) 141 }) 142 143 return semversions[0].String() 144 }