From 6904e8bac18619124bdeda9da879bd91bbd76b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha?= Date: Fri, 26 Sep 2025 16:12:10 +0200 Subject: [PATCH 1/3] Doc preference for safe navigation of nested values --- doc/development/style_guide.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index 151194d365..d9626023d4 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -240,6 +240,24 @@ Let's look at two snippet examples, which easily exemplify the reasoning: Related issue: [#729 Refactoring: Helm templates](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/729) +### Nested Value Access + +When accessing nested values in Helm templates, always use safe navigation patterns to prevent template rendering failures. + +**Preferred approach**: Use parentheses syntax for safe nested value access: + +```yaml +{{- $host := (((.Values.database).connection).host) -}} +{{- $port := (((.Values.database).connection).port) -}} +``` + +**Avoid**: Direct nested access without safety checks: + +```yaml +{{/* ❌ Unsafe - will fail if intermediate objects are null */}} +{{- if .Values.database.connection.host -}} +``` + ### When to utilize `toYaml` in templates It is frowned upon to default to utilizing a `toYaml` in the template files as -- GitLab From 0453dbd1474375140c74b2e4803ac89e544c243e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha?= Date: Tue, 7 Oct 2025 22:07:33 +0200 Subject: [PATCH 2/3] Provide guidence on using dig, index, and direct access --- doc/development/style_guide.md | 44 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index d9626023d4..c837e75e85 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -242,16 +242,54 @@ Related issue: [#729 Refactoring: Helm templates](https://gitlab.com/gitlab-org/ ### Nested Value Access -When accessing nested values in Helm templates, always use safe navigation patterns to prevent template rendering failures. +When accessing nested values in Helm templates, choose the appropriate safe navigation pattern based on your use case to prevent template rendering failures. Below we describe each case with examples. -**Preferred approach**: Use parentheses syntax for safe nested value access: +#### When to use each approach + +- **`dig`**: When you need fallback defaults and the path is known at template time. Best for most use cases. +- **`index`**: When accessing dynamic keys, working with complex nested structures, or when performance is critical. +- **Parentheses**: For simple cases where you just need safe navigation without defaults. +- **Direct access**: Only when you can guarantee the full path exists (rare in practice). + +#### Performance considerations + +Functions like `dig` and `index` can be more efficient than deeply nested parentheses, especially when accessing the same nested structure multiple times. Consider storing the result in a variable for reuse. + +#### Use `dig` for safe access with fallback defaults + +The [`dig` function](https://masterminds.github.io/sprig/dicts.html#dig) provides safe nested access with default values and is often the most robust approach: + +```yaml +{{- $host := dig "database" "connection" "host" "localhost" .Values -}} +{{- $port := dig "database" "connection" "port" 5432 .Values -}} +{{- $enabled := dig "registry" "enabled" false .Values.global -}} +``` + +#### Use `index` for dynamic keys or performance-critical paths + +The [`index` function](https://helm.sh/docs/chart_template_guide/function_list/#index) is ideal when accessing dynamic keys or when performance matters: + +```yaml +{{- $config := index .Values.global.redis .redisConfigName | default dict -}} +{{- $image := index .Values "shared-secrets" "selfsign" "image" -}} +{{- $settings := index .Values.gitlab "gitlab-shell" -}} +``` + +#### Use parentheses for simple safe navigation + +Parentheses syntax works well for straightforward cases where you need basic safe navigation: ```yaml {{- $host := (((.Values.database).connection).host) -}} {{- $port := (((.Values.database).connection).port) -}} ``` -**Avoid**: Direct nested access without safety checks: +But note that if you already know for other means that, ofr instance, `.Values.database` is present, you can simplify +the safe navitation with `(.Values.database.connection).port`. + +#### Avoid direct nested access without safety checks + +Direct access should only be used when you can guarantee the full path exists: ```yaml {{/* ❌ Unsafe - will fail if intermediate objects are null */}} -- GitLab From 7377494d41ff100ed7b2692ca1db772fd69161ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha?= Date: Mon, 13 Oct 2025 21:55:49 +0200 Subject: [PATCH 3/3] Clarify use of index and remove Performance bit It's very unlikely that we'll get impacted by Performance. So the section about it is not so useful. --- doc/development/style_guide.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md index c837e75e85..2497c7b506 100644 --- a/doc/development/style_guide.md +++ b/doc/development/style_guide.md @@ -247,14 +247,10 @@ When accessing nested values in Helm templates, choose the appropriate safe navi #### When to use each approach - **`dig`**: When you need fallback defaults and the path is known at template time. Best for most use cases. -- **`index`**: When accessing dynamic keys, working with complex nested structures, or when performance is critical. +- **`index`**: When accessing dynamic keys, working with complex nested structures, or naming conventions imcompatible with Go, like kebab-case or snake_case. - **Parentheses**: For simple cases where you just need safe navigation without defaults. - **Direct access**: Only when you can guarantee the full path exists (rare in practice). -#### Performance considerations - -Functions like `dig` and `index` can be more efficient than deeply nested parentheses, especially when accessing the same nested structure multiple times. Consider storing the result in a variable for reuse. - #### Use `dig` for safe access with fallback defaults The [`dig` function](https://masterminds.github.io/sprig/dicts.html#dig) provides safe nested access with default values and is often the most robust approach: @@ -265,14 +261,12 @@ The [`dig` function](https://masterminds.github.io/sprig/dicts.html#dig) provide {{- $enabled := dig "registry" "enabled" false .Values.global -}} ``` -#### Use `index` for dynamic keys or performance-critical paths +#### Use `index` for dynamic keys, or naming conventions incompatible with Go -The [`index` function](https://helm.sh/docs/chart_template_guide/function_list/#index) is ideal when accessing dynamic keys or when performance matters: +Use [`index`](https://helm.sh/docs/chart_template_guide/function_list/#index) for dynamic keys or Go-incompatible naming like `kebab-case`: ```yaml -{{- $config := index .Values.global.redis .redisConfigName | default dict -}} {{- $image := index .Values "shared-secrets" "selfsign" "image" -}} -{{- $settings := index .Values.gitlab "gitlab-shell" -}} ``` #### Use parentheses for simple safe navigation @@ -284,7 +278,7 @@ Parentheses syntax works well for straightforward cases where you need basic saf {{- $port := (((.Values.database).connection).port) -}} ``` -But note that if you already know for other means that, ofr instance, `.Values.database` is present, you can simplify +But note that if you already know for other means that, for instance, `.Values.database` is present, you can simplify the safe navitation with `(.Values.database.connection).port`. #### Avoid direct nested access without safety checks -- GitLab