use derive_builder::Builder;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
config::package::PackageConfig,
error::{ReleasaurusError, Result},
forge::config::DEFAULT_COMMIT_SEARCH_DEPTH,
};
pub mod changelog;
pub mod package;
pub mod prerelease;
pub mod release_type;
use self::prerelease::PrereleaseConfig;
pub const DEFAULT_CONFIG_FILE: &str = "releasaurus.toml";
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Builder)]
#[schemars(rename = "Releasaurus TOML Configuration Schema")]
#[serde(default)]
#[builder(setter(into, strip_option), default)]
pub struct Config {
pub base_branch: Option<String>,
pub first_release_search_depth: u64,
pub separate_pull_requests: bool,
pub prerelease: PrereleaseConfig,
pub auto_start_next: Option<bool>,
pub breaking_always_increment_major: bool,
pub features_always_increment_minor: bool,
pub custom_major_increment_regex: Option<String>,
pub custom_minor_increment_regex: Option<String>,
pub changelog: changelog::ChangelogConfig,
#[serde(rename = "package")]
pub packages: Vec<PackageConfig>,
}
impl Default for Config {
fn default() -> Self {
Self {
base_branch: None,
first_release_search_depth: DEFAULT_COMMIT_SEARCH_DEPTH,
separate_pull_requests: false,
prerelease: PrereleaseConfig::default(),
auto_start_next: None,
breaking_always_increment_major: true,
features_always_increment_minor: true,
custom_major_increment_regex: None,
custom_minor_increment_regex: None,
changelog: changelog::ChangelogConfig::default(),
packages: vec![package::PackageConfig::default()],
}
}
}
impl Config {
pub fn base_branch(&self) -> Result<String> {
self.base_branch
.clone()
.ok_or_else(|| ReleasaurusError::BaseBranchNotConfigured)
}
pub fn auto_start_next(&self, package: &PackageConfig) -> bool {
package
.auto_start_next
.or(self.auto_start_next)
.unwrap_or_default()
}
}
#[cfg(test)]
mod tests {
use crate::forge::config::DEFAULT_COMMIT_SEARCH_DEPTH;
use super::*;
#[test]
fn loads_defaults() {
let config = Config::default();
assert!(!config.changelog.body.is_empty());
assert_eq!(
config.first_release_search_depth,
DEFAULT_COMMIT_SEARCH_DEPTH
);
}
#[test]
fn base_branch_returns_value_when_set() {
let config = Config {
base_branch: Some("main".into()),
..Default::default()
};
assert_eq!(config.base_branch().unwrap(), "main");
}
#[test]
fn base_branch_returns_error_when_none() {
let config = Config {
base_branch: None,
..Default::default()
};
assert!(config.base_branch().is_err());
}
#[test]
fn auto_start_next_uses_package_override() {
let config = Config {
auto_start_next: Some(false),
..Default::default()
};
let package = PackageConfig {
auto_start_next: Some(true),
..Default::default()
};
assert!(config.auto_start_next(&package));
}
#[test]
fn auto_start_next_uses_global_when_package_not_set() {
let config = Config {
auto_start_next: Some(true),
..Default::default()
};
let package = PackageConfig::default();
assert!(config.auto_start_next(&package));
}
#[test]
fn auto_start_next_defaults_to_false() {
let config = Config::default();
let package = PackageConfig::default();
assert!(!config.auto_start_next(&package));
}
}