123 lines
4 KiB
Go
123 lines
4 KiB
Go
// Package semverbump provides a function to bump a semVer tag, extending golang.org/x/mod/semver library.
|
|
//
|
|
// The function Bump() takes a semVer tag and a bump type (major, minor, patch) and returns the new semVer tag.
|
|
// For example if the current semVer tag is v1.0.0 and the bump type is patch, the new semVer tag will be v1.0.1.
|
|
// If the current semVer tag is v1.0.1 and the bump type is minor, the new semVer tag will be v1.1.0
|
|
// (note that the patch version is reset to 0).
|
|
//
|
|
// Shortened semVer tags are supported, for example if the current semVer tag is v1.0 and the bump type is patch,
|
|
// the bumped semVer tag will be v1.0.1.
|
|
//
|
|
// If the current semVer tag does not have a leading v, it will be added.
|
|
// If it is an empty string, it will behave as if the current semVer tag is v0.0.0, e.g. if the bump type is patch,
|
|
// the bumped semVer tag will be v0.0.1.
|
|
//
|
|
// If the current semVer tag is invalid, such as "x.y.z", an error will be returned.
|
|
//
|
|
// The library currently does not handle pre-release or build metadata.
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"golang.org/x/mod/semver"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Bump takes a semVer tag and a bump type (major, minor, patch) and returns a new semVer tag
|
|
// whose value is incremented according to the bump type. If the current semVer tag does not have a leading v,
|
|
// it will be added. If it is an empty string, it will behave as if the current semVer tag is v0.0.0
|
|
// Invalid semVer tags will return an error.
|
|
func Bump(currentVersion, majorMinorPatch string) (string, error) {
|
|
if currentVersion == "" {
|
|
currentVersion = "v0.0.0"
|
|
} else {
|
|
if !semver.IsValid(currentVersion) {
|
|
if semver.IsValid("v" + currentVersion) {
|
|
currentVersion = "v" + currentVersion
|
|
} else {
|
|
return "", fmt.Errorf("invalid semVer tag '%s'", currentVersion)
|
|
}
|
|
}
|
|
// semVer lib allows v1 and v1.0, so check for that
|
|
if currentVersion == semver.Major(currentVersion) {
|
|
currentVersion = currentVersion + ".0.0"
|
|
}
|
|
if currentVersion == semver.MajorMinor(currentVersion) {
|
|
currentVersion = currentVersion + ".0"
|
|
}
|
|
}
|
|
// now we have a valid currentVersion
|
|
newMajor, newMinor, newPatch := majorMinorPatchFromSemVer(currentVersion)
|
|
if majorMinorPatch == "major" {
|
|
newMajor++
|
|
newMinor = 0
|
|
newPatch = 0
|
|
} else if majorMinorPatch == "minor" {
|
|
newMinor++
|
|
newPatch = 0
|
|
} else if majorMinorPatch == "patch" {
|
|
newPatch++
|
|
} else {
|
|
return "", fmt.Errorf("invalid arg for majorMinorPatch, expect 'major', 'minor' or 'patch', got '%s'", majorMinorPatch)
|
|
}
|
|
return semVerFromMajorMinorPatch(newMajor, newMinor, newPatch), nil
|
|
}
|
|
|
|
func majorMinorPatchFromSemVer(semVer string) (int, int, int) {
|
|
parts := strings.Split(semVer, ".")
|
|
major, _ := strconv.Atoi(strings.TrimPrefix(parts[0], "v"))
|
|
minor, _ := strconv.Atoi(parts[1])
|
|
patch, _ := strconv.Atoi(parts[2])
|
|
return major, minor, patch
|
|
}
|
|
|
|
func semVerFromMajorMinorPatch(major, minor, patch int) string {
|
|
return "v" + strconv.Itoa(major) + "." + strconv.Itoa(minor) + "." + strconv.Itoa(patch)
|
|
}
|
|
|
|
func BumpWithRollover(currentVersion, bumpType string) (string, error) {
|
|
if currentVersion == "" {
|
|
currentVersion = "v0.0.0"
|
|
} else {
|
|
if !semver.IsValid(currentVersion) {
|
|
if semver.IsValid("v" + currentVersion) {
|
|
currentVersion = "v" + currentVersion
|
|
} else {
|
|
return "", fmt.Errorf("invalid semVer tag '%s'", currentVersion)
|
|
}
|
|
}
|
|
if currentVersion == semver.Major(currentVersion) {
|
|
currentVersion = currentVersion + ".0.0"
|
|
}
|
|
if currentVersion == semver.MajorMinor(currentVersion) {
|
|
currentVersion = currentVersion + ".0"
|
|
}
|
|
}
|
|
|
|
major, minor, patch := majorMinorPatchFromSemVer(currentVersion)
|
|
|
|
switch bumpType {
|
|
case "major":
|
|
major++
|
|
minor = 0
|
|
patch = 0
|
|
|
|
case "minor":
|
|
minor++
|
|
patch = 0
|
|
|
|
case "patch":
|
|
patch++
|
|
// Handle rollover if patch reaches 10 (custom logic)
|
|
if patch >= 10 {
|
|
patch = 0
|
|
minor++
|
|
}
|
|
|
|
default:
|
|
return "", fmt.Errorf("invalid bump type, expected 'major', 'minor' or 'patch', got '%s'", bumpType)
|
|
}
|
|
|
|
return semVerFromMajorMinorPatch(major, minor, patch), nil
|
|
}
|