conventional_commits_next_semver/
lib.rs

1use crate::utils::{increment_major, increment_minor, increment_patch};
2use conventional_commits_parser::Commit;
3
4use semver::Version;
5
6pub mod error;
7mod git;
8pub mod types;
9pub mod utils;
10
11// Public API exports
12pub use error::Error;
13pub use git::{git_commits_in_range, latest_semver_compatible_git_tag};
14pub use types::SemverCompatibleGitTag;
15
16/// Returns the next semantic release version.
17///
18/// # Arguments
19///
20/// - `current_version`: The current semantic release version.
21/// - `commits`: The list of conventional commits.
22///
23/// # Returns
24///
25/// `Ok(Version)` if the version needs to be bumped, `Err(Error::SameVersion)`
26/// if the commits do not result in any version increment.`
27pub fn next_version<'a>(
28    current_version: Version,
29    commits: &'a [&'a Commit<'a>],
30) -> Result<Version, Error<'a>> {
31    // Detect if any breaking changes happened.
32    let is_breaking_change = commits.iter().any(|c| c.is_breaking_change);
33    if is_breaking_change {
34        return Ok(increment_major(current_version));
35    }
36
37    // Detect minor changes.
38    let is_new_feature_available = commits.iter().any(|c| c.ty == "feat");
39    if is_new_feature_available {
40        return Ok(increment_minor(current_version));
41    }
42
43    // Detect patch changes.
44    let is_new_fix_available = commits.iter().any(|c| c.ty == "fix");
45    if is_new_fix_available {
46        return Ok(increment_patch(current_version));
47    }
48
49    Err(Error::SameVersion(current_version))
50}