summaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2026-02-15 21:27:00 +0100
committerDawid Rycerz <dawid@rycerz.xyz>2026-02-15 21:27:00 +0100
commitce0dbf6b249956700c6a1705bf4ad85a09d53e8c (patch)
treed7c3236807cfbf75d7f3a355eb5df5a5e2cc4ad7 /src/config.rs
parent064a1d01c5c14f5ecc032fa9b8346a4a88b893f6 (diff)
feat: witryna 0.2.0HEADv0.2.0main
Switch, cleanup, and status CLI commands. Persistent build state via state.json. Post-deploy hooks on success and failure with WITRYNA_BUILD_STATUS. Dependency diet (axum→tiny_http, clap→argh, tracing→log). Drop built-in rate limiting. Nix flake with NixOS module. Arch Linux PKGBUILD. Centralized version management. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs73
1 files changed, 17 insertions, 56 deletions
diff --git a/src/config.rs b/src/config.rs
index 63f3447..d79e91c 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,20 +1,16 @@
use crate::repo_config;
use anyhow::{Context as _, Result, bail};
+use log::LevelFilter;
use serde::{Deserialize, Deserializer};
use std::collections::{HashMap, HashSet};
use std::net::SocketAddr;
use std::path::{Component, PathBuf};
use std::time::Duration;
-use tracing::level_filters::LevelFilter;
fn default_log_dir() -> PathBuf {
PathBuf::from("/var/log/witryna")
}
-const fn default_rate_limit() -> u32 {
- 10
-}
-
const fn default_max_builds_to_keep() -> u32 {
5
}
@@ -50,8 +46,6 @@ pub struct Config {
#[serde(default = "default_log_dir")]
pub log_dir: PathBuf,
pub log_level: String,
- #[serde(default = "default_rate_limit")]
- pub rate_limit_per_minute: u32,
#[serde(default = "default_max_builds_to_keep")]
pub max_builds_to_keep: u32,
/// Optional global git operation timeout (e.g., "2m", "5m").
@@ -109,7 +103,7 @@ pub struct SiteConfig {
#[serde(default)]
pub cache_dirs: Option<Vec<String>>,
/// Optional post-deploy hook command (array form, no shell).
- /// Runs after successful symlink switch. Non-fatal on failure.
+ /// Runs after every build (success or failure). Non-fatal on failure.
#[serde(default)]
pub post_deploy: Option<Vec<String>>,
/// Optional environment variables passed to container builds and post-deploy hooks.
@@ -265,17 +259,14 @@ impl Config {
)
})?;
} else if let Some(path) = &site.webhook_token_file {
- site.webhook_token = tokio::fs::read_to_string(path)
- .await
- .with_context(|| {
- format!(
- "site '{}': failed to read webhook_token_file '{}'",
- site.name,
- path.display()
- )
- })?
- .trim()
- .to_owned();
+ let token_content = tokio::fs::read_to_string(path).await.with_context(|| {
+ format!(
+ "site '{}': failed to read webhook_token_file '{}'",
+ site.name,
+ path.display()
+ )
+ })?;
+ token_content.trim().clone_into(&mut site.webhook_token);
}
}
Ok(())
@@ -284,7 +275,6 @@ impl Config {
fn validate(&self) -> Result<()> {
self.validate_listen_address()?;
self.validate_log_level()?;
- self.validate_rate_limit()?;
self.validate_git_timeout()?;
self.validate_container_runtime()?;
self.validate_sites()?;
@@ -295,13 +285,12 @@ impl Config {
if let Some(timeout) = self.git_timeout {
if timeout < MIN_GIT_TIMEOUT {
bail!(
- "git_timeout is too short ({:?}): minimum is {}s",
- timeout,
+ "git_timeout is too short ({timeout:?}): minimum is {}s",
MIN_GIT_TIMEOUT.as_secs()
);
}
if timeout > MAX_GIT_TIMEOUT {
- bail!("git_timeout is too long ({:?}): maximum is 1h", timeout,);
+ bail!("git_timeout is too long ({timeout:?}): maximum is 1h");
}
}
Ok(())
@@ -333,13 +322,6 @@ impl Config {
Ok(())
}
- fn validate_rate_limit(&self) -> Result<()> {
- if self.rate_limit_per_minute == 0 {
- bail!("rate_limit_per_minute must be greater than 0");
- }
- Ok(())
- }
-
fn validate_sites(&self) -> Result<()> {
let mut seen_names = HashSet::new();
@@ -369,12 +351,12 @@ impl Config {
#[must_use]
pub fn log_level_filter(&self) -> LevelFilter {
match self.log_level.to_lowercase().as_str() {
- "trace" => LevelFilter::TRACE,
- "debug" => LevelFilter::DEBUG,
- "warn" => LevelFilter::WARN,
- "error" => LevelFilter::ERROR,
+ "trace" => LevelFilter::Trace,
+ "debug" => LevelFilter::Debug,
+ "warn" => LevelFilter::Warn,
+ "error" => LevelFilter::Error,
// Catch-all: covers "info" and the unreachable default after validation.
- _ => LevelFilter::INFO,
+ _ => LevelFilter::Info,
}
}
@@ -921,27 +903,6 @@ sites = []
}
#[test]
- fn zero_rate_limit_rejected() {
- let toml = r#"
-listen_address = "127.0.0.1:8080"
-container_runtime = "podman"
-base_dir = "/var/lib/witryna"
-log_level = "info"
-rate_limit_per_minute = 0
-sites = []
-"#;
- let config: Config = toml::from_str(toml).unwrap();
- let result = config.validate();
- assert!(result.is_err());
- assert!(
- result
- .unwrap_err()
- .to_string()
- .contains("rate_limit_per_minute")
- );
- }
-
- #[test]
fn duplicate_site_names() {
let toml = r#"
listen_address = "127.0.0.1:8080"