pull/31062/merge
JS 1 month ago committed by GitHub
commit 7d7f4030a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -31,10 +31,7 @@ import (
) )
// chartName is a regular expression for testing the supplied name of a chart. // chartName is a regular expression for testing the supplied name of a chart.
// This regular expression is probably stricter than it needs to be. We can relax it var chartName = regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`)
// somewhat. Newline characters, as well as $, quotes, +, parens, and % are known to be
// problematic.
var chartName = regexp.MustCompile("^[a-zA-Z0-9._-]+$")
const ( const (
// ChartfileName is the default Chart file name. // ChartfileName is the default Chart file name.
@ -826,7 +823,7 @@ func validateChartName(name string) error {
return fmt.Errorf("chart name must be between 1 and %d characters", maxChartNameLength) return fmt.Errorf("chart name must be between 1 and %d characters", maxChartNameLength)
} }
if !chartName.MatchString(name) { if !chartName.MatchString(name) {
return fmt.Errorf("chart name must match the regular expression %q", chartName.String()) return fmt.Errorf("chart name must use only lowercase letters or digits optionally with dash separators")
} }
return nil return nil
} }

@ -147,8 +147,10 @@ func TestCreate_Overwrite(t *testing.T) {
func TestValidateChartName(t *testing.T) { func TestValidateChartName(t *testing.T) {
for name, shouldPass := range map[string]bool{ for name, shouldPass := range map[string]bool{
"": false, "": false,
"abcdefghijklmnopqrstuvwxyz-_.": true, "abcdefghijklmnopqrstuvwxyz-_.": false,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.": true, "abcdefghijklmnopqrstuvwxyz": true,
"abcdefghijklm-nopqrstuvwxyz": true,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-_.": false,
"$hello": false, "$hello": false,
"Hellô": false, "Hellô": false,
"he%%o": false, "he%%o": false,

@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
@ -31,6 +32,13 @@ import (
"helm.sh/helm/v4/pkg/lint/support" "helm.sh/helm/v4/pkg/lint/support"
) )
// chartName is a regular expression for testing the supplied name of a chart.
var chartName = regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`)
// maxChartNameLength is lower than the limits we know of with certain file systems,
// and with certain Kubernetes fields.
const maxChartNameLength = 250
// Chartfile runs a set of linter rules related to Chart.yaml file // Chartfile runs a set of linter rules related to Chart.yaml file
func Chartfile(linter *support.Linter) { func Chartfile(linter *support.Linter) {
chartFileName := "Chart.yaml" chartFileName := "Chart.yaml"
@ -113,12 +121,11 @@ func validateChartYamlStrictFormat(chartFileError error) error {
} }
func validateChartName(cf *chart.Metadata) error { func validateChartName(cf *chart.Metadata) error {
if cf.Name == "" { if cf.Name == "" || len(cf.Name) > maxChartNameLength {
return errors.New("name is required") return fmt.Errorf("chart name must be between 1 and %d characters", maxChartNameLength)
} }
name := filepath.Base(cf.Name) if !chartName.MatchString(cf.Name) {
if name != cf.Name { return fmt.Errorf("chart name must use only lowercase letters or digits optionally with dash separators")
return fmt.Errorf("chart name %q is invalid", cf.Name)
} }
return nil return nil
} }

@ -76,6 +76,43 @@ func TestValidateChartName(t *testing.T) {
if err == nil { if err == nil {
t.Error("expected validateChartName to return a linter error for an invalid name, got no error") t.Error("expected validateChartName to return a linter error for an invalid name, got no error")
} }
failTests := []*chart.Metadata{
{Name: ""}, // empty
{Name: "ChartName"}, // uppercase
{Name: "chart_name"}, // underscore
{Name: "chart.name"}, // dot
{Name: "chart--name"}, // double dash
{Name: "-chartname"}, // starts with dash
{Name: "chartname-"}, // ends with dash
{Name: "chart$name"}, // special character
{Name: "chart/name"}, // forward slash
{Name: "chart\\name"}, // backslash
{Name: "chart name"}, // space
{Name: strings.Repeat("a", 251)}, // 251 chars — too long
}
successTests := []*chart.Metadata{
{Name: "chartname"},
{Name: "chart-name"},
{Name: "chart-name-success"},
{Name: "chartname123"},
{Name: strings.Repeat("a", 250)},
}
for _, chart := range failTests {
err := validateChartName(chart)
if err == nil {
t.Errorf("validateChartName(%q) expected error, got nil", chart.Name)
}
}
for _, chart := range successTests {
err := validateChartName(chart)
if err != nil {
t.Errorf("validateChartName(%q) expected no error, got: %s", chart.Name, err)
}
}
} }
func TestValidateChartVersion(t *testing.T) { func TestValidateChartVersion(t *testing.T) {

Loading…
Cancel
Save