Files
steep/crates/herald-server/src/env.rs
T
qpismont 99d1c2feef
ci/woodpecker/push/tests Pipeline was canceled
Add sandbox
2026-09-17 13:16:15 +00:00

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"));
}
}