Skip to content

helmify mangles resource names and values.yaml keys when object names don't share a common prefix #201

Description

@mkarlheim

Description

For charts whose Kubernetes object names legitimately diverge (e.g. an umbrella
chart or multi-app manifest bundling several independent services), helmify silently
corrupts the generated resource names by stripping leading characters that were never
actually a shared prefix.

The output is still valid YAML/templates, so this is easy to miss and confusing to
debug. The derived values.yaml keys are mangled the same way.

Single-app charts are unaffected, because all their objects naturally share the
release-name prefix — which is likely why this hasn't been caught by existing
tests/examples.

Steps to reproduce

Save the following as manifests.yaml — four independent Deployments, as you'd have
in an umbrella chart. Note the names don't all share a common prefix, and two of them
(products, promotions) share a short one (pro):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders
  namespace: default
spec:
  replicas: 1
  selector: {matchLabels: {app: orders}}
  template:
    metadata: {labels: {app: orders}}
    spec:
      containers: [{name: orders, image: nginx:1.25}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments
  namespace: default
spec:
  replicas: 1
  selector: {matchLabels: {app: payments}}
  template:
    metadata: {labels: {app: payments}}
    spec:
      containers: [{name: payments, image: nginx:1.25}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: products
  namespace: default
spec:
  replicas: 1
  selector: {matchLabels: {app: products}}
  template:
    metadata: {labels: {app: products}}
    spec:
      containers: [{name: products, image: nginx:1.25}]
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: promotions
  namespace: default
spec:
  replicas: 1
  selector: {matchLabels: {app: promotions}}
  template:
    metadata: {labels: {app: promotions}}
    spec:
      containers: [{name: promotions, image: nginx:1.25}]

Run:

$ cat manifests.yaml | helmify mychart

Actual behavior

products and promotions lose their leading pro:

$ grep 'name: {{' mychart/templates/deployment.yaml
  name: {{ include "mychart.fullname" . }}-orders
  name: {{ include "mychart.fullname" . }}-payments
  name: {{ include "mychart.fullname" . }}-ducts        # <- should be -products
  name: {{ include "mychart.fullname" . }}-motions      # <- should be -promotions

The values.yaml keys are mangled identically:

$ grep -E '^[a-z]' mychart/values.yaml
ducts:                                                  # <- should be products
kubernetesClusterDomain: cluster.local
motions:                                                # <- should be promotions
orders:
payments:

Expected behavior

  name: {{ include "mychart.fullname" . }}-orders
  name: {{ include "mychart.fullname" . }}-payments
  name: {{ include "mychart.fullname" . }}-products
  name: {{ include "mychart.fullname" . }}-promotions

No prefix should be stripped when the objects share no common prefix.

Root cause

In pkg/metadata/metadata.go, detectCommonPrefix uses prevName == "" to mean
"not initialized yet". But "" is also the correct running value once it's
determined that objects share no common prefix.

Walking the example (objects are folded in document order):

step object running prefix note
1 orders orders first object
2 payments "" no common prefix with orders → correctly empty
3 products products bug: empty prefix mistaken for "uninitialized", reset to full name
4 promotions pro common of products and promotions

The final prefix pro then gets stripped off every matching name by TrimName,
turning productsducts and promotionsmotions. The result also depends on
object ordering, so it's non-deterministic across inputs.

Expected fix direction

Track prefix-fold initialization with a dedicated boolean (e.g.
commonPrefixSet bool) instead of overloading prevName == "", so
detectCommonPrefix never resets an empty-but-initialized prefix.

Happy to open a PR with a regression test.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions