98 lines
3.1 KiB
Rust
98 lines
3.1 KiB
Rust
use anyhow::anyhow;
|
|
|
|
#[derive(Clone)]
|
|
pub struct EnvConfig {
|
|
pub http_port: u16,
|
|
pub webhook_secret: String,
|
|
pub open_router_api_key: String,
|
|
pub open_router_model: String,
|
|
pub open_router_timeout: u64,
|
|
pub bot_max_concurrent: usize,
|
|
pub gitea_url: String,
|
|
pub gitea_token: String,
|
|
pub gitea_timeout: u64,
|
|
pub metrics_bind_addr: Option<String>,
|
|
pub container_runtime: String,
|
|
pub sandbox_enabled: bool,
|
|
pub sandbox_max_iterations: usize,
|
|
}
|
|
|
|
pub fn load_config() -> anyhow::Result<EnvConfig> {
|
|
let http_port = try_get_env("HTTP_PORT")?.parse()?;
|
|
let webhook_secret = try_get_env("WEBHOOK_SIG_HEADER_SECRET")?;
|
|
let open_router_api_key = try_get_env("OPEN_ROUTER_API_KEY")?;
|
|
let open_router_model = try_get_env("OPEN_ROUTER_MODEL")?;
|
|
let open_router_timeout = try_get_env("OPEN_ROUTER_TIMEOUT")?.parse()?;
|
|
let bot_max_concurrent = try_get_env("BOT_MAX_CONCURRENT")?.parse()?;
|
|
let gitea_url = try_get_env("GITEA_URL")?;
|
|
let gitea_token = try_get_env("GITEA_TOKEN")?;
|
|
let gitea_timeout = try_get_env("GITEA_TIMEOUT")?.parse()?;
|
|
let metrics_bind_addr = std::env::var("METRICS_BIND_ADDR").ok();
|
|
let container_runtime =
|
|
std::env::var("CONTAINER_RUNTIME").unwrap_or_else(|_| "docker".to_string());
|
|
let sandbox_enabled = std::env::var("SANDBOX_ENABLED")
|
|
.map(|value| matches!(value.as_str(), "1" | "true" | "yes"))
|
|
.unwrap_or(false);
|
|
let sandbox_max_iterations = std::env::var("SANDBOX_MAX_ITERATIONS")
|
|
.ok()
|
|
.and_then(|value| value.parse().ok())
|
|
.unwrap_or(8);
|
|
|
|
Ok(EnvConfig {
|
|
http_port,
|
|
webhook_secret,
|
|
open_router_api_key,
|
|
open_router_model,
|
|
open_router_timeout,
|
|
bot_max_concurrent,
|
|
gitea_url,
|
|
gitea_token,
|
|
gitea_timeout,
|
|
metrics_bind_addr,
|
|
container_runtime,
|
|
sandbox_enabled,
|
|
sandbox_max_iterations,
|
|
})
|
|
}
|
|
|
|
pub fn try_get_env(key: &str) -> anyhow::Result<String> {
|
|
let env_value = std::env::var(key).map_err(|e| anyhow::anyhow!("{}: {}", key, e))?;
|
|
|
|
if env_value.trim().is_empty() {
|
|
return Err(anyhow!(format!("env var {} is empty", key)));
|
|
}
|
|
|
|
Ok(env_value)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_try_get_env_returns_value() {
|
|
unsafe { std::env::set_var("TEST_ENV_PRESENT", "hello") };
|
|
assert_eq!(try_get_env("TEST_ENV_PRESENT").unwrap(), "hello");
|
|
}
|
|
|
|
#[test]
|
|
fn test_try_get_env_missing_var_returns_error() {
|
|
unsafe { std::env::remove_var("TEST_ENV_MISSING") };
|
|
assert!(try_get_env("TEST_ENV_MISSING").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_try_get_env_empty_value_returns_error() {
|
|
unsafe { std::env::set_var("TEST_ENV_EMPTY", "") };
|
|
let err = try_get_env("TEST_ENV_EMPTY").unwrap_err();
|
|
assert!(err.to_string().contains("TEST_ENV_EMPTY"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_try_get_env_whitespace_only_returns_error() {
|
|
unsafe { std::env::set_var("TEST_ENV_WHITESPACE", " ") };
|
|
let err = try_get_env("TEST_ENV_WHITESPACE").unwrap_err();
|
|
assert!(err.to_string().contains("TEST_ENV_WHITESPACE"));
|
|
}
|
|
}
|