helm: Error: validation: chart.metadata.version is required on helm package even though --version is used

Output of helm version: version.BuildInfo{Version:"v3.5.0", GitCommit:"32c22239423b3b4ba6706d450bd044baffdcf9e6", GitTreeState:"clean", GoVersion:"go1.15.6"}

Output of kubectl version: n/a

Cloud Provider/Platform (AKS, GKE, Minikube etc.): n/a

helm package always requires the version field to be set in the Chart.yaml, even if the --version flag is set. Otherwise helm exits with Error: validation: chart.metadata.version is required.

Since helm package ignores the version from the Chart.yaml anyway if it is provided via command line it seems unnecessary and a bit confusing to still require it.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 25 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@bacongobbler it looks like this issue got introduced with version v3.5.2

The Validate() function in pkg/chart/metadata.go looks like the following in v3.5.1:

func (md *Metadata) Validate() error {
	if md == nil {
		return ValidationError("chart.metadata is required")
	}
	if md.APIVersion == "" {
		return ValidationError("chart.metadata.apiVersion is required")
	}
	if md.Name == "" {
		return ValidationError("chart.metadata.name is required")
	}
	if md.Version == "" {
		return ValidationError("chart.metadata.version is required")
	}
	if !isValidChartType(md.Type) {
		return ValidationError("chart.metadata.type must be application or library")
	}

	// Aliases need to be validated here to make sure that the alias name does
	// not contain any illegal characters.
	for _, dependency := range md.Dependencies {
		if err := validateDependency(dependency); err != nil {
			return err
		}
	}

	// TODO validate valid semver here?
	return nil
}

While the same function in v3.5.2 has the SemVer check built in:

func (md *Metadata) Validate() error {
	if md == nil {
		return ValidationError("chart.metadata is required")
	}

	md.Name = sanitizeString(md.Name)
	md.Description = sanitizeString(md.Description)
	md.Home = sanitizeString(md.Home)
	md.Icon = sanitizeString(md.Icon)
	md.Condition = sanitizeString(md.Condition)
	md.Tags = sanitizeString(md.Tags)
	md.AppVersion = sanitizeString(md.AppVersion)
	md.KubeVersion = sanitizeString(md.KubeVersion)
	for i := range md.Sources {
		md.Sources[i] = sanitizeString(md.Sources[i])
	}
	for i := range md.Keywords {
		md.Keywords[i] = sanitizeString(md.Keywords[i])
	}

	if md.APIVersion == "" {
		return ValidationError("chart.metadata.apiVersion is required")
	}
	if md.Name == "" {
		return ValidationError("chart.metadata.name is required")
	}
	if md.Version == "" {
		return ValidationError("chart.metadata.version is required")
	}
	if !isValidSemver(md.Version) {
		return ValidationErrorf("chart.metadata.version %q is invalid", md.Version)
	}

	...

	return nil
}

While the Run() method of the helm package command would actually respect the provided --version flag:

func (p *Package) Run(path string, vals map[string]interface{}) (string, error) {
        ...

	if p.Version != "" {
		ch.Metadata.Version = p.Version
	}

	if err := validateVersion(ch.Metadata.Version); err != nil {
		return "", err
	}

       ...
}

it never gets to that point because the metadata of the Chart is being parsed AND validated at the time the files are being loaded.

While the early validation certainly works for most of the other, if not all of the other commands it doesn’t work for package where you can provide a version via the --version flag.

To fix this there would only really be two options I could see:

  1. Make the parsing “aware” of what command has been invoked (i.e. disable the version check for package via flag)
  2. Turn it off by default and have the individual command validate it like package is actually trying to do

Cheers,

Kimba