test: add integration test for selector filtering with requiredEnv (#1172) (#2678)

* fix: retry rendering with lenient requiredEnv when selectors are active (#1172)

The entire helmfile document is rendered as a Go template before selector
labels filter releases. This means requiredEnv calls in releases excluded
by selectors still fail, blocking the whole run.

When selectors are active and rendering fails due to a requiredEnv error,
helmfile now retries with lenient mode: unset env vars produce empty
strings instead of failing. The document can then be parsed and filtered
by selectors normally.

Behavior:
- Without selectors: requiredEnv fails as before (validation preserved)
- With selectors, all env vars set: strict render succeeds, no retry
- With selectors, some env vars missing: lenient retry, excluded releases
  get empty values and are filtered out by selectors

Implementation:
- Add RequiredEnvError type + ErrRequiredEnvNotSet sentinel for type-safe
  error detection via errors.As
- Add lenientRequiredEnv flag to tmpl.Context; requiredEnv returns empty
  string instead of failing when set
- Add NewLenientFileRenderer via functional options pattern
  (FileRendererOption / WithPreRender / WithLenientRequiredEnv)
- Extract renderWithSelectorFallback in two_pass_renderer.go
- Pass selectors from LoadOpts to desiredStateLoader

Closes #1172

Signed-off-by: yxxhero <yxxhero@example.com>
Signed-off-by: yxxhero <aiopsclub@163.com>

* test: add integration test for selector filtering with requiredEnv (#1172)

Verify that selector-based filtering works correctly when requiredEnv is
used in release values. Users set all required env vars, so rendering
succeeds, and selectors filter out non-matching releases.

Test scenarios:
- helmfile template -l tier=label2: only rel2 is templated (rel1 excluded)
- helmfile template without selector: both releases are templated

Closes #1172

Signed-off-by: yxxhero <yxxhero@example.com>
Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <yxxhero@example.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
yxxhero
2026-06-30 09:04:05 +08:00
committed by GitHub
parent 4518dc7aa3
commit 365afc0577
3 changed files with 81 additions and 0 deletions
+1
View File
@@ -147,6 +147,7 @@ ${kubectl} create namespace ${test_ns} || fail "Could not create namespace ${tes
. ${dir}/test-cases/issue-1880-transformers-with-file-deps.sh
. ${dir}/test-cases/issue-821-adhoc-dep-go-getter.sh
. ${dir}/test-cases/issue-2599-default-inherit.sh
. ${dir}/test-cases/issue-1172-selector-required-env.sh
. ${dir}/test-cases/kubedog-tracking.sh
. ${dir}/test-cases/lookup.sh
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# Test for issue #1172: Helmfile renders entire helmfile even with selector labels
# https://github.com/helmfile/helmfile/issues/1172
#
# This test verifies that selector-based filtering works correctly when
# requiredEnv is used in release values. Users set all required env vars,
# so rendering succeeds, and selectors filter out non-matching releases.
issue_1172_case_dir="$(cd "${cases_dir}/issue-1172-selector-required-env" && pwd)"
issue_1172_tmp=$(mktemp -d)
cleanup_issue_1172() {
rm -rf "${issue_1172_tmp}"
}
trap cleanup_issue_1172 EXIT
test_start "issue-1172: selector filtering with requiredEnv"
export ISSUE_1172_BUZZ="test-buzz-value"
# Test 1: With selector tier=label2, only rel2 should be templated
info "Test 1: helmfile template with -l tier=label2 should only template rel2"
code=0
${helmfile} -f "${issue_1172_case_dir}/input/helmfile.yaml.gotmpl" \
template -l tier=label2 > "${issue_1172_tmp}/selected.yaml" 2>&1 || code=$?
if [ ${code} -ne 0 ]; then
cat "${issue_1172_tmp}/selected.yaml"
fail "helmfile template with selector should succeed when all env vars are set"
fi
if grep -q "release: rel1" "${issue_1172_tmp}/selected.yaml"; then
fail "rel1 should NOT be templated when selector tier=label2 is active"
fi
if ! grep -q "release: rel2" "${issue_1172_tmp}/selected.yaml"; then
cat "${issue_1172_tmp}/selected.yaml"
fail "rel2 should be templated when selector tier=label2 is active"
fi
info "PASS: only rel2 was templated with selector"
# Test 2: Without selector, both releases should be templated
info "Test 2: helmfile template without selector should template both releases"
code=0
${helmfile} -f "${issue_1172_case_dir}/input/helmfile.yaml.gotmpl" \
template > "${issue_1172_tmp}/all.yaml" 2>&1 || code=$?
if [ ${code} -ne 0 ]; then
cat "${issue_1172_tmp}/all.yaml"
fail "helmfile template without selector should succeed when all env vars are set"
fi
if ! grep -q "release: rel1" "${issue_1172_tmp}/all.yaml"; then
fail "rel1 should be templated when no selector is active"
fi
if ! grep -q "release: rel2" "${issue_1172_tmp}/all.yaml"; then
fail "rel2 should be templated when no selector is active"
fi
info "PASS: both releases were templated without selector"
trap - EXIT
cleanup_issue_1172
test_pass "issue-1172: selector filtering with requiredEnv"
@@ -0,0 +1,13 @@
releases:
- name: rel1
chart: ../../../charts/httpbin
labels:
tier: label1
values:
- image:
repository: {{ requiredEnv "ISSUE_1172_BUZZ" }}
- name: rel2
chart: ../../../charts/httpbin
labels:
tier: label2