1use crate::cli::output::print_success;
4use crate::core::config::Config;
5use crate::core::semver::validate_semver;
6use crate::infra::git::{
7 git_create_annotated_tag, git_is_clean, resolve_repo_name, resolve_toplevel,
8};
9use crate::workflow::error::WorkflowError;
10use std::path::Path;
11
12pub struct TagOptions<'a> {
13 pub version: &'a str,
14 pub repo_root: Option<&'a Path>,
15}
16
17pub fn tag_release(options: TagOptions<'_>) -> Result<(), WorkflowError> {
19 if !validate_semver(options.version) {
20 return Err(WorkflowError::InvalidSemVer(options.version.to_string()));
21 }
22
23 let toplevel = resolve_toplevel(options.repo_root)?;
24 let repo_name = resolve_repo_name(&toplevel);
25
26 let config_path = toplevel.join(".git-claw.toml");
27 let config = Config::load_or_default(&config_path, &repo_name)?;
28
29 if !git_is_clean(&toplevel)? {
30 return Err(WorkflowError::DirtyWorkingTree);
31 }
32
33 let message = format!("Release {}", options.version);
34 git_create_annotated_tag(&toplevel, options.version, config.main_branch(), &message)?;
35
36 print_success(format!(
37 "Created annotated release tag '{}' on branch '{}'",
38 options.version,
39 config.main_branch()
40 ));
41
42 Ok(())
43}