Skip to content

Commit

Permalink
feat(bump): support annotated tags
Browse files Browse the repository at this point in the history
Many projects use annotated commits for their releases. This commit
extends `cog bump` with the `-A MSG`/`--annoted MSG` argument, which
will create an annotated tag with the tag message `MSG`.

Much like the bump hooks, `{{version}}` and `{{latest}}` can be used in
the provided tag message and will be replaced accordingly.
  • Loading branch information
bitfehler authored and oknozor committed Feb 17, 2023
1 parent 0b82758 commit 363387d
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 15 deletions.
8 changes: 8 additions & 0 deletions src/bin/cog/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ enum Command {
#[arg(long, value_parser = packages())]
package: Option<String>,

/// Annotate tag with given message
#[arg(short = 'A', long)]
annotated: Option<String>,

/// Dry-run: print the target version. No action taken
#[arg(short, long)]
dry_run: bool,
Expand Down Expand Up @@ -311,6 +315,7 @@ fn main() -> Result<()> {
pre,
hook_profile,
package,
annotated,
dry_run,
} => {
let mut cocogitto = CocoGitto::get()?;
Expand All @@ -336,13 +341,15 @@ fn main() -> Result<()> {
increment,
pre.as_deref(),
hook_profile.as_deref(),
annotated,
dry_run,
)?
}
None => cocogitto.create_monorepo_version(
increment,
pre.as_deref(),
hook_profile.as_deref(),
annotated,
dry_run,
)?,
}
Expand All @@ -351,6 +358,7 @@ fn main() -> Result<()> {
increment,
pre.as_deref(),
hook_profile.as_deref(),
annotated,
dry_run,
)?
}
Expand Down
34 changes: 30 additions & 4 deletions src/command/bump/monorepo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use colored::*;

use log::info;
use semver::Prerelease;
use tera::Tera;

use crate::conventional::error::BumpError;
use crate::git::oid::OidOf;
Expand All @@ -41,20 +42,28 @@ impl CocoGitto {
increment: IncrementCommand,
pre_release: Option<&str>,
hooks_config: Option<&str>,
annotated: Option<String>,
dry_run: bool,
) -> Result<()> {
match increment {
IncrementCommand::Auto => {
self.create_monorepo_version_auto(pre_release, hooks_config, dry_run)
self.create_monorepo_version_auto(pre_release, hooks_config, annotated, dry_run)
}
_ => self.create_monorepo_version_manual(increment, pre_release, hooks_config, dry_run),
_ => self.create_monorepo_version_manual(
increment,
pre_release,
hooks_config,
annotated,
dry_run,
),
}
}

fn create_monorepo_version_auto(
&mut self,
pre_release: Option<&str>,
hooks_config: Option<&str>,
annotated: Option<String>,
dry_run: bool,
) -> Result<()> {
self.pre_bump_checks()?;
Expand Down Expand Up @@ -158,7 +167,15 @@ impl CocoGitto {
self.repository.create_tag(&bump.new_version.prefixed_tag)?;
}

self.repository.create_tag(&tag)?;
if let Some(msg_tmpl) = annotated {
let mut context = tera::Context::new();
context.insert("latest", &old.version.to_string());
context.insert("version", &tag.version.to_string());
let msg = Tera::one_off(&msg_tmpl, &context, false)?;
self.repository.create_annotated_tag(&tag, &msg)?;
} else {
self.repository.create_tag(&tag)?;
}

// Run per package post hooks
for bump in bumps {
Expand Down Expand Up @@ -194,6 +211,7 @@ impl CocoGitto {
increment: IncrementCommand,
pre_release: Option<&str>,
hooks_config: Option<&str>,
annotated: Option<String>,
dry_run: bool,
) -> Result<()> {
self.pre_bump_checks()?;
Expand Down Expand Up @@ -266,7 +284,15 @@ impl CocoGitto {
sign,
)?;

self.repository.create_tag(&tag)?;
if let Some(msg_tmpl) = annotated {
let mut context = tera::Context::new();
context.insert("latest", &old.version.to_string());
context.insert("version", &tag.version.to_string());
let msg = Tera::one_off(&msg_tmpl, &context, false)?;
self.repository.create_annotated_tag(&tag, &msg)?;
} else {
self.repository.create_tag(&tag)?;
}

// Run global post hooks
self.run_hooks(
Expand Down
12 changes: 11 additions & 1 deletion src/command/bump/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use anyhow::Result;
use colored::*;
use log::info;
use semver::Prerelease;
use tera::Tera;

impl CocoGitto {
pub fn create_package_version(
Expand All @@ -18,6 +19,7 @@ impl CocoGitto {
increment: IncrementCommand,
pre_release: Option<&str>,
hooks_config: Option<&str>,
annotated: Option<String>,
dry_run: bool,
) -> Result<()> {
self.pre_bump_checks()?;
Expand Down Expand Up @@ -76,7 +78,15 @@ impl CocoGitto {
self.repository
.commit(&format!("chore(version): {}", tag), sign)?;

self.repository.create_tag(&tag)?;
if let Some(msg_tmpl) = annotated {
let mut context = tera::Context::new();
context.insert("latest", &current_tag.version.to_string());
context.insert("version", &tag.version.to_string());
let msg = Tera::one_off(&msg_tmpl, &context, false)?;
self.repository.create_annotated_tag(&tag, &msg)?;
} else {
self.repository.create_tag(&tag)?;
}

self.run_hooks(
HookType::PostBump,
Expand Down
12 changes: 11 additions & 1 deletion src/command/bump/standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ use anyhow::Result;
use colored::*;
use log::info;
use semver::Prerelease;
use tera::Tera;

impl CocoGitto {
pub fn create_version(
&mut self,
increment: IncrementCommand,
pre_release: Option<&str>,
hooks_config: Option<&str>,
annotated: Option<String>,
dry_run: bool,
) -> Result<()> {
self.pre_bump_checks()?;
Expand Down Expand Up @@ -70,7 +72,15 @@ impl CocoGitto {
sign,
)?;

self.repository.create_tag(&tag)?;
if let Some(msg_tmpl) = annotated {
let mut context = tera::Context::new();
context.insert("latest", &current_tag.version.to_string());
context.insert("version", &tag.version.to_string());
let msg = Tera::one_off(&msg_tmpl, &context, false)?;
self.repository.create_annotated_tag(&tag, &msg)?;
} else {
self.repository.create_tag(&tag)?;
}

self.run_hooks(
HookType::PostBump,
Expand Down
14 changes: 14 additions & 0 deletions src/git/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ impl Repository {
.map_err(Git2Error::from)
}

pub(crate) fn create_annotated_tag(&self, tag: &Tag, msg: &str) -> Result<(), Git2Error> {
if self.get_diff(true).is_some() {
let statuses = self.get_statuses()?;
return Err(Git2Error::ChangesNeedToBeCommitted(statuses));
}

let head = self.get_head_commit().unwrap();
let sig = self.0.signature()?;
self.0
.tag(&tag.to_string(), &head.into_object(), &sig, msg, false)
.map(|_| ())
.map_err(Git2Error::from)
}

/// Get the latest tag, will ignore package tag if on a monorepo
pub(crate) fn get_latest_tag(&self) -> Result<Tag, TagError> {
let tags: Vec<Tag> = self.all_tags()?;
Expand Down
7 changes: 7 additions & 0 deletions tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ pub fn assert_latest_tag(tag: &str) -> Result<()> {
Ok(())
}

pub fn assert_tag_is_annotated(tag: &str) -> Result<()> {
let objtype = run_fun!(git for-each-ref --format="%(objecttype)" refs/tags/$tag)?;
let objtype: Vec<&str> = objtype.split('\n').collect();
assert_that!(objtype.first()).is_some().is_equal_to(&"tag");
Ok(())
}

/// Git log showing only the HEAD commit, this can be used to make assertion on the last commit
pub fn git_log_head() -> Result<String> {
run_fun!(git log -1 --pretty=%B).map_err(|e| anyhow!(e))
Expand Down
47 changes: 38 additions & 9 deletions tests/lib_tests/bump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,41 @@ fn bump_ok() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_ok();
assert_latest_tag("1.1.0")?;
Ok(())
}

#[sealed_test]
fn annotated_bump_ok() -> Result<()> {
// Arrange
git_init()?;
git_commit("chore: first commit")?;
git_commit("feat: add a feature commit")?;
git_tag("1.0.0")?;
git_commit("feat: add another feature commit")?;

let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(
IncrementCommand::Auto,
None,
None,
Some(String::from("Release version {{version}}")),
false,
);

// Assert
assert_that!(result).is_ok();
assert_latest_tag("1.1.0")?;
assert_tag_is_annotated("1.1.0")?;
Ok(())
}

#[sealed_test]
fn monorepo_bump_ok() -> Result<()> {
// Arrange
Expand All @@ -39,7 +66,7 @@ fn monorepo_bump_ok() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_monorepo_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_monorepo_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_ok();
Expand All @@ -63,7 +90,8 @@ fn monorepo_bump_manual_ok() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_monorepo_version(IncrementCommand::Major, None, None, false);
let result =
cocogitto.create_monorepo_version(IncrementCommand::Major, None, None, None, false);

// Assert
assert_that!(result).is_ok();
Expand All @@ -84,7 +112,7 @@ fn monorepo_with_tag_prefix_bump_ok() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_monorepo_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_monorepo_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_ok();
Expand All @@ -110,6 +138,7 @@ fn package_bump_ok() -> Result<()> {
IncrementCommand::AutoPackage("one".to_string()),
None,
None,
None,
false,
);

Expand All @@ -130,7 +159,7 @@ fn should_fallback_to_0_0_0_when_there_is_no_tag() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_ok();
Expand Down Expand Up @@ -183,7 +212,7 @@ fn bump_with_whitelisted_branch_ok() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_ok();
Expand All @@ -208,7 +237,7 @@ fn bump_with_whitelisted_branch_fails() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result.unwrap_err().to_string()).is_equal_to(
Expand Down Expand Up @@ -237,7 +266,7 @@ fn bump_with_whitelisted_branch_pattern_ok() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_ok();
Expand All @@ -262,7 +291,7 @@ fn bump_with_whitelisted_branch_pattern_err() -> Result<()> {
let mut cocogitto = CocoGitto::get()?;

// Act
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, false);
let result = cocogitto.create_version(IncrementCommand::Auto, None, None, None, false);

// Assert
assert_that!(result).is_err();
Expand Down

0 comments on commit 363387d

Please sign in to comment.