diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d066b..6b17511 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Changed to use log statements - Updated fastly.toml for local development +### Fixed +- Rebuild when `TRUSTED_SERVER__*` env variables change + ## [1.0.6] - 2025-05-29 ### Changed diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 6f24dac..01eee86 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -26,6 +26,11 @@ sha2 = "0.10.9" tokio = { version = "1.46", features = ["sync", "macros", "io-util", "rt", "time"] } url = "2.4.1" +[build-dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0.91" +config = "0.15.11" + [dev-dependencies] regex = "1.1.1" temp-env = "0.3.6" diff --git a/crates/common/build.rs b/crates/common/build.rs new file mode 100644 index 0000000..f25ec0d --- /dev/null +++ b/crates/common/build.rs @@ -0,0 +1,52 @@ +#[path = "src/settings.rs"] +mod settings; + +use serde_json::Value; +use std::collections::HashSet; + +fn main() { + // Watch the settings.rs file for changes + println!("cargo:rerun-if-changed=../../trusted-server.toml"); + + // Create a default Settings instance and convert to JSON to discover all fields + let default_settings = settings::Settings::default(); + let settings_json = serde_json::to_value(&default_settings).unwrap(); + + let mut env_vars = HashSet::new(); + collect_env_vars(&settings_json, &mut env_vars, vec![]); + + // Print rerun-if-env-changed for each variable + let mut sorted_vars: Vec<_> = env_vars.into_iter().collect(); + sorted_vars.sort(); + + for var in sorted_vars { + println!("cargo:rerun-if-env-changed={}", var); + } +} + +fn collect_env_vars(value: &Value, env_vars: &mut HashSet, path: Vec) { + if let Value::Object(map) = value { + for (key, val) in map { + let mut new_path = path.clone(); + new_path.push(key.to_uppercase()); + + match val { + Value::String(_) | Value::Number(_) | Value::Bool(_) => { + // Leaf node - create environment variable + let env_var = format!( + "{}{}{}", + settings::ENVIRONMENT_VARIABLE_PREFIX, + settings::ENVIRONMENT_VARIABLE_SEPARATOR, + new_path.join(settings::ENVIRONMENT_VARIABLE_SEPARATOR) + ); + env_vars.insert(env_var); + } + Value::Object(_) => { + // Recurse into nested objects + collect_env_vars(val, env_vars, new_path); + } + _ => {} + } + } + } +} diff --git a/crates/common/src/settings.rs b/crates/common/src/settings.rs index 9bccb8b..8bf69ba 100644 --- a/crates/common/src/settings.rs +++ b/crates/common/src/settings.rs @@ -1,31 +1,30 @@ use std::str; use config::{Config, ConfigError, Environment, File, FileFormat}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize)] -#[allow(unused)] +pub const ENVIRONMENT_VARIABLE_PREFIX: &str = "TRUSTED_SERVER"; +pub const ENVIRONMENT_VARIABLE_SEPARATOR: &str = "__"; + +#[derive(Debug, Default, Deserialize, Serialize)] pub struct AdServer { pub ad_partner_url: String, pub sync_url: String, } -#[derive(Debug, Deserialize)] -#[allow(unused)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct Publisher { pub domain: String, pub cookie_domain: String, pub origin_url: String, } -#[derive(Debug, Deserialize)] -#[allow(unused)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct Prebid { pub server_url: String, } -#[derive(Debug, Deserialize)] -#[allow(unused)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct Synthetic { pub counter_store: String, pub opid_store: String, @@ -33,8 +32,7 @@ pub struct Synthetic { pub template: String, } -#[derive(Debug, Deserialize)] -#[allow(unused)] +#[derive(Debug, Default, Deserialize, Serialize)] pub struct Settings { pub ad_server: AdServer, pub publisher: Publisher, @@ -42,6 +40,7 @@ pub struct Settings { pub synthetic: Synthetic, } +#[allow(unused)] impl Settings { pub fn new() -> Result { let toml_bytes = include_bytes!("../../../trusted-server.toml"); @@ -52,8 +51,8 @@ impl Settings { pub fn from_toml(toml_str: &str) -> Result { let environment = Environment::default() - .prefix("TRUSTED_SERVER") - .separator("__"); + .prefix(ENVIRONMENT_VARIABLE_PREFIX) + .separator(ENVIRONMENT_VARIABLE_SEPARATOR); let toml = File::from_str(toml_str, FileFormat::Toml); let config = Config::builder() @@ -181,7 +180,12 @@ mod tests { let toml_str = re.replace(&toml_str, ""); temp_env::with_var( - "TRUSTED_SERVER__AD_SERVER__AD_PARTNER_URL", + format!( + "{}{}AD_SERVER{}AD_PARTNER_URL", + ENVIRONMENT_VARIABLE_PREFIX, + ENVIRONMENT_VARIABLE_SEPARATOR, + ENVIRONMENT_VARIABLE_SEPARATOR + ), Some("https://change-ad.com/serve"), || { let settings = Settings::from_toml(&toml_str); @@ -200,7 +204,12 @@ mod tests { let toml_str = crate_test_settings_str(); temp_env::with_var( - "TRUSTED_SERVER__AD_SERVER__AD_PARTNER_URL", + format!( + "{}{}AD_SERVER{}AD_PARTNER_URL", + ENVIRONMENT_VARIABLE_PREFIX, + ENVIRONMENT_VARIABLE_SEPARATOR, + ENVIRONMENT_VARIABLE_SEPARATOR + ), Some("https://change-ad.com/serve"), || { let settings = Settings::from_toml(&toml_str);