What does helm package produce, and what determines the archive's filename?
answer
- A chart ships as one file
- The filename is derived, not chosen
- Two Chart.yaml fields decide it
- name-version.tgz, SemVer 2 enforced
- One top-level directory inside
basics
~20 shelm package compresses a chart directory into a gzipped tar named <name>-<version>.tgz, with both parts read from Chart.yaml. The version must be valid SemVer 2, and the archive unpacks into one directory named for the chart.
solid answer
~40 s`helm package ./pdfsign` reads `Chart.yaml`, validates the metadata and writes `pdfsign-2.7.3.tgz` into the working directory; `-d/--destination` sends it elsewhere. The filename is a contract, not a label: it is always `<name>-<version>.tgz`, and both halves come from `Chart.yaml`, so the directory name on disk is irrelevant. `version` must parse as SemVer 2 or packaging fails, and `--version` / `--app-version` override those two fields at package time, which is how CI stamps a build without editing the file. `-u/--dependency-update` resolves declared dependencies into `charts/` first, so an optional bundled database subchart is vendored inside the tarball. Everything under the chart directory is included except what `.helmignore` excludes, and the archive expands to a single top-level directory named after the chart. Run `helm lint` first — `helm package` is not a linter and never renders a template.
code
bash · 5 lineshelm lint ./pdfsign
helm package -u -d ./dist ./pdfsign
# ./dist/pdfsign-2.7.3.tgz
helm show chart ./dist/pdfsign-2.7.3.tgz
helm install pdfsign ./dist/pdfsign-2.7.3.tgzgo deeper
Be ready to say what the command outputs and where the name comes from: a <name>-<version>.tgz built from the name and version fields of Chart.yaml, written to the current directory unless you pass a destination.
Explain the mechanics around it: SemVer 2 enforcement on version, the version/appVersion split, -u vendoring subcharts into charts/, the single top-level directory inside the archive, and the fact that packaging never renders a template.
Show the pipeline judgement: lint and render before packaging, package into a clean output directory, keep the version bump in the same commit as the change, and treat a published archive as immutable rather than rebuilding over it.
Own the artifact policy: who is allowed to cut a chart version, how chart versions relate to application releases across many teams, and whether charts are versioned per-service or as one platform bundle.
### A chart is an artifact, not a folder During development a chart is a directory: `Chart.yaml`, `values.yaml`, `templates/`, maybe `charts/` and `crds/`. `helm package` turns that directory into the distributable form of the same thing — a gzip-compressed tar archive. Everything downstream of packaging (a chart repository, an `oci://` reference, an air-gapped copy on a USB stick, `helm install ./pdfsign-2.7.3.tgz`) deals in that archive rather than in your working tree. Interviewers ask about it because the difference between "a folder of YAML I happen to have" and "a versioned artifact somebody else can pin" is the whole reason Helm exists. ### The filename is derived, not chosen The output is always `<name>-<version>.tgz`, where `name` and `version` are the two required fields of `Chart.yaml`. A chart directory called `pdf-signer-chart` whose `Chart.yaml` says `name: pdfsign` and `version: 2.7.3` packages to `pdfsign-2.7.3.tgz`. `helm lint` flags a directory whose name disagrees with the chart name, and that is worth fixing because humans read the directory and tools read `Chart.yaml`. `version` is the chart's own version and must be a valid SemVer 2 string; packaging fails outright on a value Helm cannot parse. `appVersion` — the version of the software the chart deploys — is free-form and has no effect on the filename. That split is what lets you ship `pdfsign-2.7.4.tgz` as a template-only fix with `appVersion` unchanged. Inside the tarball there is exactly one top-level directory, named after the chart, with the chart files beneath it. Helm's loader relies on that shape, which is why you cannot simply `tar czf` a directory's *contents* and expect Helm to read it. ### The flags that actually come up - `-d, --destination` — write the `.tgz` somewhere other than the current directory (in CI, a dedicated output dir). - `-u, --dependency-update` — resolve the dependencies declared in `Chart.yaml` into `charts/` before packaging, so subcharts travel inside the archive. A chart for a PDF-signing service with an optional bundled database subchart carries that subchart's `.tgz` under `charts/`; the toggle that decides whether it is *installed* is a value, but the bytes are in the package either way. - `--version` / `--app-version` — override the two `Chart.yaml` fields for this build. A pipeline that packages `2.7.3-rc.14` from a release branch without committing that string uses these. - `--sign` and its key flags exist too, but signing a package into a `.prov` file is a separate concern from producing the `.tgz` itself. ### What packaging does *not* do This is where junior answers go wrong. `helm package` does not render templates, does not contact a cluster, does not validate that your `Deployment` is legal Kubernetes, and does not publish anything. It checks the chart metadata, collects the files the loader can see, and writes an archive. A chart with a template that fails to parse packages happily and explodes at install time — which is why `helm lint` (and, better, a render in CI) belongs in front of it. It also does not upload. Making the archive discoverable — building or updating a repository index, or pushing it to an OCI registry — is a distinct step after packaging. ### Consuming the result A packaged chart is a first-class input everywhere a directory is: `helm install pdfsign ./pdfsign-2.7.3.tgz`, `helm template`, `helm show chart pdfsign-2.7.3.tgz`, `helm upgrade`. Because the chart's identity lives in `Chart.yaml` *inside* the archive, renaming the file does not rename the chart — but repository tooling expects the canonical name, so do not rename it. One more consequence worth knowing: the archive is a snapshot. `.helmignore` decided what went in at package time, and nothing you change in the source tree afterwards affects a `.tgz` that already exists. If the wrong file got in, you fix the ignore rules and cut a new version — you never edit a published archive in place. ### Reading a chart you were handed The same properties make an unfamiliar archive easy to interrogate without installing it. `helm show chart` prints the metadata, `helm show values` prints the defaults, and listing the tar contents tells you what files came along — a chart that ships 18 MB of sample documents or a stray developer values file announces itself immediately. Doing that once, before a chart enters a production path, catches most of what goes wrong at packaging time. ### A workable habit In CI: lint, render, package into a clean output directory, then hand the `.tgz` to whatever publishes it. Keep the version bump in the same commit as the change, so the artifact name alone tells you what is inside it.
- What does --app-version change, and why would a pipeline set it?It overrides the `appVersion` field written into the packaged chart, which describes the software being deployed rather than the chart itself. A pipeline that builds an image tagged 5.14.3 can package the chart with `--app-version 5.14.3` so the artifact records what it ships, without a commit that edits `Chart.yaml`. It does not affect the archive filename — only `--version` does that.
- Your chart declares an optional bundled database subchart. What actually ends up inside the .tgz?The subchart archive is vendored under `charts/` and travels inside the package, so the tarball is self-contained and installs without network access to the dependency's repository. `-u` resolves dependencies before packaging; without it you package whatever is already in `charts/`, which may be stale or empty. Whether the subchart is installed at runtime is a values decision, not a packaging one.
- Can you rename pdfsign-2.7.3.tgz and still install it?Locally, yes — Helm reads the chart's identity from the `Chart.yaml` inside the archive, so `helm install` from an odd filename works. But repository tooling and any digest-keyed reference expect the canonical `<name>-<version>.tgz`, so renaming is a good way to produce an artifact nobody can resolve later. Treat the name as generated output.
The chart directory is the recipe you are still editing; helm package is sealing it into a labelled tin, where the label is printed from the recipe itself rather than written on by hand.
saying these in an interview costs you the question
- Thinks the .tgz filename is cosmetic and can be anything
- Says the archive name comes from the chart directory name
- Assumes helm package renders templates and catches template errors
- Believes packaging also publishes or signs the chart
- Confuses version with appVersion when naming the artifact
- Expects a .helmignore edit to change an already-built archive