Fix crash on empty helm render: treat no-output chart as no-op - #207
Merged
Conversation
When helm template --output-dir produces an empty directory (e.g. all templates are gated behind a falsy conditional), ReplaceWithRendered now removes the chart's content dirs and returns successfully with an empty file list instead of crashing with an assertion error. Adds test chart testdata/charts/emptychart and integration test 'empty render no op' to cover this scenario. Closes #206
Copilot
AI
changed the title
[WIP] Fix chartify crash on empty render
Fix crash on empty helm render: treat no-output chart as no-op
Aug 1, 2026
Addresses the gaps identified in review of the empty-render fix (#206): 1. replace.go: the empty-render branch no longer early-returns. It removes the content dirs and temp output, then falls through so the Chart.yaml `dependencies` field and Chart.lock/requirements.lock cleanup still run. Without this, an empty-rendering chart that declares dependencies would leave Chart.yaml referencing subcharts whose charts/ dir was removed, causing a downstream "found in Chart.yaml, but missing in charts/ directory" error. Also fixes %v -> %w wrapping and adds path context. 2. chartify.go: skip the kustomize Patch step when no resources were rendered (`len(generatedManifestFiles) == 0`). Previously an empty render combined with JsonPatches/StrategicMergePatches/Transformers fed kustomize an empty resource list plus patches, failing with "no resource matches strategic merge patch ...". An empty render is now a no-op success even when patches are configured (there is simply nothing to patch). Tests: - TestEmptyRenderCleansChartDependencies: verifies a chart that declares a dependency and renders nothing still produces a chartifiable output whose Chart.yaml has no dependencies and templates empty. Proven to fail without fix #1. - integration "empty render with patch": exercises the StrategicMergePatches path on the empty chart; proven to fail without fix #2. - testdata/chart_patch/configmap.emptychart.strategic.yaml + empty snapshot. Signed-off-by: yxxhero <aiopsclub@163.com>
yxxhero
force-pushed
the
copilot/chartify-crashes-on-empty-render
branch
from
August 2, 2026 23:05
6935ef1 to
f2507b1
Compare
yxxhero
marked this pull request as ready for review
August 2, 2026 23:08
There was a problem hiding this comment.
Pull request overview
This pull request updates Chartify’s Helm render/replace pipeline to gracefully handle charts that render zero resources (empty helm template --output-dir result), treating that case as a successful no-op instead of crashing with an assertion error. This aligns Chartify behavior with downstream expectations (e.g., helmfile) and prevents kustomize/patch processing from running on an empty resource set.
Changes:
- Handle empty
helm template --output-diroutput inReplaceWithRenderedby cleaning up rendered/output dirs and chart content dirs, then returning an empty rendered-file list without error. - Skip the kustomize build/patch step when there are no generated manifest files, even if patch options were provided.
- Add an integration test chart and new integration + unit tests to cover empty-render behavior (including dependency cleanup).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| replace.go | Detects empty helm output-dir and treats it as a no-op success while still performing dependency/lock cleanup. |
| chartify.go | Skips kustomize patch/build when generatedManifestFiles is empty to avoid patching/building nothing. |
| integration_test.go | Adds integration coverage for “empty render no op” and “empty render with patch” scenarios. |
| chartify_test.go | Adds a focused unit test to ensure dependency cleanup still happens on empty renders. |
| testdata/charts/emptychart/Chart.yaml | Introduces a minimal chart that renders nothing by default to exercise the empty-render path. |
| testdata/charts/emptychart/values.yaml | Defaults enabled: false to ensure the chart renders no resources. |
| testdata/charts/emptychart/templates/configmap.yaml | Template gated behind Values.enabled, producing zero manifests by default. |
| testdata/chart_patch/configmap.emptychart.strategic.yaml | Patch fixture used by the “empty render with patch” integration test. |
| testdata/integration/testcases/empty_render_no_op/want | Snapshot expectation for the empty-render no-op integration case (empty output). |
| testdata/integration/testcases/empty_render_with_patch/want | Snapshot expectation for the empty-render-with-patch integration case (empty output). |
Suppressed comments (1)
integration_test.go:283
- Same as above: this snippet uses
go1.25but go.mod declaresgo 1.26.0, sogo1.25 testwill error. Usego test(orgo1.26 test) in the example command.
// SAVE_SNAPSHOT=1 go1.25 test -run ^TestIntegration/empty_render_with_patch$ ./
The SAVE_SNAPSHOT example comments used `go1.25 test`, but this repo's go.mod requires Go 1.26.0+, so `go1.25 test` would fail. Switch to the unversioned `go test` (reviewer's preferred form) on the two empty-render test cases flagged in review. Signed-off-by: yxxhero <aiopsclub@163.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When all chart templates are gated behind a falsy conditional,
helm template --output-dirproduces an empty directory.ReplaceWithRenderedthen crashed with an opaque assertion error because it expected exactly one subdirectory in the output dir.Changes
replace.go: After readinghelmOutputDirEntries, if the slice is empty, remove the chart's content dirs (templates/,charts/,crds/) so subsequent helm processing also sees no resources, clean up the temp output dir, and returnnil, nil(empty file list, no error). This is a no-op from the caller's perspective.testdata/charts/emptychart/: Minimal test chart with a ConfigMap template fully gated behind{{- if .Values.enabled }}(default:false).integration_test.go: New"empty render no op"integration test exercising this path viaOverrideNamespace(which forcesReplaceWithRenderedto be called).Example
Previously, running chartify against such a chart (with any of
OverrideNamespace,JsonPatches,StrategicMergePatches, orTransformersconfigured) would crash:After this fix, chartify returns successfully with an empty resource list.