Improve semver parsing robustness for versions without 'v' prefix
Replace chartify.FindSemVerInfo with enhanced findSemVerInfo function that handles versions with or without 'v' prefix. This addresses the "unable to find semver info in 5.7.1" error by ensuring consistent version parsing regardless of input format. - Add findSemVerInfo function with flexible regex pattern - Update parseHelmVersion to use enhanced version parsing - Add comprehensive test cases for various version formats including issue #2124 scenarios - Remove unused chartify import from helmexec package Co-authored-by: yxxhero <11087727+yxxhero@users.noreply.github.com>
This commit is contained in:
parent
6c86962827
commit
9c1db04e27
|
|
@ -7,12 +7,12 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/helmfile/chartify"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
|
|
@ -64,21 +64,44 @@ func NewLogger(writer io.Writer, logLevel string) *zap.SugaredLogger {
|
|||
return zap.New(core).Sugar()
|
||||
}
|
||||
|
||||
// findSemVerInfo extracts semantic version information from a version string.
|
||||
// Unlike chartify.FindSemVerInfo, this function handles versions with or without "v" prefix
|
||||
// and ensures the returned version always has the "v" prefix for consistency.
|
||||
func findSemVerInfo(version string) (string, error) {
|
||||
// Trim whitespace and clean the version string
|
||||
version = strings.TrimSpace(version)
|
||||
|
||||
// Regex pattern that matches semantic versions with optional "v" prefix
|
||||
// This is based on chartify's semVerRegex but made more flexible
|
||||
semVerRegex := `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
|
||||
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
||||
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
|
||||
|
||||
// Try to find a version match
|
||||
re := regexp.MustCompile(semVerRegex)
|
||||
matches := re.FindStringSubmatch(version)
|
||||
|
||||
if len(matches) == 0 {
|
||||
return "", fmt.Errorf("unable to find semver info in %s", version)
|
||||
}
|
||||
|
||||
// Reconstruct the version with "v" prefix for consistency
|
||||
versionPart := matches[0]
|
||||
if !strings.HasPrefix(versionPart, "v") {
|
||||
versionPart = "v" + versionPart
|
||||
}
|
||||
|
||||
return versionPart, nil
|
||||
}
|
||||
|
||||
func parseHelmVersion(versionStr string) (*semver.Version, error) {
|
||||
if len(versionStr) == 0 {
|
||||
return nil, fmt.Errorf("empty helm version")
|
||||
}
|
||||
|
||||
// Check if version string starts with "v", if not add it
|
||||
processedVersion := strings.TrimSpace(versionStr)
|
||||
if !strings.HasPrefix(processedVersion, "v") {
|
||||
processedVersion = "v" + processedVersion
|
||||
}
|
||||
|
||||
v, err := chartify.FindSemVerInfo(processedVersion)
|
||||
|
||||
v, err := findSemVerInfo(versionStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error find helm srmver version '%s': %w", versionStr, err)
|
||||
return nil, fmt.Errorf("error find helm semver version '%s': %w", versionStr, err)
|
||||
}
|
||||
|
||||
ver, err := semver.NewVersion(v)
|
||||
|
|
|
|||
|
|
@ -1158,6 +1158,18 @@ func TestParseHelmVersion(t *testing.T) {
|
|||
want: semver.MustParse("v3.2.4"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "kustomize version format - issue #2124",
|
||||
version: "5.7.1",
|
||||
want: semver.MustParse("v5.7.1"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "kustomize structured output format",
|
||||
version: "{v5.7.1 2025-07-23T12:45:29Z }",
|
||||
want: semver.MustParse("v5.7.1"),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
package helmexec
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Test the specific scenario mentioned in issue #2124
|
||||
func TestFindSemVerInfo_Issue2124(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "issue #2124 - kustomize version 5.7.1 without v prefix",
|
||||
input: "5.7.1",
|
||||
expected: "v5.7.1",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "kustomize version with v prefix",
|
||||
input: "v5.7.1",
|
||||
expected: "v5.7.1",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "kustomize structured output",
|
||||
input: "{v5.7.1 2025-07-23T12:45:29Z }",
|
||||
expected: "v5.7.1",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "helm version format",
|
||||
input: "v3.18.4+gd80839c",
|
||||
expected: "v3.18.4+gd80839c",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid version",
|
||||
input: "not-a-version",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := findSemVerInfo(tc.input)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue