Skip to content

Commit

Permalink
feat: Add calver modifier and prerelease
Browse files Browse the repository at this point in the history
  • Loading branch information
David MICHENEAU committed Oct 30, 2024
1 parent 1025b73 commit 5cd75ab
Show file tree
Hide file tree
Showing 6 changed files with 368 additions and 69 deletions.
2 changes: 1 addition & 1 deletion api/v1alpha1/image_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ type (
Name string `json:"name"`

// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=calver-major;calver-minor;calver-patch;semver-major;semver-minor;semver-patch;regex;always
// +kubebuilder:validation:Enum=calver-major;calver-minor;calver-patch;calver-modifier;calver-prerelease;semver-major;semver-minor;semver-patch;regex;always
Type rules.Name `json:"type"`

// +kubebuilder:validation:Optional
Expand Down
53 changes: 49 additions & 4 deletions docs/rules/calver.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,81 @@ hide:
The `calver` rule allows you to define a rule that will be executed when the image is updated with a new calver version.
It follows the [Calendar Versioning](https://calver.org/) specification.
A lot of options are available to match the version you want to update.
The format of the version [following this logic regex](https://regex101.com/r/25eVYJ/2).

The format of the version [following this logic regex](https://regex101.com/r/25eVYJ/7).
```regex
^([0-9]{4}|[0-9]{2})(\.[0-9]{1,2})?(\.[0-9]{1,2})?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$
```

Format:
```s
# YYYY.MM.XX
2024
2024-dev
2024.01
2024.01-dev
2024.01.01
2024.01.01-dev
# YY.MM.XX
24
24-dev
24.01
24.01-dev
# YY.M.X
24.1
24.1.1
24.1.1-dev
2024.01.01-dev.prerelease
```


* `calver-major`: Update the image with the latest major version.
* `calver-minor`: Update the image with the latest minor version.
* `calver-patch`: Update the image with the latest patch version.
* `calver-modifier`: Update the image with the latest modifier version.(dev, alpha, beta, rc, etc.)
* `calver-prerelease`: Update the image with the latest prerelease version.

**`calver-major`** is the most restrictive and will only update the image when the major version is updated [calver documentation](https://calver.org/).
``` { .yaml .no-copy title="calver rule" }
version: 2024.0.0
Match: >=2024.*.* # (1)
Match: >=2025.*.* # (1)
```

1. :man_raising_hand: For more information about the calver range, you can check the [calver documentation](https://calver.org/).

**`calver-minor`** is less restrictive and will update the image when the minor version is updated.
``` { .yaml .no-copy title="calver rule" }
version: 2024.0.0
Match: >=2024.1.* <2 # (1)
Match: >=2024.1.* # (1)
```

1. :man_raising_hand: For more information about the calver range, you can check the [calver documentation](https://calver.org/).

**`calver-patch`** is the least restrictive and will update the image when the patch version is updated.
``` { .yaml .no-copy title="calver rule" }
version: 2024.0.0
Match: >=2024.0.1 <2024.1.0 # (1)
Match: >=2024.0.1 and < 2024.1.0 # (1)
```

1. :man_raising_hand: For more information about the calver range, you can check the [calver documentation](https://calver.org/).

**`calver-modifier`** is the least restrictive and will update the image when the modifier version is updated.
``` { .yaml .no-copy title="calver rule" }
version: 2024.0.0-dev
Match: >*.*.*-dev # (1)
```

**`calver-prerelease`** is the least restrictive and will update the image when the prerelease version is updated.
``` { .yaml .no-copy title="calver rule" }
version: 2024.0.0-dev.1
Match: >2024.0.0-dev.*
```

2. :man_raising_hand: For more information about the calver range, you can check the [calver documentation](https://calver.org/).

## Who to use

Create an `Image` resource with the `calver` rule.
Expand Down
77 changes: 74 additions & 3 deletions internal/rules/calver.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package rules

import (
"strings"

"github.com/shipengqi/vc"

"github.com/orange-cloudavenue/kube-image-updater/internal/log"
Expand All @@ -21,12 +23,24 @@ type (
calverPatch struct {
rule
}

// calverModifier - The modifier is an optional part of the version.
calverModifier struct {
rule
}

// calverPrerelease - The prerelease is an optional part of the version.
calverPrerelease struct {
rule
}
)

func init() {
register(CalverMajor, &calverMajor{})
register(CalverMinor, &calverMinor{})
register(CalverPatch, &calverPatch{})
register(CalverModifier, &calverModifier{})
register(CalverPrerelease, &calverPrerelease{})
}

func (c *calverMajor) Evaluate() (matchWithRule bool, newTag string, err error) {
Expand All @@ -43,7 +57,7 @@ func (c *calverMajor) Evaluate() (matchWithRule bool, newTag string, err error)
continue
}

if cv.Major() > actualCV.Major() {
if cv.Major() > actualCV.Major() && actualCV.Prerelease() == "" && cv.Prerelease() == "" {
return true, t, nil
}
}
Expand All @@ -65,7 +79,7 @@ func (c *calverMinor) Evaluate() (matchWithRule bool, newTag string, err error)
continue
}

if cv.Minor() > actualCV.Minor() && cv.Major() == actualCV.Major() {
if cv.Minor() > actualCV.Minor() && cv.Major() == actualCV.Major() && actualCV.Prerelease() == "" && cv.Prerelease() == "" {
return true, t, nil
}
}
Expand All @@ -87,10 +101,67 @@ func (c *calverPatch) Evaluate() (matchWithRule bool, newTag string, err error)
continue
}

if cv.Patch() > actualCV.Patch() && cv.Minor() == actualCV.Minor() && cv.Major() == actualCV.Major() {
if cv.Patch() > actualCV.Patch() && cv.Minor() == actualCV.Minor() && cv.Major() == actualCV.Major() && actualCV.Prerelease() == "" && cv.Prerelease() == "" {
return true, t, nil
}
}

return false, "", nil
}

func (c *calverModifier) Evaluate() (matchWithRule bool, newTag string, err error) {
actualCV, err := vc.NewCalVerStr(c.actualTag)
if err != nil {
log.WithError(err).WithField("tag", c.actualTag).Error("Error parsing actual tag")
return false, "", err
}

for _, t := range c.tags {
cv, err := vc.NewCalVerStr(t)
if err != nil {
log.WithError(err).WithField("tag", t).Error("Error parsing tag")
continue
}

if cv.Gt(actualCV) && extractPrerelease(cv.Prerelease()) == "" && extractPrerelease(actualCV.Prerelease()) == "" && cv.Patch() == actualCV.Patch() && cv.Minor() == actualCV.Minor() && cv.Major() == actualCV.Major() {
return true, t, nil
}
}

return false, "", nil
}

func (c *calverPrerelease) Evaluate() (matchWithRule bool, newTag string, err error) {
actualCV, err := vc.NewCalVerStr(c.actualTag)
if err != nil {
log.WithError(err).WithField("tag", c.actualTag).Error("Error parsing actual tag")
return false, "", err
}

for _, t := range c.tags {
cv, err := vc.NewCalVerStr(t)
if err != nil {
log.WithError(err).WithField("tag", t).Error("Error parsing tag")
continue
}

if cv.Prerelease() > actualCV.Prerelease() && extractModifier(cv.Prerelease()) == extractModifier(actualCV.Prerelease()) && cv.Patch() == actualCV.Patch() && cv.Minor() == actualCV.Minor() && cv.Major() == actualCV.Major() {
return true, t, nil
}
}

return false, "", nil
}

func extractModifier(s string) string {
x := strings.Split(s, ".")
return x[0]
}

func extractPrerelease(s string) string {
x := strings.Split(s, ".")
if len(x) < 2 {
return ""
}
return x[1]
}
Loading

0 comments on commit 5cd75ab

Please sign in to comment.