Lint invalid chart names

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
pull/32075/head
Akash Kumar 6 months ago
parent 8f56f24d63
commit 011a56b9e3

@ -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,10 @@ import (
chartutil "helm.sh/helm/v4/internal/chart/v3/util" chartutil "helm.sh/helm/v4/internal/chart/v3/util"
) )
const validChartNameMessage = "chart names must contain lowercase letters, numbers, and dashes, and must start and end with a lowercase letter or number"
var validChartName = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`)
// 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"
@ -120,6 +125,9 @@ func validateChartName(cf *chart.Metadata) error {
if name != cf.Name { if name != cf.Name {
return fmt.Errorf("chart name %q is invalid", cf.Name) return fmt.Errorf("chart name %q is invalid", cf.Name)
} }
if !validChartName.MatchString(cf.Name) {
return fmt.Errorf("chart name %q is invalid; %s", cf.Name, validChartNameMessage)
}
return nil return nil
} }

@ -29,19 +29,16 @@ import (
) )
const ( const (
badChartNameDir = "testdata/badchartname"
badChartDir = "testdata/badchartfile" badChartDir = "testdata/badchartfile"
anotherBadChartDir = "testdata/anotherbadchartfile" anotherBadChartDir = "testdata/anotherbadchartfile"
) )
var ( var (
badChartNamePath = filepath.Join(badChartNameDir, "Chart.yaml")
badChartFilePath = filepath.Join(badChartDir, "Chart.yaml") badChartFilePath = filepath.Join(badChartDir, "Chart.yaml")
nonExistingChartFilePath = filepath.Join(os.TempDir(), "Chart.yaml") nonExistingChartFilePath = filepath.Join(os.TempDir(), "Chart.yaml")
) )
var badChart, _ = chartutil.LoadChartfile(badChartFilePath) var badChart, _ = chartutil.LoadChartfile(badChartFilePath)
var badChartName, _ = chartutil.LoadChartfile(badChartNamePath)
// Validation functions Test // Validation functions Test
func TestValidateChartYamlNotDirectory(t *testing.T) { func TestValidateChartYamlNotDirectory(t *testing.T) {
@ -67,14 +64,65 @@ func TestValidateChartYamlFormat(t *testing.T) {
} }
func TestValidateChartName(t *testing.T) { func TestValidateChartName(t *testing.T) {
err := validateChartName(badChart) tests := []struct {
if err == nil { name string
t.Error("validateChartName to return a linter error, got no error") wantErr string
}{
{
name: "",
wantErr: "name is required",
},
{
name: "../badchartname",
wantErr: `chart name "../badchartname" is invalid`,
},
{
name: "BadChart",
wantErr: `chart name "BadChart" is invalid`,
},
{
name: "bad.chart",
wantErr: `chart name "bad.chart" is invalid`,
},
{
name: "bad_chart",
wantErr: `chart name "bad_chart" is invalid`,
},
{
name: "-badchart",
wantErr: `chart name "-badchart" is invalid`,
},
{
name: "badchart-",
wantErr: `chart name "badchart-" is invalid`,
},
{
name: "badchart",
},
{
name: "bad-chart-1",
},
{
name: "bad--chart",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validateChartName(&chart.Metadata{Name: tt.name})
if tt.wantErr == "" {
if err != nil {
t.Fatalf("validateChartName(%q) returned unexpected error: %s", tt.name, err)
}
return
} }
err = validateChartName(badChartName)
if err == nil { if err == nil {
t.Error("expected validateChartName to return a linter error for an invalid name, got no error") t.Fatalf("validateChartName(%q) returned no error, want %q", tt.name, tt.wantErr)
}
if !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("validateChartName(%q) returned %q, want to contain %q", tt.name, err, tt.wantErr)
}
})
} }
} }

@ -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,10 @@ import (
chartutil "helm.sh/helm/v4/pkg/chart/v2/util" chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
) )
const validChartNameMessage = "chart names must contain lowercase letters, numbers, and dashes, and must start and end with a lowercase letter or number"
var validChartName = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`)
// 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"
@ -121,6 +126,9 @@ func validateChartName(cf *chart.Metadata) error {
if name != cf.Name { if name != cf.Name {
return fmt.Errorf("chart name %q is invalid", cf.Name) return fmt.Errorf("chart name %q is invalid", cf.Name)
} }
if !validChartName.MatchString(cf.Name) {
return fmt.Errorf("chart name %q is invalid; %s", cf.Name, validChartNameMessage)
}
return nil return nil
} }

@ -29,19 +29,16 @@ import (
) )
const ( const (
badChartNameDir = "testdata/badchartname"
badChartDir = "testdata/badchartfile" badChartDir = "testdata/badchartfile"
anotherBadChartDir = "testdata/anotherbadchartfile" anotherBadChartDir = "testdata/anotherbadchartfile"
) )
var ( var (
badChartNamePath = filepath.Join(badChartNameDir, "Chart.yaml")
badChartFilePath = filepath.Join(badChartDir, "Chart.yaml") badChartFilePath = filepath.Join(badChartDir, "Chart.yaml")
nonExistingChartFilePath = filepath.Join(os.TempDir(), "Chart.yaml") nonExistingChartFilePath = filepath.Join(os.TempDir(), "Chart.yaml")
) )
var badChart, _ = chartutil.LoadChartfile(badChartFilePath) var badChart, _ = chartutil.LoadChartfile(badChartFilePath)
var badChartName, _ = chartutil.LoadChartfile(badChartNamePath)
// Validation functions Test // Validation functions Test
func TestValidateChartYamlNotDirectory(t *testing.T) { func TestValidateChartYamlNotDirectory(t *testing.T) {
@ -67,14 +64,65 @@ func TestValidateChartYamlFormat(t *testing.T) {
} }
func TestValidateChartName(t *testing.T) { func TestValidateChartName(t *testing.T) {
err := validateChartName(badChart) tests := []struct {
if err == nil { name string
t.Error("validateChartName to return a linter error, got no error") wantErr string
}{
{
name: "",
wantErr: "name is required",
},
{
name: "../badchartname",
wantErr: `chart name "../badchartname" is invalid`,
},
{
name: "BadChart",
wantErr: `chart name "BadChart" is invalid`,
},
{
name: "bad.chart",
wantErr: `chart name "bad.chart" is invalid`,
},
{
name: "bad_chart",
wantErr: `chart name "bad_chart" is invalid`,
},
{
name: "-badchart",
wantErr: `chart name "-badchart" is invalid`,
},
{
name: "badchart-",
wantErr: `chart name "badchart-" is invalid`,
},
{
name: "badchart",
},
{
name: "bad-chart-1",
},
{
name: "bad--chart",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validateChartName(&chart.Metadata{Name: tt.name})
if tt.wantErr == "" {
if err != nil {
t.Fatalf("validateChartName(%q) returned unexpected error: %s", tt.name, err)
}
return
} }
err = validateChartName(badChartName)
if err == nil { if err == nil {
t.Error("expected validateChartName to return a linter error for an invalid name, got no error") t.Fatalf("validateChartName(%q) returned no error, want %q", tt.name, tt.wantErr)
}
if !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("validateChartName(%q) returned %q, want to contain %q", tt.name, err, tt.wantErr)
}
})
} }
} }

Loading…
Cancel
Save