Skip to main content

gitversion_rs/config/
defaults.rs

1//! Built-in default configuration per workflow.
2//!
3//! Ports the values from the original
4//! `GitVersion.Configuration/Builders/{GitFlow,GitHubFlow,TrunkBased}ConfigurationBuilder.cs`.
5
6use super::model::*;
7use std::collections::BTreeMap;
8
9const MAIN_REGEX: &str = "^master$|^main$";
10const DEVELOP_REGEX: &str = "^dev(elop)?(ment)?$";
11const RELEASE_REGEX: &str = r"^releases?[\/-](?<BranchName>.+)";
12const FEATURE_REGEX: &str = r"^features?[\/-](?<BranchName>.+)";
13const PR_REGEX: &str = r"^(pull-requests|pull|pr)[\/-](?<Number>\d*)";
14const HOTFIX_REGEX: &str = r"^hotfix(es)?[\/-](?<BranchName>.+)";
15const SUPPORT_REGEX: &str = r"^support[\/-](?<BranchName>.+)";
16const UNKNOWN_REGEX: &str = "(?<BranchName>.+)";
17
18const MAJOR_BUMP: &str = r"\+semver:\s?(breaking|major)";
19const MINOR_BUMP: &str = r"\+semver:\s?(feature|minor)";
20const PATCH_BUMP: &str = r"\+semver:\s?(fix|patch)";
21const NO_BUMP: &str = r"\+semver:\s?(none|skip)";
22
23fn prevent(
24    of_merged: Option<bool>,
25    when_merged: Option<bool>,
26    when_tagged: Option<bool>,
27) -> PreventIncrement {
28    PreventIncrement {
29        of_merged_branch: of_merged,
30        when_branch_merged: when_merged,
31        when_current_commit_tagged: when_tagged,
32    }
33}
34
35/// Root configuration with global default fields populated (no branch entries).
36fn global_base(mode: DeploymentMode, strategies: Vec<VersionStrategy>) -> GitVersionConfiguration {
37    GitVersionConfiguration {
38        assembly_versioning_scheme: Some(VersioningScheme::MajorMinorPatch),
39        assembly_file_versioning_scheme: Some(VersioningScheme::MajorMinorPatch),
40        assembly_informational_format: Some("{InformationalVersion}".into()),
41        tag_prefix: Some("[vV]?".into()),
42        version_in_branch_pattern: Some(r"(?<version>[vV]?\d+(\.\d+)?(\.\d+)?).*".into()),
43        major_version_bump_message: Some(MAJOR_BUMP.into()),
44        minor_version_bump_message: Some(MINOR_BUMP.into()),
45        patch_version_bump_message: Some(PATCH_BUMP.into()),
46        no_bump_message: Some(NO_BUMP.into()),
47        tag_pre_release_weight: Some(60000),
48        commit_date_format: Some("yyyy-MM-dd".into()),
49        semantic_version_format: Some(SemanticVersionFormat::Strict),
50        update_build_number: Some(true),
51        strategies,
52        increment: Some(IncrementStrategy::Inherit),
53        mode: Some(mode),
54        label: Some("{BranchName}".into()),
55        regex: Some(String::new()),
56        commit_message_incrementing: Some(CommitMessageIncrementMode::Enabled),
57        prevent_increment: Some(prevent(Some(false), Some(false), Some(true))),
58        track_merge_target: Some(false),
59        track_merge_message: Some(true),
60        tracks_release_branches: Some(false),
61        is_release_branch: Some(false),
62        is_main_branch: Some(false),
63        ..Default::default()
64    }
65}
66
67fn branch(regex: &str) -> BranchConfiguration {
68    BranchConfiguration {
69        regex: Some(regex.into()),
70        ..Default::default()
71    }
72}
73
74/// Default version strategies shared by GitFlow and GitHubFlow.
75fn default_strategies() -> Vec<VersionStrategy> {
76    vec![
77        VersionStrategy::Fallback,
78        VersionStrategy::ConfiguredNextVersion,
79        VersionStrategy::MergeMessage,
80        VersionStrategy::TaggedCommit,
81        VersionStrategy::TrackReleaseBranches,
82        VersionStrategy::VersionInBranchName,
83    ]
84}
85
86/// GitFlow workflow (the default).
87pub fn gitflow() -> GitVersionConfiguration {
88    let mut c = global_base(DeploymentMode::ContinuousDelivery, default_strategies());
89    let mut b: BTreeMap<String, BranchConfiguration> = BTreeMap::new();
90
91    b.insert(
92        "develop".into(),
93        BranchConfiguration {
94            increment: Some(IncrementStrategy::Minor),
95            mode: Some(DeploymentMode::ContinuousDelivery),
96            label: Some("alpha".into()),
97            source_branches: vec!["main".into()],
98            prevent_increment: Some(prevent(None, None, Some(false))),
99            track_merge_target: Some(true),
100            track_merge_message: Some(true),
101            tracks_release_branches: Some(true),
102            is_main_branch: Some(false),
103            is_release_branch: Some(false),
104            pre_release_weight: Some(0),
105            ..branch(DEVELOP_REGEX)
106        },
107    );
108    b.insert(
109        "main".into(),
110        BranchConfiguration {
111            increment: Some(IncrementStrategy::Patch),
112            label: Some(String::new()),
113            source_branches: vec![],
114            prevent_increment: Some(prevent(Some(true), None, None)),
115            track_merge_target: Some(false),
116            track_merge_message: Some(true),
117            is_main_branch: Some(true),
118            pre_release_weight: Some(55000),
119            ..branch(MAIN_REGEX)
120        },
121    );
122    b.insert(
123        "release".into(),
124        BranchConfiguration {
125            increment: Some(IncrementStrategy::Minor),
126            mode: Some(DeploymentMode::ManualDeployment),
127            label: Some("beta".into()),
128            source_branches: vec!["main".into(), "support".into()],
129            prevent_increment: Some(prevent(Some(true), None, Some(false))),
130            track_merge_target: Some(false),
131            is_release_branch: Some(true),
132            pre_release_weight: Some(30000),
133            ..branch(RELEASE_REGEX)
134        },
135    );
136    b.insert(
137        "feature".into(),
138        BranchConfiguration {
139            increment: Some(IncrementStrategy::Inherit),
140            mode: Some(DeploymentMode::ManualDeployment),
141            label: Some("{BranchName}".into()),
142            source_branches: vec![
143                "develop".into(),
144                "main".into(),
145                "release".into(),
146                "support".into(),
147                "hotfix".into(),
148            ],
149            prevent_increment: Some(prevent(None, None, Some(false))),
150            track_merge_message: Some(true),
151            pre_release_weight: Some(30000),
152            ..branch(FEATURE_REGEX)
153        },
154    );
155    b.insert(
156        "pull-request".into(),
157        BranchConfiguration {
158            increment: Some(IncrementStrategy::Inherit),
159            mode: Some(DeploymentMode::ContinuousDelivery),
160            label: Some("PullRequest{Number}".into()),
161            source_branches: vec![
162                "develop".into(),
163                "main".into(),
164                "release".into(),
165                "feature".into(),
166                "support".into(),
167                "hotfix".into(),
168            ],
169            prevent_increment: Some(prevent(Some(true), None, Some(false))),
170            track_merge_message: Some(true),
171            pre_release_weight: Some(30000),
172            ..branch(PR_REGEX)
173        },
174    );
175    b.insert(
176        "hotfix".into(),
177        BranchConfiguration {
178            increment: Some(IncrementStrategy::Inherit),
179            mode: Some(DeploymentMode::ManualDeployment),
180            label: Some("beta".into()),
181            source_branches: vec!["main".into(), "support".into()],
182            prevent_increment: Some(prevent(None, None, Some(false))),
183            is_release_branch: Some(true),
184            pre_release_weight: Some(30000),
185            ..branch(HOTFIX_REGEX)
186        },
187    );
188    b.insert(
189        "support".into(),
190        BranchConfiguration {
191            increment: Some(IncrementStrategy::Patch),
192            label: Some(String::new()),
193            source_branches: vec!["main".into()],
194            prevent_increment: Some(prevent(Some(true), None, None)),
195            track_merge_target: Some(false),
196            is_main_branch: Some(true),
197            pre_release_weight: Some(55000),
198            ..branch(SUPPORT_REGEX)
199        },
200    );
201    b.insert(
202        "unknown".into(),
203        BranchConfiguration {
204            increment: Some(IncrementStrategy::Inherit),
205            mode: Some(DeploymentMode::ManualDeployment),
206            label: Some("{BranchName}".into()),
207            source_branches: vec![
208                "main".into(),
209                "develop".into(),
210                "release".into(),
211                "feature".into(),
212                "pull-request".into(),
213                "support".into(),
214                "hotfix".into(),
215            ],
216            ..branch(UNKNOWN_REGEX)
217        },
218    );
219
220    c.branches = b;
221    c
222}
223
224/// GitHubFlow workflow.
225pub fn githubflow() -> GitVersionConfiguration {
226    let mut c = global_base(DeploymentMode::ContinuousDelivery, default_strategies());
227    let mut b: BTreeMap<String, BranchConfiguration> = BTreeMap::new();
228
229    b.insert(
230        "main".into(),
231        BranchConfiguration {
232            increment: Some(IncrementStrategy::Patch),
233            label: Some(String::new()),
234            source_branches: vec![],
235            prevent_increment: Some(prevent(Some(true), None, None)),
236            is_main_branch: Some(true),
237            pre_release_weight: Some(55000),
238            ..branch(MAIN_REGEX)
239        },
240    );
241    b.insert(
242        "release".into(),
243        BranchConfiguration {
244            increment: Some(IncrementStrategy::Patch),
245            mode: Some(DeploymentMode::ManualDeployment),
246            label: Some("beta".into()),
247            source_branches: vec!["main".into()],
248            prevent_increment: Some(prevent(Some(true), Some(false), Some(false))),
249            track_merge_target: Some(false),
250            track_merge_message: Some(true),
251            is_release_branch: Some(true),
252            pre_release_weight: Some(30000),
253            ..branch(RELEASE_REGEX)
254        },
255    );
256    b.insert(
257        "feature".into(),
258        BranchConfiguration {
259            increment: Some(IncrementStrategy::Inherit),
260            mode: Some(DeploymentMode::ManualDeployment),
261            label: Some("{BranchName}".into()),
262            source_branches: vec!["main".into(), "release".into()],
263            prevent_increment: Some(prevent(None, None, Some(false))),
264            pre_release_weight: Some(30000),
265            ..branch(FEATURE_REGEX)
266        },
267    );
268    b.insert(
269        "pull-request".into(),
270        BranchConfiguration {
271            increment: Some(IncrementStrategy::Inherit),
272            mode: Some(DeploymentMode::ContinuousDelivery),
273            label: Some("PullRequest{Number}".into()),
274            source_branches: vec!["main".into(), "release".into(), "feature".into()],
275            prevent_increment: Some(prevent(Some(true), None, Some(false))),
276            pre_release_weight: Some(30000),
277            ..branch(PR_REGEX)
278        },
279    );
280    b.insert(
281        "unknown".into(),
282        BranchConfiguration {
283            increment: Some(IncrementStrategy::Inherit),
284            mode: Some(DeploymentMode::ManualDeployment),
285            label: Some("{BranchName}".into()),
286            source_branches: vec![
287                "main".into(),
288                "release".into(),
289                "feature".into(),
290                "pull-request".into(),
291            ],
292            prevent_increment: Some(prevent(None, None, Some(false))),
293            track_merge_message: Some(false),
294            ..branch(UNKNOWN_REGEX)
295        },
296    );
297
298    c.branches = b;
299    c
300}
301
302/// TrunkBased (Mainline) workflow.
303pub fn trunkbased() -> GitVersionConfiguration {
304    let mut c = global_base(
305        DeploymentMode::ContinuousDelivery,
306        vec![
307            VersionStrategy::ConfiguredNextVersion,
308            VersionStrategy::Mainline,
309        ],
310    );
311    let mut b: BTreeMap<String, BranchConfiguration> = BTreeMap::new();
312
313    b.insert(
314        "main".into(),
315        BranchConfiguration {
316            increment: Some(IncrementStrategy::Patch),
317            mode: Some(DeploymentMode::ContinuousDeployment),
318            label: Some(String::new()),
319            source_branches: vec![],
320            prevent_increment: Some(prevent(Some(true), None, None)),
321            is_main_branch: Some(true),
322            pre_release_weight: Some(55000),
323            ..branch(MAIN_REGEX)
324        },
325    );
326    b.insert(
327        "feature".into(),
328        BranchConfiguration {
329            increment: Some(IncrementStrategy::Minor),
330            mode: Some(DeploymentMode::ContinuousDelivery),
331            label: Some("{BranchName}".into()),
332            source_branches: vec!["main".into()],
333            prevent_increment: Some(prevent(None, None, Some(false))),
334            pre_release_weight: Some(30000),
335            ..branch(FEATURE_REGEX)
336        },
337    );
338    b.insert(
339        "hotfix".into(),
340        BranchConfiguration {
341            increment: Some(IncrementStrategy::Patch),
342            mode: Some(DeploymentMode::ContinuousDelivery),
343            label: Some("{BranchName}".into()),
344            source_branches: vec!["main".into()],
345            prevent_increment: Some(prevent(None, None, Some(false))),
346            is_release_branch: Some(true),
347            pre_release_weight: Some(30000),
348            ..branch(HOTFIX_REGEX)
349        },
350    );
351    b.insert(
352        "pull-request".into(),
353        BranchConfiguration {
354            increment: Some(IncrementStrategy::Inherit),
355            mode: Some(DeploymentMode::ContinuousDelivery),
356            label: Some("PullRequest{Number}".into()),
357            source_branches: vec!["main".into(), "feature".into(), "hotfix".into()],
358            prevent_increment: Some(prevent(Some(true), None, Some(false))),
359            pre_release_weight: Some(30000),
360            ..branch(PR_REGEX)
361        },
362    );
363    b.insert(
364        "unknown".into(),
365        BranchConfiguration {
366            increment: Some(IncrementStrategy::Patch),
367            mode: Some(DeploymentMode::ContinuousDelivery),
368            label: Some("{BranchName}".into()),
369            source_branches: vec!["main".into()],
370            prevent_increment: Some(prevent(None, None, Some(false))),
371            pre_release_weight: Some(30000),
372            ..branch(UNKNOWN_REGEX)
373        },
374    );
375
376    c.branches = b;
377    c
378}
379
380/// Select default configuration by workflow name. Falls back to GitFlow when None.
381pub fn for_workflow(workflow: Option<&str>) -> GitVersionConfiguration {
382    match workflow.map(|w| w.to_ascii_lowercase()) {
383        Some(w) if w.starts_with("githubflow") => githubflow(),
384        Some(w) if w.starts_with("trunkbased") || w.starts_with("mainline") => trunkbased(),
385        _ => gitflow(),
386    }
387}