6.6 KiB
Schema Configuration Fix for E2E Services
Date: 2025-01-30
Status: ✅ Complete
Branch: main
Summary
Fixed an issue where the start-e2e-services.sh script was ignoring the database schema configuration from custom config files and always defaulting to the attune schema.
Problem
When launching services with a custom config file:
CONFIG_FILE=config.development.yaml ./scripts/start-e2e-services.sh
The services would ignore the schema: "public" setting in config.development.yaml and always use the attune schema instead.
Root Cause
The configuration loading system has the following priority order:
- Base config file (e.g.,
config.yamlfromATTUNE_CONFIG) - Environment-specific config file (e.g.,
config.{environment}.yaml) - Environment variables (highest priority)
The start-e2e-services.sh script was setting ATTUNE__ENVIRONMENT=e2e, which caused the config loader to look for and load config.e2e.yaml after loading the custom config file. Since environment-specific files have higher priority, any settings in config.e2e.yaml (including the default schema: "attune") would override the custom config.
Code Flow
// In crates/common/src/config.rs::Config::load()
// 1. Load base config (from ATTUNE_CONFIG)
builder = builder.add_source(config_crate::File::with_name(&config_path));
// 2. Load environment-specific config (PROBLEM: this overrides step 1)
let environment = std::env::var("ATTUNE__ENVIRONMENT").unwrap_or_else(...);
let env_config_path = format!("config.{}.yaml", environment);
builder = builder.add_source(config_crate::File::with_name(&env_config_path));
// 3. Load environment variables (highest priority)
builder = builder.add_source(config_crate::Environment::with_prefix("ATTUNE")...);
When ATTUNE__ENVIRONMENT=e2e was set, it loaded config.e2e.yaml which contained schema: "attune", overriding the schema: "public" from config.development.yaml.
Solution
Modified scripts/start-e2e-services.sh to only set ATTUNE__ENVIRONMENT=e2e when using the default E2E config file, allowing custom config files to determine their own environment:
# Only set ATTUNE__ENVIRONMENT if using default e2e config
# Otherwise, let the config file determine the environment
if [ "$CONFIG_FILE" = "config.e2e.yaml" ]; then
ATTUNE__ENVIRONMENT=e2e ATTUNE_CONFIG="$CONFIG_FILE" ./target/debug/$binary_name > "$log_file" 2>&1 &
else
ATTUNE_CONFIG="$CONFIG_FILE" ./target/debug/$binary_name > "$log_file" 2>&1 &
fi
Changes Made
Modified Files
scripts/start-e2e-services.sh:
- Added schema detection from config file to display in startup banner
- Modified service startup to conditionally set
ATTUNE__ENVIRONMENTonly for default E2E config - Added configuration info display showing config file and detected schema
Enhanced User Experience
Added informative banner showing configuration being used:
Configuration:
• Config file: config.development.yaml
• Database schema: public
This helps users verify the correct configuration is loaded before services start.
Verification
Before Fix
$ CONFIG_FILE=config.development.yaml ./scripts/start-e2e-services.sh
# Services would show:
INFO Using production schema: attune
After Fix
$ CONFIG_FILE=config.development.yaml ./scripts/start-e2e-services.sh
Configuration:
• Config file: config.development.yaml
• Database schema: public
# Services now show:
INFO Connecting to database with max_connections=50, schema=public
All services (api, executor, worker, sensor) correctly use the public schema.
Usage
Default E2E Environment
# Uses config.e2e.yaml with attune schema (default)
./scripts/start-e2e-services.sh
Development Environment
# Uses config.development.yaml with public schema
CONFIG_FILE=config.development.yaml ./scripts/start-e2e-services.sh
Custom Configuration
# Uses any custom config file with its specified schema
CONFIG_FILE=my-custom-config.yaml ./scripts/start-e2e-services.sh
Related Files
scripts/start-e2e-services.sh- Service startup script (modified)crates/common/src/config.rs- Configuration loading logic (reference)crates/common/src/db.rs- Database connection with schema support (reference)config.development.yaml- Development config withschema: "public"config.e2e.yaml- E2E test config with defaultschema: "attune"
Configuration Priority Reference
For future reference, Attune's configuration loading priority is:
-
Base config file (lowest priority)
config.yamlor file specified byATTUNE_CONFIGenv var
-
Environment-specific config file
config.{ATTUNE__ENVIRONMENT}.yaml- Only loaded if
ATTUNE__ENVIRONMENTis set or determined from base config
-
Environment variables (highest priority)
- Prefix:
ATTUNE__ - Separator:
__(double underscore) - Example:
ATTUNE__DATABASE__SCHEMA=public
- Prefix:
Schema Configuration
The database schema can be configured via:
- Config file:
database.schema: "public" - Environment variable:
ATTUNE__DATABASE__SCHEMA=public - Default if not specified:
"attune"
Lessons Learned
- Environment variable overrides can be subtle: Setting
ATTUNE__ENVIRONMENThas cascading effects by triggering additional config file loads - Configuration priority matters: Higher priority sources always override lower priority ones
- Scripts should respect user intent: When users provide custom config, don't override their choices
- Visibility helps debugging: Showing the detected configuration at startup makes issues immediately visible
Testing
Tested with:
- ✅ Default E2E config (uses
attuneschema) - ✅ Development config (uses
publicschema) - ✅ All services (api, executor, worker, sensor) respect the config
- ✅ Schema detection and display in startup banner
Impact
Positive:
- Users can now easily switch between development and E2E environments
- Schema isolation works correctly for parallel testing
- Configuration behavior is more intuitive and predictable
No Breaking Changes:
- Default behavior unchanged (E2E config still uses
attuneschema) - Existing scripts and workflows continue to work
- Only affects behavior when custom
CONFIG_FILEis provided
Future Improvements
Consider adding:
- Validation warning if config file doesn't exist
- Display full resolved configuration on startup (with sensitive values masked)
- Config validation command:
attune config validate --file config.yaml - Environment variable to completely disable environment-specific config loading