diff --git a/docs/3-create-a-zarf-package/2-zarf-components.md b/docs/3-create-a-zarf-package/2-zarf-components.md index 2ebd2f975f..df26966412 100644 --- a/docs/3-create-a-zarf-package/2-zarf-components.md +++ b/docs/3-create-a-zarf-package/2-zarf-components.md @@ -66,20 +66,11 @@ Charts using the `url` key can be: - A remote URL (http/https) to a Git repository - A remote URL (oci://) to an OCI registry +- A remote URL (http/https) to a Helm repository #### Chart Examples - - - - - - - - - - - + ### Kubernetes Manifests diff --git a/docs/3-create-a-zarf-package/4-zarf-schema.md b/docs/3-create-a-zarf-package/4-zarf-schema.md index 00b5601dcc..6f6ae55236 100644 --- a/docs/3-create-a-zarf-package/4-zarf-schema.md +++ b/docs/3-create-a-zarf-package/4-zarf-schema.md @@ -988,7 +988,7 @@ Must be one of: ![Required](https://img.shields.io/badge/Required-red) -**Description:** The name of the chart to deploy; this should be the name of the chart as it is installed in the helm repo +**Description:** The name of the chart within Zarf; note that this must be unique and does not need to be the same as the name in the chart repo | | | | -------- | -------- | @@ -999,12 +999,12 @@ Must be one of:
- releaseName + version  
-**Description:** The name of the release to create; defaults to the name of the chart +**Description:** The version of the chart to deploy; for git-based charts this is also the tag of the git repo by default (when not using the '@' syntax for 'repos') | | | | -------- | -------- | @@ -1029,19 +1029,19 @@ Must be one of: **Examples:** -"OCI registry: oci://ghcr.io/stefanprodan/charts/podinfo", "helm chart repo: https://stefanprodan.github.io/podinfo", "git repo: https://github.com/stefanprodan/podinfo" +"OCI registry: oci://ghcr.io/stefanprodan/charts/podinfo", "helm chart repo: https://stefanprodan.github.io/podinfo", "git repo: https://github.com/stefanprodan/podinfo (note the '@' syntax for 'repos' is supported here too)"
- version + repoName  
-**Description:** The version of the chart to deploy; for git-based charts this is also the tag of the git repo +**Description:** The name of a chart within a Helm repository (defaults to the Zarf name of the chart) | | | | -------- | -------- | @@ -1052,41 +1052,33 @@ Must be one of:
- namespace * + gitPath  
-![Required](https://img.shields.io/badge/Required-red) - -**Description:** The namespace to deploy the chart to +**Description:** (git repo only) The sub directory to the chart within a git repo | | | | -------- | -------- | | **Type** | `string` | +**Example:** + + +"charts/your-chart" +
- valuesFiles + localPath  
-**Description:** List of local values file paths or remote URLs to include in the package; these will be merged together - -| | | -| -------- | ----------------- | -| **Type** | `array of string` | - -![Min Items: N/A](https://img.shields.io/badge/Min%20Items%3A%20N/A-gold) -![Max Items: N/A](https://img.shields.io/badge/Max%20Items%3A%20N/A-gold) -![Item unicity: False](https://img.shields.io/badge/Item%20unicity%3A%20False-gold) -![Additional items: N/A](https://img.shields.io/badge/Additional%20items%3A%20N/A-gold) - - ### valuesFiles items +**Description:** The path to a local chart's folder or .tgz archive | | | | -------- | -------- | @@ -1097,33 +1089,30 @@ Must be one of:
- gitPath + namespace *  
-**Description:** The path to the chart in the repo if using a git repo instead of a helm repo +![Required](https://img.shields.io/badge/Required-red) + +**Description:** The namespace to deploy the chart to | | | | -------- | -------- | | **Type** | `string` | -**Example:** - - -"charts/your-chart" -
- localPath + releaseName  
-**Description:** The path to the local chart's folder or .tgz archive +**Description:** The name of the Helm release to create (defaults to the Zarf name of the chart) | | | | -------- | -------- | @@ -1148,6 +1137,33 @@ Must be one of:
+
+ + valuesFiles + +  +
+ +**Description:** List of local values file paths or remote URLs to include in the package; these will be merged together when deployed + +| | | +| -------- | ----------------- | +| **Type** | `array of string` | + +![Min Items: N/A](https://img.shields.io/badge/Min%20Items%3A%20N/A-gold) +![Max Items: N/A](https://img.shields.io/badge/Max%20Items%3A%20N/A-gold) +![Item unicity: False](https://img.shields.io/badge/Item%20unicity%3A%20False-gold) +![Additional items: N/A](https://img.shields.io/badge/Additional%20items%3A%20N/A-gold) + + ### valuesFiles items + +| | | +| -------- | -------- | +| **Type** | `string` | + +
+
+
diff --git a/examples/helm-charts/zarf.yaml b/examples/helm-charts/zarf.yaml index cfc16bfef9..27a50c5595 100644 --- a/examples/helm-charts/zarf.yaml +++ b/examples/helm-charts/zarf.yaml @@ -5,60 +5,45 @@ metadata: version: 0.0.1 components: - - name: demo-helm-local-chart - required: false + - name: demo-helm-charts + required: true charts: - - name: podinfo + # Charts are organized in a list with unique chart names per component - note that a Zarf chart name does not need to match the chart name in a Chart.yaml + - name: podinfo-local version: 6.4.0 namespace: podinfo-from-local-chart + # In this case `localPath` will load the podinfo chart that is located in the `chart` directory localPath: chart valuesFiles: - values.yaml - images: - - ghcr.io/stefanprodan/podinfo:6.4.0 - # This is the cosign signature for the podinfo image for image signature verification - - ghcr.io/stefanprodan/podinfo:sha256-57a654ace69ec02ba8973093b6a786faa15640575fbf0dbb603db55aca2ccec8.sig - actions: - onDeploy: - after: - - wait: - cluster: - kind: deployment - name: podinfo - namespace: podinfo-from-local-chart - condition: available + + - name: podinfo-oci + version: 6.4.0 + namespace: podinfo-from-oci + # In this case `url` will load the helm chart located in the podinfo OCI repository + url: oci://ghcr.io/stefanprodan/charts/podinfo + valuesFiles: + - values.yaml - - name: demo-helm-git-chart - required: false - charts: - - name: podinfo + - name: podinfo-git version: 6.4.0 namespace: podinfo-from-git + # In this case `url` will load the helm chart located in the podinfo git repository url: https://github.com/stefanprodan/podinfo.git + # By default git will look in the root of the git repository but you can define a sub directory with `gitPath` gitPath: charts/podinfo valuesFiles: - values.yaml - images: - - ghcr.io/stefanprodan/podinfo:6.4.0 - # This is the cosign signature for the podinfo image for image signature verification - - ghcr.io/stefanprodan/podinfo:sha256-57a654ace69ec02ba8973093b6a786faa15640575fbf0dbb603db55aca2ccec8.sig - actions: - onDeploy: - after: - - wait: - cluster: - kind: deployment - namespace: podinfo-from-git - name: podinfo - condition: available - - name: demo-helm-oci-chart - required: false - charts: - - name: podinfo + - name: podinfo-repo version: 6.4.0 - namespace: podinfo-from-oci - url: oci://ghcr.io/stefanprodan/charts/podinfo + namespace: podinfo-from-repo + # In this case `url` will load the helm chart located in the podinfo helm repository + url: https://stefanprodan.github.io/podinfo + # By default the chart `name` will be what is used to search a repository but since Zarf chart names must be unique per-component you can override this with `repoName` + repoName: podinfo + # By default the release name will be the chart name, but you can override this with the `releaseName` key + releaseName: cool-release-name valuesFiles: - values.yaml images: @@ -70,38 +55,25 @@ components: after: - wait: cluster: - kind: pod - name: app.kubernetes.io/name=podinfo - namespace: podinfo-from-oci - condition: ready + kind: deployment + name: podinfo-local + namespace: podinfo-from-local-chart + condition: available - wait: cluster: kind: deployment - # note this version is the same as the chart version - name: app.kubernetes.io/version=6.4.0 + name: podinfo-oci namespace: podinfo-from-oci condition: available - - - name: demo-helm-alt-release-name - required: false - charts: - - name: podinfo - version: 6.4.0 - namespace: helm-alt-release-name - url: https://stefanprodan.github.io/podinfo - releaseName: cool-name - valuesFiles: - - values.yaml - images: - - ghcr.io/stefanprodan/podinfo:6.4.0 - # This is the cosign signature for the podinfo image for image signature verification - - ghcr.io/stefanprodan/podinfo:sha256-57a654ace69ec02ba8973093b6a786faa15640575fbf0dbb603db55aca2ccec8.sig - actions: - onDeploy: - after: - wait: cluster: - kind: pod - name: app.kubernetes.io/name=cool-name-podinfo - namespace: helm-alt-release-name - condition: ready + kind: deployment + name: podinfo-git + namespace: podinfo-from-git + condition: available + - wait: + cluster: + kind: deployment + name: cool-release-name-podinfo + namespace: podinfo-from-repo + condition: available diff --git a/src/internal/packager/helm/repo.go b/src/internal/packager/helm/repo.go index b4c46db433..ae41d2b0bc 100644 --- a/src/internal/packager/helm/repo.go +++ b/src/internal/packager/helm/repo.go @@ -79,7 +79,8 @@ func (h *Helm) PackageChartFromLocalFiles(cosignKeyPath string) error { } // Handle the chart directory or tarball - var path string + var saved string + temp := filepath.Join(h.chartPath, "temp") if _, ok := cl.(loader.DirLoader); ok { err = h.buildChartDependencies(spinner) if err != nil { @@ -88,20 +89,22 @@ func (h *Helm) PackageChartFromLocalFiles(cosignKeyPath string) error { client := action.NewPackage() - client.Destination = h.chartPath - path, err = client.Run(h.chart.LocalPath, nil) + client.Destination = temp + saved, err = client.Run(h.chart.LocalPath, nil) } else { - path = filepath.Join(h.chartPath, filepath.Base(h.chart.LocalPath)) - err = utils.CreatePathAndCopy(h.chart.LocalPath, path) + saved = filepath.Join(temp, filepath.Base(h.chart.LocalPath)) + err = utils.CreatePathAndCopy(h.chart.LocalPath, saved) } + defer os.RemoveAll(temp) if err != nil { - return fmt.Errorf("unable to save the archive and create the package %s: %w", path, err) + return fmt.Errorf("unable to save the archive and create the package %s: %w", saved, err) } - err = h.packageValues(cosignKeyPath) + // Finalize the chart + err = h.finalizeChartPackage(saved, cosignKeyPath) if err != nil { - return fmt.Errorf("unable to process the values for the package: %w", err) + return err } spinner.Success() @@ -151,8 +154,13 @@ func (h *Helm) DownloadPublishedChart(cosignKeyPath string) error { // Explicitly set the pull version for OCI pull.Version = h.chart.Version } else { + chartName := h.chart.Name + if h.chart.RepoName != "" { + chartName = h.chart.RepoName + } + // Perform simple chart download - chartURL, err = repo.FindChartInRepoURL(h.chart.URL, h.chart.Name, h.chart.Version, pull.CertFile, pull.KeyFile, pull.CaFile, getter.All(pull.Settings)) + chartURL, err = repo.FindChartInRepoURL(h.chart.URL, chartName, h.chart.Version, pull.CertFile, pull.KeyFile, pull.CaFile, getter.All(pull.Settings)) if err != nil { if strings.Contains(err.Error(), "not found") { // Intentionally dogsled this error since this is just a nice to have helper @@ -174,8 +182,14 @@ func (h *Helm) DownloadPublishedChart(cosignKeyPath string) error { }, } - // Download the file (we don't control what name helm creates here) - saved, _, err := chartDownloader.DownloadTo(chartURL, pull.Version, h.chartPath) + // Download the file into a temp directory since we don't control what name helm creates here + temp := filepath.Join(h.chartPath, "temp") + if err = utils.CreateDirectory(temp, 0700); err != nil { + return fmt.Errorf("unable to create helm chart temp directory: %w", err) + } + defer os.RemoveAll(temp) + + saved, _, err := chartDownloader.DownloadTo(chartURL, pull.Version, temp) if err != nil { return fmt.Errorf("unable to download the helm chart: %w", err) } @@ -186,16 +200,10 @@ func (h *Helm) DownloadPublishedChart(cosignKeyPath string) error { return err } - // Ensure the name is consistent for deployments - destinationTarball := StandardName(h.chartPath, h.chart) + ".tgz" - err = os.Rename(saved, destinationTarball) + // Finalize the chart + err = h.finalizeChartPackage(saved, cosignKeyPath) if err != nil { - return fmt.Errorf("unable to save the chart tarball: %w", err) - } - - err = h.packageValues(cosignKeyPath) - if err != nil { - return fmt.Errorf("unable to process the values for the package: %w", err) + return err } spinner.Success() @@ -217,6 +225,21 @@ func DownloadChartFromGitToTemp(url string, spinner *message.Spinner) (string, e return gitCfg.GitPath, nil } +func (h *Helm) finalizeChartPackage(saved, cosignKeyPath string) error { + // Ensure the name is consistent for deployments + destinationTarball := StandardName(h.chartPath, h.chart) + ".tgz" + err := os.Rename(saved, destinationTarball) + if err != nil { + return fmt.Errorf("unable to save the final chart tarball: %w", err) + } + + err = h.packageValues(cosignKeyPath) + if err != nil { + return fmt.Errorf("unable to process the values for the package: %w", err) + } + return nil +} + func (h *Helm) packageValues(cosignKeyPath string) error { for valuesIdx, path := range h.chart.ValuesFiles { dst := fmt.Sprintf("%s-%d", StandardName(h.valuesPath, h.chart), valuesIdx) diff --git a/src/pkg/packager/deploy.go b/src/pkg/packager/deploy.go index 53dbdb7351..8835e0f92e 100644 --- a/src/pkg/packager/deploy.go +++ b/src/pkg/packager/deploy.go @@ -377,7 +377,7 @@ func (p *Packager) processComponentFiles(component types.ZarfComponent, pkgLocat // Try to remove the filepath if it exists _ = os.RemoveAll(link) // Make sure the parent directory exists - _ = utils.CreateFilePath(link) + _ = utils.CreateParentDirectory(link) // Create the symlink err := os.Symlink(file.Target, link) if err != nil { diff --git a/src/pkg/utils/io.go b/src/pkg/utils/io.go index 38349329fd..436e8b0155 100755 --- a/src/pkg/utils/io.go +++ b/src/pkg/utils/io.go @@ -45,7 +45,7 @@ func MakeTempDir(basePath string) (string, error) { } } tmp, err := os.MkdirTemp(basePath, tmpPathPrefix) - message.Debug("Using temporary directory:", basePath) + message.Debug("Using temporary directory:", tmp) return tmp, err } @@ -234,15 +234,15 @@ func RecursiveFileList(dir string, pattern *regexp.Regexp, skipHidden bool) (fil return files, err } -// CreateFilePath creates the parent directory for the given file path. -func CreateFilePath(destination string) error { +// CreateParentDirectory creates the parent directory for the given file path. +func CreateParentDirectory(destination string) error { parentDest := filepath.Dir(destination) return CreateDirectory(parentDest, 0700) } // CreatePathAndCopy creates the parent directory for the given file path and copies the source file to the destination. func CreatePathAndCopy(source string, destination string) error { - if err := CreateFilePath(destination); err != nil { + if err := CreateParentDirectory(destination); err != nil { return err } diff --git a/src/test/e2e/09_component_compose_test.go b/src/test/e2e/09_component_compose_test.go index b96cc6b3f6..4dc73c340d 100644 --- a/src/test/e2e/09_component_compose_test.go +++ b/src/test/e2e/09_component_compose_test.go @@ -102,18 +102,18 @@ func (suite *CompositionSuite) Test_1_FullComposability() { suite.Contains(stdErr, e2e.NormalizeYAMLFilenames(` charts: - name: podinfo-compose - releaseName: podinfo-override - url: oci://ghcr.io/stefanprodan/charts/podinfo version: 6.4.0 + url: oci://ghcr.io/stefanprodan/charts/podinfo namespace: podinfo-override + releaseName: podinfo-override valuesFiles: - files/test-values.yaml - files/test-values.yaml - name: podinfo-compose-two - releaseName: podinfo-compose-two - url: oci://ghcr.io/stefanprodan/charts/podinfo version: 6.4.0 + url: oci://ghcr.io/stefanprodan/charts/podinfo namespace: podinfo-compose-two + releaseName: podinfo-compose-two valuesFiles: - files/test-values.yaml `)) diff --git a/src/test/e2e/25_helm_test.go b/src/test/e2e/25_helm_test.go index b76e2644c6..38478d710c 100644 --- a/src/test/e2e/25_helm_test.go +++ b/src/test/e2e/25_helm_test.go @@ -8,7 +8,6 @@ import ( "fmt" "os/exec" "path/filepath" - "strings" "testing" "github.com/stretchr/testify/require" @@ -56,24 +55,17 @@ func testHelmChartsExample(t *testing.T) { require.Contains(t, e2e.StripMessageFormatting(stdErr), "chart \"asdf\" version \"6.4.0\" not found") require.Contains(t, e2e.StripMessageFormatting(stdErr), "Available charts and versions from \"https://stefanprodan.github.io/podinfo\":") - // Create the package with a registry override + // Create the package (with a registry override to test that as well) stdOut, stdErr, err = e2e.Zarf("package", "create", "examples/helm-charts", "-o", "build", "--registry-override", "ghcr.io=docker.io", "--tmpdir", tmpdir, "--confirm") require.NoError(t, err, stdOut, stdErr) - // Deploy the package. - allComponents := []string{ - "demo-helm-local-chart", - "demo-helm-git-chart", - "demo-helm-oci-chart", - "demo-helm-alt-release-name", - } - componentsFlag := fmt.Sprintf("--components=%s", strings.Join(allComponents, ",")) - stdOut, stdErr, err = e2e.Zarf("package", "deploy", helmChartsPkg, componentsFlag, "--confirm") + // Deploy the example package. + stdOut, stdErr, err = e2e.Zarf("package", "deploy", helmChartsPkg, "--confirm") require.NoError(t, err, stdOut, stdErr) require.Contains(t, string(stdErr), "registryOverrides", "registry overrides was not saved to build data") require.Contains(t, string(stdErr), "docker.io", "docker.io not found in registry overrides") - // Remove the package. + // Remove the example package. stdOut, stdErr, err = e2e.Zarf("package", "remove", "helm-charts", "--confirm") require.NoError(t, err, stdOut, stdErr) } diff --git a/src/test/e2e/50_oci_publish_deploy_test.go b/src/test/e2e/50_oci_publish_deploy_test.go index 563d700750..5a6e35d067 100644 --- a/src/test/e2e/50_oci_publish_deploy_test.go +++ b/src/test/e2e/50_oci_publish_deploy_test.go @@ -85,7 +85,7 @@ func (suite *PublishDeploySuiteTestSuite) Test_1_Deploy() { ref := suite.Reference.String() // Deploy the package via OCI. - stdOut, stdErr, err := e2e.Zarf("package", "deploy", "oci://"+ref, "--components=demo-helm-oci-chart", "--insecure", "--confirm") + stdOut, stdErr, err := e2e.Zarf("package", "deploy", "oci://"+ref, "--insecure", "--confirm") suite.NoError(err, stdOut, stdErr) // Remove the package via OCI. diff --git a/src/test/packages/51-import-everything/oci-import/zarf.yaml b/src/test/packages/51-import-everything/oci-import/zarf.yaml index 1173eb6e5d..6c27000904 100644 --- a/src/test/packages/51-import-everything/oci-import/zarf.yaml +++ b/src/test/packages/51-import-everything/oci-import/zarf.yaml @@ -9,5 +9,5 @@ components: description: "import-component-oci == ###ZARF_COMPONENT_NAME###" required: false import: - name: demo-helm-local-chart + name: demo-helm-charts url: oci://localhost:555/helm-charts:0.0.1-skeleton diff --git a/src/types/component.go b/src/types/component.go index 8c44dbed5e..36fa1d529c 100644 --- a/src/types/component.go +++ b/src/types/component.go @@ -90,15 +90,16 @@ type ZarfFile struct { // ZarfChart defines a helm chart to be deployed. type ZarfChart struct { - Name string `json:"name" jsonschema:"description=The name of the chart to deploy; this should be the name of the chart as it is installed in the helm repo"` - ReleaseName string `json:"releaseName,omitempty" jsonschema:"description=The name of the release to create; defaults to the name of the chart"` - URL string `json:"url,omitempty" jsonschema:"example=OCI registry: oci://ghcr.io/stefanprodan/charts/podinfo,example=helm chart repo: https://stefanprodan.github.io/podinfo,example=git repo: https://github.com/stefanprodan/podinfo" jsonschema_description:"The URL of the OCI registry, chart repository, or git repo where the helm chart is stored"` - Version string `json:"version,omitempty" jsonschema:"description=The version of the chart to deploy; for git-based charts this is also the tag of the git repo"` + Name string `json:"name" jsonschema:"description=The name of the chart within Zarf; note that this must be unique and does not need to be the same as the name in the chart repo"` + Version string `json:"version,omitempty" jsonschema:"description=The version of the chart to deploy; for git-based charts this is also the tag of the git repo by default (when not using the '@' syntax for 'repos')"` + URL string `json:"url,omitempty" jsonschema:"example=OCI registry: oci://ghcr.io/stefanprodan/charts/podinfo,example=helm chart repo: https://stefanprodan.github.io/podinfo,example=git repo: https://github.com/stefanprodan/podinfo (note the '@' syntax for 'repos' is supported here too)" jsonschema_description:"The URL of the OCI registry, chart repository, or git repo where the helm chart is stored"` + RepoName string `json:"repoName,omitempty" jsonschema:"description=The name of a chart within a Helm repository (defaults to the Zarf name of the chart)"` + GitPath string `json:"gitPath,omitempty" jsonschema:"description=(git repo only) The sub directory to the chart within a git repo,example=charts/your-chart"` + LocalPath string `json:"localPath,omitempty" jsonschema:"description=The path to a local chart's folder or .tgz archive"` Namespace string `json:"namespace" jsonschema:"description=The namespace to deploy the chart to"` - ValuesFiles []string `json:"valuesFiles,omitempty" jsonschema:"description=List of local values file paths or remote URLs to include in the package; these will be merged together"` - GitPath string `json:"gitPath,omitempty" jsonschema:"description=The path to the chart in the repo if using a git repo instead of a helm repo,example=charts/your-chart"` - LocalPath string `json:"localPath,omitempty" jsonschema:"description=The path to the local chart's folder or .tgz archive"` + ReleaseName string `json:"releaseName,omitempty" jsonschema:"description=The name of the Helm release to create (defaults to the Zarf name of the chart)"` NoWait bool `json:"noWait,omitempty" jsonschema:"description=Whether to not wait for chart resources to be ready before continuing"` + ValuesFiles []string `json:"valuesFiles,omitempty" jsonschema:"description=List of local values file paths or remote URLs to include in the package; these will be merged together when deployed"` } // ZarfManifest defines raw manifests Zarf will deploy as a helm chart. diff --git a/zarf.schema.json b/zarf.schema.json index 7f4aa0abf3..d8d1b5c3ac 100644 --- a/zarf.schema.json +++ b/zarf.schema.json @@ -148,11 +148,11 @@ "properties": { "name": { "type": "string", - "description": "The name of the chart to deploy; this should be the name of the chart as it is installed in the helm repo" + "description": "The name of the chart within Zarf; note that this must be unique and does not need to be the same as the name in the chart repo" }, - "releaseName": { + "version": { "type": "string", - "description": "The name of the release to create; defaults to the name of the chart" + "description": "The version of the chart to deploy; for git-based charts this is also the tag of the git repo by default (when not using the '@' syntax for 'repos')" }, "url": { "type": "string", @@ -160,38 +160,42 @@ "examples": [ "OCI registry: oci://ghcr.io/stefanprodan/charts/podinfo", "helm chart repo: https://stefanprodan.github.io/podinfo", - "git repo: https://github.com/stefanprodan/podinfo" + "git repo: https://github.com/stefanprodan/podinfo (note the '@' syntax for 'repos' is supported here too)" ] }, - "version": { + "repoName": { "type": "string", - "description": "The version of the chart to deploy; for git-based charts this is also the tag of the git repo" - }, - "namespace": { - "type": "string", - "description": "The namespace to deploy the chart to" - }, - "valuesFiles": { - "items": { - "type": "string" - }, - "type": "array", - "description": "List of local values file paths or remote URLs to include in the package; these will be merged together" + "description": "The name of a chart within a Helm repository (defaults to the Zarf name of the chart)" }, "gitPath": { "type": "string", - "description": "The path to the chart in the repo if using a git repo instead of a helm repo", + "description": "(git repo only) The sub directory to the chart within a git repo", "examples": [ "charts/your-chart" ] }, "localPath": { "type": "string", - "description": "The path to the local chart's folder or .tgz archive" + "description": "The path to a local chart's folder or .tgz archive" + }, + "namespace": { + "type": "string", + "description": "The namespace to deploy the chart to" + }, + "releaseName": { + "type": "string", + "description": "The name of the Helm release to create (defaults to the Zarf name of the chart)" }, "noWait": { "type": "boolean", "description": "Whether to not wait for chart resources to be ready before continuing" + }, + "valuesFiles": { + "items": { + "type": "string" + }, + "type": "array", + "description": "List of local values file paths or remote URLs to include in the package; these will be merged together when deployed" } }, "additionalProperties": false,