From f03dbea74675db91191443a130886c4e28bfc92a Mon Sep 17 00:00:00 2001 From: Morten Olsen Date: Thu, 1 Jan 2026 13:28:58 +0100 Subject: [PATCH] transform forgejo --- apps/charts/common/TEMPLATING.md | 149 ++++++++++++++++++ apps/charts/common/common-1.0.0.tgz | Bin 0 -> 19154 bytes apps/charts/common/templates/_helpers.tpl | 121 ++++++++++++-- apps/charts/forgejo/Chart.yaml | 4 + apps/charts/forgejo/templates/deployment.yaml | 107 +------------ apps/charts/forgejo/templates/pvc.yaml | 12 +- apps/charts/forgejo/templates/service.yaml | 33 +--- .../forgejo/templates/virtual-service.yaml | 40 +---- apps/charts/forgejo/values.yaml | 100 +++++++++++- 9 files changed, 359 insertions(+), 207 deletions(-) create mode 100644 apps/charts/common/TEMPLATING.md create mode 100644 apps/charts/common/common-1.0.0.tgz diff --git a/apps/charts/common/TEMPLATING.md b/apps/charts/common/TEMPLATING.md new file mode 100644 index 0000000..a0f4f3a --- /dev/null +++ b/apps/charts/common/TEMPLATING.md @@ -0,0 +1,149 @@ +# Values Templating Guide + +This document explains how templating works in `values.yaml` files and what placeholders are available. + +## Current Placeholders + +The templating system supports the following placeholders in `values.yaml`: + +| Placeholder | Maps To | Example | +|------------|---------|---------| +| `{release}` | `.Release.Name` | `forgejo`, `audiobookshelf` | +| `{namespace}` | `.Release.Namespace` | `prod`, `default` | +| `{fullname}` | `common.fullname` helper | `audiobookshelf`, `forgejo` | +| `{subdomain}` | `.Values.subdomain` | `code`, `audiobookshelf` | +| `{domain}` | `.Values.globals.domain` | `olsen.cloud` | +| `{timezone}` | `.Values.globals.timezone` | `Europe/Amsterdam` | + +## Available Values + +### Release Object (`.Release.*`) +- `.Release.Name` - The release name (chart instance name) +- `.Release.Namespace` - The namespace the release will be installed into +- `.Release.Service` - The service that rendered the chart (usually "Helm") +- `.Release.Revision` - The revision number of this release + +### Chart Object (`.Chart.*`) +- `.Chart.Name` - The name of the chart +- `.Chart.Version` - The version of the chart +- `.Chart.AppVersion` - The app version of the chart + +### Values Object (`.Values.*`) +- `.Values.subdomain` - The subdomain for this application +- `.Values.globals.environment` - The environment (e.g., `prod`) +- `.Values.globals.domain` - The domain (e.g., `olsen.cloud`) +- `.Values.globals.timezone` - The timezone (e.g., `Europe/Amsterdam`) +- `.Values.globals.istio.gateways.public` - Public Istio gateway +- `.Values.globals.istio.gateways.private` - Private Istio gateway +- `.Values.globals.authentik.ref.name` - Authentik server name +- `.Values.globals.authentik.ref.namespace` - Authentik server namespace +- `.Values.globals.networking.private.ip` - Private network IP + +## Usage Examples + +### Simple String Replacement + +```yaml +env: + BASE_URL: + value: "https://{subdomain}.{domain}" + # Renders to: "https://audiobookshelf.olsen.cloud" +``` + +### Secret Reference with Release Name + +```yaml +env: + DATABASE_URL: + valueFrom: + secretKeyRef: + name: "{release}-database" + key: url + # Renders to: name: "audiobookshelf-database" +``` + +### Complex String with Multiple Placeholders + +```yaml +env: + SSH_DOMAIN: + value: "ssh-{subdomain}.{domain}" + # Renders to: "ssh-code.olsen.cloud" +``` + +## Extending Placeholders + +To add more placeholders, edit `apps/charts/common/templates/_helpers.tpl` in the `common.env` helper: + +### Current Implementation + +```go +value: {{ $value + | replace "{release}" $.Release.Name + | replace "{namespace}" $.Release.Namespace + | replace "{fullname}" (include "common.fullname" $) + | replace "{subdomain}" $.Values.subdomain + | replace "{domain}" $.Values.globals.domain + | replace "{timezone}" $.Values.globals.timezone + | quote }} +``` + +**Note:** `{fullname}` uses the `common.fullname` helper which: +- Returns `.Release.Name` if it contains the chart name +- Otherwise returns `{release}-{chart-name}` +- Respects `.Values.fullnameOverride` if set + +**Important:** Update both locations: +1. Line ~245: For `value:` entries (when `$value.value` exists) +2. Line ~248: For simple string values + +### Example Usage + +```yaml +env: + NAMESPACE: + value: "{namespace}" + # Renders to: "prod" (or whatever namespace the release is in) + + TIMEZONE: + value: "{timezone}" + # Renders to: "Europe/Amsterdam" + + APP_NAME: + value: "{fullname}" + # Renders to: "audiobookshelf" (or "release-chartname" if different) + + FULL_URL: + value: "https://{subdomain}.{domain}" + # Renders to: "https://audiobookshelf.olsen.cloud" + + SECRET_NAME: + valueFrom: + secretKeyRef: + name: "{fullname}-secrets" + key: apiKey + # Renders to: name: "audiobookshelf-secrets" +``` + +## Limitations + +1. **No nested placeholders**: Placeholders cannot reference other placeholders +2. **No conditional logic**: Placeholders are simple string replacements +3. **No functions**: Cannot use Helm template functions in values.yaml +4. **Order matters**: Replacements happen in order, so `{release}` is replaced before `{subdomain}` + +## Best Practices + +1. **Use placeholders for dynamic values**: Release names, domains, subdomains +2. **Keep it simple**: Use placeholders for common values, not complex logic +3. **Document custom placeholders**: If you add new ones, document them +4. **Test thoroughly**: Verify placeholders render correctly in your environment + +## Troubleshooting + +If a placeholder isn't being replaced: + +1. Check the placeholder name matches exactly (case-sensitive) +2. Verify the value exists in the context (`.Release.*` or `.Values.*`) +3. Check the replacement chain in `_helpers.tpl` +4. Use `helm template --debug` to see the rendered output diff --git a/apps/charts/common/common-1.0.0.tgz b/apps/charts/common/common-1.0.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..51039671ea5080e45b5d0dfe6b72a39e3c84988a GIT binary patch literal 19154 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 htE}J3&^FN9fkwe77zHB;00IC2|NpS|6>