Skip to content

Update version handling to support more prerelease types #220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 43 additions & 18 deletions pkg/auto/chart_bump.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"log/slog"
"os"
"os/exec"
"regexp"
"strings"

"github.com/rancher/charts-build-scripts/pkg/charts"
Expand Down Expand Up @@ -61,6 +62,12 @@ var (
errBumpVersion = errors.New("version to bump is not greater than the latest version")
)

var prereleaseRegex = regexp.MustCompile(`(?i)[-.]?(rc|alpha|beta)[-.]?\d*`)

func isPrerelease(version string) bool {
return prereleaseRegex.MatchString(version)
}

/*******************************************************
*
* This file can be understood in 2 sections:
Expand Down Expand Up @@ -336,19 +343,18 @@ func (b *Bump) BumpChart(ctx context.Context, versionOverride string, multiRCs b
}

if !multiRCs {
if strings.Contains(b.versions.toRelease.txt, "-rc") {

listRCVersions, err := listRCVersions(b.versions.toRelease.txt, b.assetsVersionsMap[b.targetChart])
if isPrerelease(b.versions.toRelease.txt) {
prereleaseVersions, err := listPrereleaseVersions(b.versions.toRelease.txt, b.assetsVersionsMap[b.targetChart])
if err != nil {
logger.Log(ctx, slog.LevelError, "error while listing RC versions", logger.Err(err))
logger.Log(ctx, slog.LevelError, "error while listing prerelease versions", logger.Err(err))
return err
}

if len(listRCVersions) > 0 {
for _, rcVersion := range listRCVersions {
logger.Log(ctx, slog.LevelInfo, "removing RC version", slog.String("rcVersion", rcVersion))
if err := makeRemove(rcVersion, targetCharts, git); err != nil {
logger.Log(ctx, slog.LevelError, "error while removing -RC version", logger.Err(err))
if len(prereleaseVersions) > 0 {
for _, prereleaseVersion := range prereleaseVersions {
logger.Log(ctx, slog.LevelInfo, "removing prerelease version", slog.String("prereleaseVersion", prereleaseVersion))
if err := makeRemove(prereleaseVersion, targetCharts, git); err != nil {
logger.Log(ctx, slog.LevelError, "error while removing prerelease version", logger.Err(err))
return err
}
}
Expand Down Expand Up @@ -547,19 +553,38 @@ func checkBumpAppVersion(ctx context.Context, bumpAppVersion *string, versions [
return false, nil
}

func listRCVersions(rcVersion string, assets []lifecycle.Asset) ([]string, error) {
idx := strings.Index(rcVersion, "-rc")
if idx == -1 {
return nil, fmt.Errorf("invalid rcVersion format: %s", rcVersion)
// listPrereleaseVersions finds all existing prerelease versions that match the same base version and prerelease type
func listPrereleaseVersions(version string, assets []lifecycle.Asset) ([]string, error) {
if !isPrerelease(version) {
return nil, fmt.Errorf("no prerelease pattern found in version: %s", version)
}

// Extract the prerelease type from the version
matches := prereleaseRegex.FindStringSubmatch(strings.ToLower(version))
if len(matches) < 2 {
return nil, fmt.Errorf("could not extract prerelease type from version: %s", version)
}
prereleaseType := matches[1] // This will be "rc", "alpha", or "beta"

// Extract base version (everything before the prerelease pattern)
baseVersionEnd := prereleaseRegex.FindStringIndex(strings.ToLower(version))
if baseVersionEnd == nil {
return nil, fmt.Errorf("could not find prerelease pattern in version: %s", version)
}
rcVersionCheckStr := rcVersion[:idx+len("-rc")]
baseVersion := strings.ToLower(version[:baseVersionEnd[0]])

prereleaseVersions := []string{}

var rcVersions []string
for _, asset := range assets {
if strings.Contains(asset.Version, rcVersionCheckStr) {
rcVersions = append(rcVersions, asset.Version)
assetLower := strings.ToLower(asset.Version)

// Check if this asset version starts with the same base version
// and contains the same prerelease type
if strings.HasPrefix(assetLower, baseVersion) &&
strings.Contains(assetLower, prereleaseType) {
prereleaseVersions = append(prereleaseVersions, asset.Version)
}
}

return rcVersions, nil
return prereleaseVersions, nil
}
129 changes: 129 additions & 0 deletions pkg/auto/chart_bump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package auto

import (
"context"
"reflect"
"testing"

"github.com/blang/semver"
"github.com/rancher/charts-build-scripts/pkg/charts"
"github.com/rancher/charts-build-scripts/pkg/lifecycle"
"github.com/rancher/charts-build-scripts/pkg/options"
"github.com/rancher/charts-build-scripts/pkg/puller"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -513,3 +515,130 @@ func Test_parsePackageYaml(t *testing.T) {
})
}
}

func Test_listPrereleaseVersions(t *testing.T) {
type args struct {
version string
assets []lifecycle.Asset
}
tests := []struct {
name string
args args
want []string
wantErr bool
}{
{
name: "RC version with hyphen",
args: args{
version: "103.0.0+up1.0.0-rc1",
assets: []lifecycle.Asset{
{Version: "103.0.0+up1.0.0-rc1"},
{Version: "103.0.0+up1.0.0-rc2"},
{Version: "103.0.0+up1.0.0"},
{Version: "103.0.0+up1.1.0-rc1"},
},
},
want: []string{"103.0.0+up1.0.0-rc1", "103.0.0+up1.0.0-rc2"},
wantErr: false,
},
{
name: "RC version with dot",
args: args{
version: "103.0.0+up1.0.0-rc.1",
assets: []lifecycle.Asset{
{Version: "103.0.0+up1.0.0-rc.1"},
{Version: "103.0.0+up1.0.0-rc.2"},
{Version: "103.0.0+up1.0.0"},
{Version: "103.0.0+up1.1.0-rc.1"},
},
},
want: []string{"103.0.0+up1.0.0-rc.1", "103.0.0+up1.0.0-rc.2"},
wantErr: false,
},
{
name: "Alpha version with hyphen",
args: args{
version: "103.0.0+up1.0.0-alpha1",
assets: []lifecycle.Asset{
{Version: "103.0.0+up1.0.0-alpha1"},
{Version: "103.0.0+up1.0.0-alpha2"},
{Version: "103.0.0+up1.0.0-beta1"},
{Version: "103.0.0+up1.0.0"},
},
},
want: []string{"103.0.0+up1.0.0-alpha1", "103.0.0+up1.0.0-alpha2"},
wantErr: false,
},
{
name: "Beta version with dot",
args: args{
version: "103.0.0+up1.0.0-beta.3",
assets: []lifecycle.Asset{
{Version: "103.0.0+up1.0.0-beta.1"},
{Version: "103.0.0+up1.0.0-beta.2"},
{Version: "103.0.0+up1.0.0-beta.3"},
{Version: "103.0.0+up1.0.0"},
},
},
want: []string{"103.0.0+up1.0.0-beta.1", "103.0.0+up1.0.0-beta.2", "103.0.0+up1.0.0-beta.3"},
wantErr: false,
},
{
name: "RC version without hyphen",
args: args{
version: "103.0.0+up1.0.0rc1",
assets: []lifecycle.Asset{
{Version: "103.0.0+up1.0.0rc1"},
{Version: "103.0.0+up1.0.0rc2"},
{Version: "103.0.0+up1.0.0"},
},
},
want: []string{"103.0.0+up1.0.0rc1", "103.0.0+up1.0.0rc2"},
wantErr: false,
},
{
name: "Case insensitive",
args: args{
version: "103.0.0+up1.0.0-RC1",
assets: []lifecycle.Asset{
{Version: "103.0.0+up1.0.0-rc1"},
{Version: "103.0.0+up1.0.0-RC2"},
{Version: "103.0.0+up1.0.0"},
},
},
want: []string{"103.0.0+up1.0.0-rc1", "103.0.0+up1.0.0-RC2"},
wantErr: false,
},
{
name: "No prerelease pattern",
args: args{
version: "103.0.0+up1.0.0",
assets: []lifecycle.Asset{{Version: "103.0.0+up1.0.0"}},
},
want: nil,
wantErr: true,
},
{
name: "No matching assets",
args: args{
version: "103.0.0+up1.0.0-rc1",
assets: []lifecycle.Asset{{Version: "103.0.0+up2.0.0-rc1"}},
},
want: []string{},
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := listPrereleaseVersions(tt.args.version, tt.args.assets)
if (err != nil) != tt.wantErr {
t.Errorf("listPrereleaseVersions() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("listPrereleaseVersions() = %v, want %v", got, tt.want)
}
})
}
}
Loading