Skip to content

How-To: Extend the Env-Mapping Schema

This guide explains how to add new environment variables to the SyRF configuration system using the env-mapping.yaml schema.

For feature flags specifically, see Managing Feature Flags instead.

Prerequisites

  • Node.js 18+ installed
  • Access to src/charts/syrf-common/ directory
  • Understanding of Helm values.yaml structure

Quick Reference

Task Section to Read Generator
Add env var to .NET service Adding to Existing Section syrf-common
Create new configuration section Creating a New Section syrf-common
Add web/frontend env var Adding Web Configuration syrf-common + web
Add feature flag Managing Feature Flags web
Add secret reference Working with Secrets syrf-common

Adding to an Existing Section

Step 1: Find the Right Section

Open src/charts/syrf-common/env-mapping.yaml and locate the appropriate section:

# Example: Adding a new MongoDB setting
mongodb:
  services: [api, project-management, quartz]
  displayName: "MongoDB"
  envVars:
    # ... existing vars

Step 2: Add the Environment Variable

Add your new variable following the schema:

mongodb:
  services: [api, project-management, quartz]
  displayName: "MongoDB"
  envVars:
    # ... existing vars

    # NEW: Add connection timeout
    - name: SYRF__ConnectionStrings__MongoConnection__Timeout
      valuePath: mongoDb.connectionTimeout
      default: "30"

Step 3: Update Service Values Files

Add the corresponding value to each service's values.yaml:

# src/services/api/.chart/values.yaml
mongoDb:
  # ... existing values
  connectionTimeout: 30  # NEW

Step 4: Regenerate Templates

cd src/charts/syrf-common
pnpm run generate:env-blocks

Step 5: Validate

cd src/services/api/.chart
rm -rf charts && helm dependency update
helm template test . | grep -A2 "SYRF__ConnectionStrings__MongoConnection__Timeout"

Expected output:

- name: SYRF__ConnectionStrings__MongoConnection__Timeout
  value: "30"

Creating a New Section

Step 1: Define the Section

Add a new section to env-mapping.yaml:

# =============================================================================
# New Feature Service
# =============================================================================
newFeatureService:
  services: [api, project-management]  # Which .NET services need this
  displayName: "New Feature Service"
  condition: newFeatureService         # Makes it optional
  envVars:
    - name: SYRF__NewFeatureService__Endpoint
      valuePath: newFeatureService.endpoint
      default: ""

    - name: SYRF__NewFeatureService__ApiKey
      secretNamePath: newFeatureService.secretName
      secretKey: apiKey

    - name: SYRF__NewFeatureService__Timeout
      valuePath: newFeatureService.timeout
      default: "30"

Step 2: Add Values to Services

# src/services/api/.chart/values.yaml
newFeatureService:
  endpoint: "https://api.newfeature.com"
  secretName: new-feature-api
  timeout: 30

Step 3: Regenerate and Validate

cd src/charts/syrf-common
pnpm run generate:env-blocks

# Verify section is included
grep -A10 "syrf-common.env.newFeatureService" templates/_env-blocks.tpl

Adding Web Configuration

Web env vars require the web object for TypeScript generation. This requires running both generators.

Step 1: Add to env-mapping.yaml

webConfig:
  services: []  # Empty = web only, no .NET services
  displayName: "Web Configuration"
  envVars:
    - name: SYRF__NewWebSetting
      valuePath: newWebSetting
      default: "default-value"
      web:
        tsName: newWebSetting       # TypeScript property name
        tsType: string              # string | boolean | number | string[]
      description: "Description for JSDoc comment"

Step 2: Add to Web Values

# src/services/web/.chart/values.yaml
newWebSetting: "production-value"

Step 3: Regenerate (Both Generators)

# Generate Helm templates (for deployment.yaml env vars)
cd src/charts/syrf-common
pnpm run generate:env-blocks

# Generate TypeScript + JSON config (for Angular app)
cd src/services/web
pnpm run generate:flags

Step 4: Verify Generated Files

Check the generated files:

# Helm templates include the new env var
grep "newWebSetting" src/charts/syrf-common/templates/_env-blocks.tpl

# TypeScript interfaces
grep "newWebSetting" src/services/web/src/app/generated/feature-flags.types.ts

# env.template.json (envsubst placeholders)
grep "newWebSetting" src/services/web/src/assets/data/env.template.json

Step 5: Use in Angular Code

import { AppConfigService } from '@app/core/services/config/app-config.service';

// In your component
constructor(private configService: AppConfigService) {
  console.log(this.configService.config.newWebSetting);
}

Adding Feature Flags

For detailed instructions on adding feature flags, see Managing Feature Flags.

Feature flags use only the web generator and are simpler than general env vars:

# 1. Edit env-mapping.yaml (featureFlags section)
# 2. Run only the web generator:
cd src/services/web
pnpm run generate:flags

# 3. The generator automatically updates:
#    - TypeScript files in src/app/generated/
#    - env.template.json
#    - .chart/values.yaml

Key difference from general env vars:

  • Feature flags are boolean only
  • Uses dedicated featureFlags section in schema
  • Generated NgRx selectors for type-safe access in components
  • Admin-only flags automatically combine with admin UI state

Working with Secrets

Simple Secret Reference

- name: SYRF__Service__ApiKey
  secretNamePath: service.secretName
  secretKey: apiKey

Values:

service:
  secretName: my-service-secret  # References K8s secret "my-service-secret"

Generated:

- name: SYRF__Service__ApiKey
  valueFrom:
    secretKeyRef:
      name: {{ .Values.service.secretName }}
      key: apiKey

Dynamic Secret Key

Use the chart name as the secret key (common for multi-service secrets):

- name: SYRF__Sentry__Dsn
  secretNamePath: sentry.authSecretName
  secretKeySource:
    source: helm
    path: .Chart.Name

Generated:

- name: SYRF__Sentry__Dsn
  valueFrom:
    secretKeyRef:
      name: {{ .Values.sentry.authSecretName }}
      key: {{ .Chart.Name }}  # e.g., "api", "project-management"

Working with ConfigMaps

For values that can come from either ConfigMap or direct values:

- name: SYRF__Database__Host
  valuePath: database.host
  configMapNamePath: database.configMapName
  configMapKey: host
  default: "localhost"

Values:

database:
  host: "direct-value"           # Used if configMapName not set
  configMapName: database-config  # Optional: read from ConfigMap instead

Transform Patterns

Apply transformations to values:

# URL pattern
- name: ASPNETCORE_URLS
  valuePath: service.port
  default: "8080"
  transform: "http://+:{0}"
# Result: http://+:8080

# Connection string pattern
- name: CONNECTION_STRING
  valuePath: database.host
  transform: "Server={0};Database=mydb"
# Result: Server=myhost;Database=mydb

Making Sections Optional

Use condition to make a section optional:

optionalService:
  services: [api, project-management]
  condition: optionalService  # Only render if .Values.optionalService exists
  envVars:
    - name: SYRF__OptionalService__Setting
      valuePath: optionalService.setting

For nested conditions:

nestedConfig:
  condition: parent.child  # Safely checks .Values.parent AND .Values.parent.child

Targeting Specific Services

Section-Level Targeting

# Only API and PM get this section
apiPmOnly:
  services: [api, project-management]
  envVars:
    - name: SYRF__Setting
      valuePath: setting

Variable-Level Additions

Use dotnet to add specific vars to additional services:

sharedSection:
  services: [api, project-management]  # Base services
  envVars:
    - name: SYRF__Common__Setting
      valuePath: common.setting

    - name: SYRF__Extra__Setting
      valuePath: extra.setting
      dotnet: [quartz]  # Also include in quartz (additive)

Troubleshooting

"nil pointer evaluating interface {}"

Cause: Accessing a nested path when parent is nil.

Fix: Add a condition to the section:

mySection:
  condition: parentObject  # Add this
  envVars:
    - name: SYRF__Setting
      valuePath: parentObject.setting  # Now safe

Template Not Rendering

Cause: Section not included in service composition.

Check: Verify services array includes your target service:

mySection:
  services: [api, project-management, quartz]  # Must include target

Web TypeScript Not Generated

Cause: Missing web object on env var.

Fix: Add the web configuration:

- name: SYRF__Setting
  valuePath: setting
  web:                    # Add this
    tsName: setting
    tsType: string

Complete Workflow Example

Adding a new "Analytics Service" integration (env vars for .NET services + feature flag for web):

1. Add Section to env-mapping.yaml

# =============================================================================
# Analytics Service
# =============================================================================
analytics:
  services: [api, project-management]
  displayName: "Analytics Service"
  condition: analytics
  envVars:
    - name: SYRF__Analytics__Endpoint
      valuePath: analytics.endpoint
      default: ""

    - name: SYRF__Analytics__ApiKey
      secretNamePath: analytics.secretName
      secretKey: apiKey

    - name: SYRF__Analytics__Enabled
      valuePath: analytics.enabled
      default: "false"
      web:
        tsName: analyticsEnabled
        tsType: boolean
      featureFlag: true
      category: monitoring
      description: "Enable analytics tracking"

2. Update Values Files

# src/services/api/.chart/values.yaml
analytics:
  endpoint: "https://analytics.example.com"
  secretName: analytics-secret
  enabled: false

# src/services/web/.chart/values.yaml
# (No need to edit - web generator updates this automatically)

3. Run Both Generators

# Generate Helm templates
cd src/charts/syrf-common
pnpm run generate:env-blocks

# Generate TypeScript + update web values.yaml
cd ../../services/web
pnpm run generate:flags

4. Validate

# Validate generated code matches schema
cd src/charts/syrf-common && pnpm run validate:env-blocks
cd src/services/web && pnpm run validate:flags

# Test Helm templates
for service in api project-management quartz web; do
  echo "=== $service ==="
  cd src/services/$service/.chart
  rm -rf charts && helm dependency update
  helm template test . >/dev/null && echo "OK" || echo "FAILED"
  cd -
done

5. Build and Test

# Ensure TypeScript compiles
cd src/services/web
pnpm run build

6. Commit

git add src/charts/syrf-common/ src/services/
git commit -m "feat(config): add analytics service integration"

Validation

Pre-commit hooks automatically validate generated code when schema or generated files change:

# Manual validation (same as pre-commit)
cd src/charts/syrf-common && pnpm run validate:env-blocks
cd src/services/web && pnpm run validate:flags

CI also validates in the validate-generated-code job for PRs.