@@ -90,6 +90,241 @@ source:
9090 ignoreMissingValueFiles: true
9191` ` `
9292
93+ # # Glob Patterns in Value Files
94+
95+ Glob patterns can be used in `valueFiles` entries to match multiple files at once. This is useful
96+ when the set of environment-specific override files is not known in advance, or when you want to
97+ pick up new files automatically without updating the Application spec.
98+
99+ ` ` ` bash
100+ # Single quotes prevent the shell from expanding the glob before Argo CD receives it
101+ argocd app set helm-guestbook --values 'envs/*.yaml'
102+ ` ` `
103+
104+ In the declarative syntax :
105+
106+ ` ` ` yaml
107+ source:
108+ helm:
109+ valueFiles:
110+ - envs/*.yaml
111+ ` ` `
112+
113+ # ## Supported pattern syntax
114+
115+ Glob expansion uses the [doublestar](https://github.com/bmatcuk/doublestar) library.
116+
117+ | Pattern | Description |
118+ |---------|-------------|
119+ | `*` | Matches any sequence of non-separator characters within a single directory level |
120+ | `?` | Matches any single non-separator character |
121+ | `[abc]` | Matches one of the characters listed inside the brackets |
122+ | `[a-z]` | Matches any character in the given range |
123+ | `**` | Matches any sequence of characters including `/` (recursive across directory levels) |
124+
125+ # ## How files are passed to Helm
126+
127+ Each matched file is passed to `helm template` as a separate `--values <path>` flag, in the same
128+ order they appear after expansion. This is identical to listing each file individually in
129+ ` valueFiles` . Argo CD does the expansion before invoking Helm.
130+
131+ Matched files are expanded **in-place** within the `valueFiles` list and sorted in **lexical
132+ (alphabetical) order**. Because Helm gives higher precedence to later `--values` flags, lexical
133+ order determines which file wins when the same key appears in multiple files.
134+
135+ ```
136+ envs/
137+ a.yaml # sets foo: a-value
138+ b.yaml # sets foo: b-value
139+ ```
140+
141+ ```yaml
142+ # envs/*.yaml expands to: envs/a.yaml, envs/b.yaml (lexical order)
143+ # b.yaml is last → foo = "b-value"
144+ source:
145+ helm:
146+ valueFiles:
147+ - envs/*.yaml
148+ ```
149+
150+ When you have multiple entries in ` valueFiles ` , the relative order between entries is preserved.
151+ Glob expansion only reorders files within a single pattern:
152+
153+ ``` yaml
154+ valueFiles :
155+ - base.yaml # passed first
156+ - overrides/*.yaml # expanded in lexical order, passed after base.yaml
157+ - final.yaml # passed last, highest precedence
158+ ` ` `
159+
160+ ### Recursive matching with ` **`
161+
162+ Use `**` to match files at any depth below a directory :
163+
164+ ` ` ` yaml
165+ # envs/**/*.yaml processes each directory's own files before descending into subdirectories,
166+ # with directories and files sorted alphabetically at each level.
167+ #
168+ # envs/a.yaml ← 'a' (flat file in envs/)
169+ # envs/z.yaml ← 'z' (flat file in envs/, processed before descending)
170+ # envs/nested/c.yaml ← inside envs/nested/, processed after envs/ flat files
171+ #
172+ # nested/c.yaml is last → foo = "nested-value"
173+ source:
174+ helm:
175+ valueFiles:
176+ - envs/**/*.yaml
177+ ` ` `
178+
179+ > [!NOTE]
180+ > `**` matches zero or more path segments, so `envs/**/*.yaml` also matches files directly
181+ > inside `envs/` (not just subdirectories). doublestar traverses directories in lexical order
182+ > and processes each directory's own files (alphabetically) before descending into its
183+ > subdirectories. This means `envs/z.yaml` always comes before `envs/nested/c.yaml`, even
184+ > though `'n' < 'z'` alphabetically. To make ordering fully explicit and predictable,
185+ > use numeric prefixes (see [Naming conventions](#naming-conventions)).
186+
187+ # ## Using environment variables in glob patterns
188+
189+ [Build environment variables](./build-environment.md) are substituted **before** the glob is
190+ evaluated, so you can construct patterns dynamically :
191+
192+ ` ` ` yaml
193+ source:
194+ helm:
195+ valueFiles:
196+ - envs/$ARGOCD_APP_NAME/*.yaml
197+ ` ` `
198+
199+ This lets a single Application template expand to the right set of files per app name.
200+
201+ # ## Glob patterns with multiple sources
202+
203+ Glob patterns work with [value files from an external repository](./multiple_sources.md#helm-value-files-from-external-git-repository).
204+ The `$ref` variable is resolved first to the external repo's root, and the rest of the pattern is
205+ evaluated within that repo's directory tree :
206+
207+ ` ` ` yaml
208+ sources:
209+ - repoURL: https://git.example.com/my-configs.git
210+ ref: configs
211+ - repoURL: https://git.example.com/my-chart.git
212+ path: chart
213+ helm:
214+ valueFiles:
215+ - $configs/envs/*.yaml # matches files in the 'my-configs' repo under envs/
216+ ` ` `
217+
218+ # ## Naming conventions
219+
220+ Because files are sorted lexically, the sort order controls merge precedence. A common pattern is
221+ to use a numeric prefix to make the intended order explicit :
222+
223+ ` ` `
224+ values/
225+ 00-defaults.yaml
226+ 10-region.yaml
227+ 20-env.yaml
228+ 30-override.yaml
229+ ` ` `
230+
231+ ` ` ` yaml
232+ valueFiles:
233+ - values/*.yaml
234+ # expands to: 00-defaults.yaml, 10-region.yaml, 20-env.yaml, 30-override.yaml
235+ # 30-override.yaml has the highest precedence
236+ ` ` `
237+
238+ Without a prefix, pure alphabetical ordering applies. Be careful with names that sort
239+ unexpectedly, for example `values-10.yaml` sorts before `values-9.yaml` because `"1"` < `"9"`
240+ lexically.
241+
242+ # ## Constraints and limitations
243+
244+ **Path boundary**: Glob patterns cannot match files outside the repository root, even with
245+ patterns like `../../secrets/*.yaml`. Argo CD resolves the pattern's base path against the
246+ repository root before expanding it, and any match that would escape the root is rejected.
247+
248+ **Symlinks**: Argo CD follows symlinks when checking the path boundary. A symlink that lives
249+ inside the repository but points to a target outside the repository root is rejected, even though
250+ the symlink's own path is within the repo. This check applies to every file produced by glob
251+ expansion, including multi-hop symlink chains. Symlinks that resolve to a target still inside the
252+ repository are allowed.
253+
254+ **Absolute paths**: A path starting with `/` is treated as relative to the **repository root**,
255+ not the filesystem root. The pattern `/configs/*.yaml` matches files in the `configs/` directory
256+ at the top of the repository.
257+
258+ **Remote URLs are not glob-expanded**: Entries that are remote URLs (e.g.
259+ ` https://raw.githubusercontent.com/.../values.yaml` ) are passed to Helm as-is. Glob characters
260+ in a URL have no special meaning and will cause the URL to fail if the literal characters are not
261+ part of the URL.
262+
263+ **Shell quoting on the CLI**: Shells expand glob patterns before passing arguments to programs.
264+ Always quote patterns to prevent unintended shell expansion :
265+
266+ ` ` ` bash
267+ # Correct: single quotes pass the literal pattern to Argo CD
268+ argocd app set myapp --values 'envs/*.yaml'
269+
270+ # Incorrect: the shell expands *.yaml against the current directory first
271+ argocd app set myapp --values envs/*.yaml
272+ ` ` `
273+
274+ # ## Deduplication
275+
276+ Each file is included only once, but **explicit entries take priority over glob matches** when
277+ determining position. If a file appears both in a glob pattern and as an explicit entry, the glob
278+ skips it and the explicit entry places it at its declared position.
279+
280+ ` ` ` yaml
281+ valueFiles:
282+ - envs/*.yaml # expands to base.yaml, prod.yaml — but prod.yaml is listed explicitly below,
283+ # so the glob skips it: only base.yaml is added here
284+ - envs/prod.yaml # placed here at the end, giving it highest Helm precedence
285+ ` ` `
286+
287+ This means you can use a glob to pick up all files in a directory and then pin a specific file to
288+ the end (highest precedence) by listing it explicitly after the glob.
289+
290+ If the same file (same absolute path) is matched by two glob patterns, it is included at the
291+ position of the first match. Subsequent glob matches for that exact path are silently dropped.
292+ Files with the same name but at different paths are treated as distinct files and are always included.
293+
294+ ` ` ` yaml
295+ valueFiles:
296+ - envs/*.yaml # matches envs/base.yaml, envs/prod.yaml
297+ - envs/**/*.yaml # envs/prod.yaml already matched above and is skipped;
298+ # envs/nested/prod.yaml is a different path and is still included
299+ ` ` `
300+
301+ # ## No-match behavior
302+
303+ If a glob pattern matches no files, Argo CD saves the Application spec (the spec is not invalid and
304+ the files may be added to the repository later) and surfaces a `ComparisonError` condition on the
305+ Application :
306+
307+ ` ` `
308+ values file glob "nonexistent/*.yaml" matched no files
309+ ` ` `
310+
311+ The app will remain in a degraded state until the pattern matches at least one file or the pattern
312+ is removed. No spec update is required once the files are added to the repository.
313+
314+ To silently skip a pattern that matches no files instead of raising an error, combine the glob with
315+ `ignoreMissingValueFiles` :
316+
317+ ` ` ` yaml
318+ source:
319+ helm:
320+ valueFiles:
321+ - envs/*.yaml
322+ ignoreMissingValueFiles: true
323+ ` ` `
324+
325+ This is useful for implementing a default/override pattern where override files may not exist in
326+ every environment.
327+
93328# # Values
94329
95330Argo CD supports the equivalent of a values file directly in the Application manifest using the `source.helm.valuesObject` key.
0 commit comments