keel/internal/policy/semver.go

108 lines
2.4 KiB
Go

package policy
import (
"errors"
"fmt"
"strings"
"github.com/Masterminds/semver"
)
// SemverPolicyType - policy type
type SemverPolicyType int
var (
ErrNoMajorMinorPatchElementsFound = errors.New("No Major.Minor.Patch elements found")
)
// available policies
const (
SemverPolicyTypeNone SemverPolicyType = iota
SemverPolicyTypeAll
SemverPolicyTypeMajor
SemverPolicyTypeMinor
SemverPolicyTypePatch
)
func (t SemverPolicyType) String() string {
switch t {
case SemverPolicyTypeNone:
return "none"
case SemverPolicyTypeAll:
return "all"
case SemverPolicyTypeMajor:
return "major"
case SemverPolicyTypeMinor:
return "minor"
case SemverPolicyTypePatch:
return "patch"
default:
return ""
}
}
func NewSemverPolicy(spt SemverPolicyType, matchPreRelease bool) *SemverPolicy {
return &SemverPolicy{
spt: spt,
matchPreRelease: matchPreRelease,
}
}
type SemverPolicy struct {
spt SemverPolicyType
matchPreRelease bool
}
func (sp *SemverPolicy) ShouldUpdate(current, new string) (bool, error) {
return shouldUpdate(sp.spt, sp.matchPreRelease, current, new)
}
func (sp *SemverPolicy) Name() string {
return sp.spt.String()
}
func (sp *SemverPolicy) Type() PolicyType { return PolicyTypeSemver }
func shouldUpdate(spt SemverPolicyType, matchPreRelease bool, current, new string) (bool, error) {
if current == "latest" {
return true, nil
}
parts := strings.SplitN(new, ".", 3)
if len(parts) != 2 && len(parts) != 3 {
return false, ErrNoMajorMinorPatchElementsFound
}
currentVersion, err := semver.NewVersion(current)
if err != nil {
return false, fmt.Errorf("failed to parse current version: %s", err)
}
newVersion, err := semver.NewVersion(new)
if err != nil {
return false, fmt.Errorf("failed to parse new version: %s", err)
}
// Do not enforce pre-release match when either:
// - All policy
// - matchPreRelease set to false
if currentVersion.Prerelease() != newVersion.Prerelease() && spt != SemverPolicyTypeAll && matchPreRelease {
return false, nil
}
// new version is not higher than current - do nothing
if !currentVersion.LessThan(newVersion) {
return false, nil
}
switch spt {
case SemverPolicyTypeAll, SemverPolicyTypeMajor:
return true, nil
case SemverPolicyTypeMinor:
return newVersion.Major() == currentVersion.Major(), nil
case SemverPolicyTypePatch:
return newVersion.Major() == currentVersion.Major() && newVersion.Minor() == currentVersion.Minor(), nil
}
return false, nil
}