feat(changelog): 添加 --no-generate 标志以支持纯模板生成

- 新增 `--no-generate` 参数,强制使用模板生成而非 AI
- 调整 `--yes` 参数仅跳过交互提示,不改变生成行为
- 统一使用工具函数替代 println 输出
This commit is contained in:
2026-08-21 13:57:25 +08:00
parent e6b8b344aa
commit a40c88c768
22 changed files with 5709 additions and 1473 deletions

View File

@@ -13,6 +13,7 @@ use crate::git::tag::{
};
use crate::git::{GitRepo, find_repo};
use crate::i18n::Messages;
use crate::utils::{print_progress, print_success, print_warning};
/// Generate and create Git tags
#[derive(Parser)]
@@ -61,7 +62,7 @@ pub struct TagCommand {
#[arg(short = 't', long)]
think: bool,
/// Skip interactive prompts
/// Skip interactive prompts only (generation behavior unchanged)
#[arg(short = 'y', long)]
yes: bool,
@@ -115,11 +116,11 @@ impl TagCommand {
{
let version_str = tag_name.trim_start_matches('v');
if let Err(e) = crate::utils::validators::validate_semver(version_str) {
println!("{}: {}", "Warning".yellow(), e);
print_warning(&format!("{}: {}", messages.warning(), e));
if !self.yes {
let proceed = Confirm::new()
.with_prompt("Proceed with this tag name anyway?")
.with_prompt(messages.proceed_invalid_tag_name())
.default(true)
.interact()?;
@@ -135,7 +136,7 @@ impl TagCommand {
None
} else if let Some(msg) = &self.message {
Some(msg.clone())
} else if self.generate || (config.tag.auto_generate && !self.yes) {
} else if self.generate || config.tag.auto_generate {
Some(
self.generate_tag_message(&repo, &tag_name, &messages)
.await?,
@@ -143,7 +144,7 @@ impl TagCommand {
} else if !self.yes {
Some(self.input_message_interactive(&tag_name, &messages)?)
} else {
Some(format!("Release {}", tag_name))
Some(messages.release_default(&tag_name))
};
// Show preview
@@ -165,13 +166,13 @@ impl TagCommand {
.interact()?;
if !confirm {
println!("{}", messages.tag_cancelled().yellow());
print_warning(messages.tag_cancelled());
return Ok(());
}
}
if self.dry_run {
println!("\n{} {}", messages.dry_run(), "- tag not created.".yellow());
println!("\n{}", messages.dry_run_tag_not_created().yellow());
return Ok(());
}
@@ -184,13 +185,13 @@ impl TagCommand {
builder.execute(&repo)?;
println!("{} {}", messages.tag_created().green(), tag_name.cyan());
print_success(&format!("{} {}", messages.tag_created(), tag_name.cyan()));
// Push if requested or ask user
if self.push {
println!("{}", messages.pushing_tag(&self.remote));
print_progress(&messages.pushing_tag(&self.remote));
repo.push(&self.remote, &format!("refs/tags/{}", tag_name))?;
println!("{}", messages.pushed_tag(&self.remote));
print_success(&messages.pushed_tag(&self.remote));
} else if !self.yes && !self.dry_run {
let should_push = Confirm::new()
.with_prompt(messages.push_after_tag())
@@ -198,9 +199,9 @@ impl TagCommand {
.interact()?;
if should_push {
println!("{}", messages.pushing_tag(&self.remote));
print_progress(&messages.pushing_tag(&self.remote));
repo.push(&self.remote, &format!("refs/tags/{}", tag_name))?;
println!("{}", messages.pushed_tag(&self.remote));
print_success(&messages.pushed_tag(&self.remote));
}
}
@@ -323,15 +324,16 @@ impl TagCommand {
};
if commits.is_empty() {
return Ok(format!("Release {}", version));
return Ok(messages.release_default(version));
}
println!("{}", messages.ai_generating_tag(commits.len()));
let generator = ContentGenerator::new_with_think(&manager, self.think, None).await?;
generator
let spinner = crate::utils::Spinner::start(&messages.ai_generating_tag(commits.len()));
let result = generator
.generate_tag_message(version, &commits, language)
.await
.await;
spinner.finish_clear();
result
}
async fn auto_detect_version(
@@ -418,7 +420,7 @@ impl TagCommand {
}
fn input_message_interactive(&self, version: &str, messages: &Messages) -> Result<String> {
let default_msg = format!("Release {}", version);
let default_msg = messages.release_default(version);
let use_editor = Confirm::new()
.with_prompt(messages.open_editor())