feat(helm): support optional: prefix on individual valueFiles entries (#27698)#27699
Open
thoro wants to merge 1 commit intoargoproj:masterfrom
Open
feat(helm): support optional: prefix on individual valueFiles entries (#27698)#27699thoro wants to merge 1 commit intoargoproj:masterfrom
thoro wants to merge 1 commit intoargoproj:masterfrom
Conversation
Per-entry optionality complements the existing all-or-nothing ignoreMissingValueFiles flag and preserves positional ordering. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Rosenstein <thomas.rosenstein@avafin.com>
✅ Preview Environment deployed on Bunnyshell
See: Environment Details | Pipeline Logs Available commands (reply to this comment):
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #27699 +/- ##
=======================================
Coverage 63.84% 63.85%
=======================================
Files 418 418
Lines 57269 57279 +10
=======================================
+ Hits 36566 36574 +8
Misses 17290 17290
- Partials 3413 3415 +2 ☔ View full report in Codecov by Sentry. |
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.
Disclaimer: This PR was created and drafted together with Claude Opus 4.7
Closes #27698.
What this PR does
Adds an
optional:prefix that can be applied to any single entry insource.helm.valueFiles. A prefixed entry behaves as ifignoreMissingValueFileswere set, but only for that one entry — siblingentries without the prefix remain strict.
Behavior:
optional:entry: silently skipped.optional:on a glob: zero-match is silently skipped instead of raisingGlobNoMatchError.optional:composes with$refsources, env substitution, glob expansion,and remote URLs.
ignoreMissingValueFiles: truekeeps working unchanged. When set, bareentries continue to be silently skipped on miss;
optional:entries arealso silently skipped (
||semantics).in its declared position next to its base.
Why a string prefix instead of a structured field
valueFilesis[]stringtoday. A typed{path, optional}element wouldbetter match Kubernetes API style (and matches how
configMapKeyRef.optionaletc. are expressed) but is an API break — every consumer of
valueFiles,including ApplicationSet templates and the CLI, would need to handle both
forms. A reserved string prefix lands the feature with no schema change, no
CRD bump, and no
valueFilesv2 field, while preserving the positionalordering that a separate
optionalValueFileslist would lose.The literal token
optional:becomes reserved at the start ofvalueFilesentries. Linux filesystems do allow
:in filenames, but it is rare inpractice (clashes with
host:pathrsync/scp conventions andPATHseparators). If a real file is genuinely named
optional:something.yaml,the entry can be escaped by prefixing with
./— only entries that startwith the literal token are treated as markers, so
./optional:legacy.yamlis parsed as a path. The docs call this out explicitly.
Why the word
optionalKubernetes already uses
optional: truefor the same semantic onconfigMapKeyRef,secretKeyRef,envFrom, andvolumes.*. Anyone readingan ArgoCD manifest will recognize the word. Alternatives considered:
?prefix — collides visually with the doublestar single-character glob.-prefix — collides with the YAML list bullet.opt:— abbreviation; no precedent.Implementation
Self-contained to
reposerver/repository/repository.go:New helper
splitOptionalPrefix(raw string) (string, bool)strips theoptional:token and reports whether it was present. Usesstrings.CutPrefixto match the existing parsing style in the same file(e.g.
alias:handling at line 1158).The helper is called at every site that interprets a
valueFilesstring,so the marker composes with every existing feature without further parser
updates:
getReferencedSourceName— central ref-source parser; coversgetReferencedSourcesandgetReferencedSourceautomatically.strings.HasPrefix(valueFile, "$")ref-preflight sitesin
resolveReferencedSources,runManifestGenAsync, andUpdateRevisionForPaths.getResolvedValueFiles(the pre-pass that buildsexplicitPaths, and the main resolution loop).In
getResolvedValueFiles, the per-entryoptionalflag is OR'd intothe two existing skip branches:
That is the entire functional diff. No CRD bump, no API version bump, no
ApplicationSet template changes, no CLI changes. Existing manifests behave
identically.
Tests
In
reposerver/repository/repository_test.go:Test_splitOptionalPrefix— unit-tests the helper across bare paths,prefixed paths, prefixed
$ref, prefixed glob, empty rest, andcase-sensitivity.
Test_getResolvedValueFiles_optional— integration-level cases:optional:on a missing plain path → skipped.optional:on an existing plain path → included.optional:on an existing$refsource → resolved through the ref.optional:on a missing$refsource path → skipped.optional:on a glob with matches → behaves like a normal glob.optional:on a glob with zero matches → skipped without error.passed through to helm (helm errors later, current contract).
still raises
GlobNoMatchError.ignoreMissingValueFiles=truepaired withoptional:entries →behavior unchanged for bare entries;
optional:continues to work.All new and existing valueFile-related tests pass under
-race.Documentation
docs/user-guide/helm.mdgains a "Marking a single file as optional"section right next to the existing
ignoreMissingValueFilesdescription,with a synthetic apps-of-apps example, a note that the marker composes with
ref sources / globs / remote URLs, and a callout that
optional:is areserved prefix.
Backwards compatibility
valueFilesremains[]string— no CRD, OpenAPI, or API version change.optional:entries are unaffected.ignoreMissingValueFileskeeps current semantics.argocd app set --values <path>and ApplicationSet template-producedstrings can carry
optional:transparently — no CLI or template codechanges needed.
Feature status
Proposed as Stable per the feature-status rubric:
before; only entries that explicitly start with
optional:opt in.evolve out of.
could change incompatibly later.
Happy to demote to Beta (with a
[BETA]marker on the docs section)if maintainers prefer the conservative path. Alpha would mean wiring
a feature flag to gate prefix recognition; I'd rather not add that
unless explicitly requested, since a silently no-op
optional:ondefault config is its own footgun.
Related issues
ignoreMissingValueFiles(this is the per-entryfollow-up)
helm.fileParameterscomponents/patchesin kustomize applications (similar toignoreMissingValueFilesfor helm) #18634 — same gap inkustomize.components/patches