releasaurus_core/config/
toml.rs1use derive_builder::Builder;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7
8use crate::{
9 config::{
10 changelog::ChangelogConfig, package::PackageConfig,
11 prerelease::PrereleaseConfig,
12 },
13 result::{ReleasaurusError, Result},
14};
15
16pub const DEFAULT_CONFIG_FILE: &str = "releasaurus.toml";
18pub const DEFAULT_COMMIT_SEARCH_DEPTH: usize = 400;
20pub const DEFAULT_TAG_SEARCH_DEPTH: usize = 100;
22
23#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Builder)]
24#[schemars(rename = "Releasaurus TOML Configuration Schema")]
25#[serde(default)]
26#[builder(setter(into, strip_option), default)]
27pub struct Config {
29 pub base_branch: Option<String>,
32 pub first_release_search_depth: usize,
35 pub tag_search_depth: usize,
38 pub separate_pull_requests: bool,
40 pub prerelease: PrereleaseConfig,
43 pub auto_start_next: Option<bool>,
46 pub breaking_always_increment_major: bool,
48 pub features_always_increment_minor: bool,
50 pub custom_major_increment_regex: Option<String>,
56 pub custom_minor_increment_regex: Option<String>,
61 pub changelog: ChangelogConfig,
63 #[serde(rename = "package")]
65 pub packages: Vec<PackageConfig>,
66}
67
68impl Default for Config {
69 fn default() -> Self {
70 Self {
71 base_branch: None,
72 first_release_search_depth: DEFAULT_COMMIT_SEARCH_DEPTH,
73 tag_search_depth: DEFAULT_TAG_SEARCH_DEPTH,
74 separate_pull_requests: false,
75 prerelease: PrereleaseConfig::default(),
76 auto_start_next: None,
77 breaking_always_increment_major: true,
78 features_always_increment_minor: true,
79 custom_major_increment_regex: None,
80 custom_minor_increment_regex: None,
81 changelog: ChangelogConfig::default(),
82 packages: vec![PackageConfig::default()],
83 }
84 }
85}
86
87impl Config {
88 pub fn base_branch(&self) -> Result<String> {
89 self.base_branch
90 .clone()
91 .ok_or_else(|| ReleasaurusError::BaseBranchNotConfigured)
92 }
93
94 pub fn auto_start_next(&self, package: &PackageConfig) -> bool {
95 package
96 .auto_start_next
97 .or(self.auto_start_next)
98 .unwrap_or_default()
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn loads_defaults() {
108 let config = Config::default();
109 assert!(!config.changelog.body.is_empty());
110 assert_eq!(
111 config.first_release_search_depth,
112 DEFAULT_COMMIT_SEARCH_DEPTH
113 );
114 }
115
116 #[test]
117 fn base_branch_returns_value_when_set() {
118 let config = Config {
119 base_branch: Some("main".into()),
120 ..Default::default()
121 };
122
123 assert_eq!(config.base_branch().unwrap(), "main");
124 }
125
126 #[test]
127 fn base_branch_returns_error_when_none() {
128 let config = Config {
129 base_branch: None,
130 ..Default::default()
131 };
132
133 assert!(config.base_branch().is_err());
134 }
135
136 #[test]
137 fn auto_start_next_uses_package_override() {
138 let config = Config {
139 auto_start_next: Some(false),
140 ..Default::default()
141 };
142 let package = PackageConfig {
143 auto_start_next: Some(true),
144 ..Default::default()
145 };
146
147 assert!(config.auto_start_next(&package));
148 }
149
150 #[test]
151 fn auto_start_next_uses_global_when_package_not_set() {
152 let config = Config {
153 auto_start_next: Some(true),
154 ..Default::default()
155 };
156 let package = PackageConfig::default();
157
158 assert!(config.auto_start_next(&package));
159 }
160
161 #[test]
162 fn auto_start_next_defaults_to_false() {
163 let config = Config::default();
164 let package = PackageConfig::default();
165
166 assert!(!config.auto_start_next(&package));
167 }
168}