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:
Step 4: Regenerate Templates¶
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:
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¶
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
featureFlagssection 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¶
Values:
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:
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:
Web TypeScript Not Generated¶
Cause: Missing web object on env var.
Fix: Add the web configuration:
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¶
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.
Related Documentation¶
- Env-Mapping Code Generation - Architecture reference
- Managing Feature Flags - Simplified feature flag workflow
- Environment Variables Reference - Complete env var listing