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  }