feat: add bump
This commit is contained in:
parent
f3b497d183
commit
a02475d6a3
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -1265,6 +1265,7 @@ dependencies = [
|
||||
"eyre",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
@ -1427,6 +1428,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.159"
|
||||
|
@ -30,6 +30,7 @@ dotenv = "0.15.0"
|
||||
eyre.workspace = true
|
||||
regex = "1.7.3"
|
||||
reqwest = "0.11.16"
|
||||
semver = "1.0.17"
|
||||
serde.workspace = true
|
||||
serde_json = "1.0.95"
|
||||
tokio.workspace = true
|
||||
|
216
src/bump.rs
Normal file
216
src/bump.rs
Normal file
@ -0,0 +1,216 @@
|
||||
use regex::Regex;
|
||||
use semver::{BuildMetadata, Prerelease, Version};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum BumpType {
|
||||
Major,
|
||||
Minor,
|
||||
Patch,
|
||||
}
|
||||
|
||||
pub fn get_most_significant_bump(commits: &[String]) -> Option<BumpType> {
|
||||
let bump_regex = Regex::new(
|
||||
r"^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test|breaking)(\([a-zA-Z-_ ]+\))?: .*",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut major_bump = None;
|
||||
let mut minor_bump = None;
|
||||
let mut patch_bump = None;
|
||||
|
||||
for commit in commits {
|
||||
if let Some(captures) = bump_regex.captures(commit) {
|
||||
let bump_type = captures.get(1).unwrap().as_str();
|
||||
match bump_type {
|
||||
"breaking" => {
|
||||
if major_bump.is_none() {
|
||||
major_bump = Some(1);
|
||||
}
|
||||
}
|
||||
"feat" => {
|
||||
if minor_bump.is_none() && major_bump.is_none() {
|
||||
minor_bump = Some(1);
|
||||
} else if let Some(mut count) = minor_bump {
|
||||
count += 1;
|
||||
minor_bump = Some(count);
|
||||
}
|
||||
}
|
||||
"chore" | "docs" | "ci" | "test" => {}
|
||||
_ => {
|
||||
if patch_bump.is_none() && minor_bump.is_none() && major_bump.is_none() {
|
||||
patch_bump = Some(1);
|
||||
} else if let Some(mut count) = patch_bump {
|
||||
count += 1;
|
||||
patch_bump = Some(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let most_significant_bump = match (major_bump, minor_bump, patch_bump) {
|
||||
(Some(count), _, _) if count > 0 => Some(BumpType::Major),
|
||||
(_, Some(count), _) if count > 0 => Some(BumpType::Minor),
|
||||
(_, _, Some(count)) if count > 0 => Some(BumpType::Patch),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
most_significant_bump
|
||||
}
|
||||
|
||||
fn increment_patch(v: &mut Version) {
|
||||
v.patch += 1;
|
||||
v.pre = Prerelease::EMPTY;
|
||||
v.build = BuildMetadata::EMPTY;
|
||||
}
|
||||
|
||||
fn increment_minor(v: &mut Version) {
|
||||
v.minor += 1;
|
||||
v.patch = 0;
|
||||
v.pre = Prerelease::EMPTY;
|
||||
v.build = BuildMetadata::EMPTY;
|
||||
}
|
||||
|
||||
fn increment_major(v: &mut Version) {
|
||||
v.major += 1;
|
||||
v.minor = 0;
|
||||
v.patch = 0;
|
||||
v.pre = Prerelease::EMPTY;
|
||||
v.build = BuildMetadata::EMPTY;
|
||||
}
|
||||
|
||||
pub fn bump_semver(semver: &str, bump_type: BumpType) -> Result<String, semver::Error> {
|
||||
let mut version = Version::parse(semver)?;
|
||||
|
||||
match bump_type {
|
||||
BumpType::Major => increment_major(&mut version),
|
||||
BumpType::Minor => increment_minor(&mut version),
|
||||
BumpType::Patch => increment_patch(&mut version),
|
||||
}
|
||||
|
||||
Ok(version.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{get_most_significant_bump, BumpType};
|
||||
|
||||
#[test]
|
||||
fn test_no_commits() {
|
||||
let commits = vec![];
|
||||
assert_eq!(get_most_significant_bump(&commits), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_major_bump() {
|
||||
let commits = vec![
|
||||
"breaking: new feature".to_string(),
|
||||
"fix: bug fix".to_string(),
|
||||
"chore: some chore".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Major));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_minor_bump() {
|
||||
let commits = vec!["feat: bug fix".to_string(), "chore: some chore".to_string()];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Minor));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_patch_bump() {
|
||||
let commits = vec![
|
||||
"chore: some chore".to_string(),
|
||||
"style: code style change".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Patch));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_significant_bumps() {
|
||||
let commits = vec![
|
||||
"docs: documentation update".to_string(),
|
||||
"chore: another chore".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_combined_bumps() {
|
||||
let commits = vec![
|
||||
"breaking: new breaking change".to_string(),
|
||||
"feat: new feature".to_string(),
|
||||
"fix: bug fix".to_string(),
|
||||
"style: code style change".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Major));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_major_bump_with_scope() {
|
||||
let commits = vec![
|
||||
"breaking(some-system): new feature".to_string(),
|
||||
"fix(another-system): bug fix".to_string(),
|
||||
"chore(third-system): some chore".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Major));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_minor_bump_with_scope() {
|
||||
let commits = vec![
|
||||
"feat(some-system): bug fix".to_string(),
|
||||
"chore(another-system): some chore".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Minor));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_patch_bump_with_scope() {
|
||||
let commits = vec![
|
||||
"chore(some-system): some chore".to_string(),
|
||||
"style(another-system): code style change".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Patch));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_combined_bumps_with_scope() {
|
||||
let commits = vec![
|
||||
"breaking(some-system): new feature".to_string(),
|
||||
"feat(another-system): bug fix".to_string(),
|
||||
"style(third-system): code style change".to_string(),
|
||||
];
|
||||
assert_eq!(get_most_significant_bump(&commits), Some(BumpType::Major));
|
||||
}
|
||||
|
||||
use super::bump_semver;
|
||||
|
||||
#[test]
|
||||
fn test_bump_semver_major() {
|
||||
let semver = "1.2.3";
|
||||
let bumped_version = bump_semver(semver, BumpType::Major).unwrap();
|
||||
assert_eq!(bumped_version, "2.0.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bump_semver_minor() {
|
||||
let semver = "1.2.3";
|
||||
let bumped_version = bump_semver(semver, BumpType::Minor).unwrap();
|
||||
assert_eq!(bumped_version, "1.3.0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bump_semver_patch() {
|
||||
let semver = "1.2.3";
|
||||
let bumped_version = bump_semver(semver, BumpType::Patch).unwrap();
|
||||
assert_eq!(bumped_version, "1.2.4");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bump_semver_invalid() {
|
||||
let semver = "1.2.invalid";
|
||||
let bumped_version = bump_semver(semver, BumpType::Patch);
|
||||
assert!(bumped_version.is_err());
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
mod bump;
|
||||
mod conventional_commits;
|
||||
mod gitea;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user