use clap::Parser;
use color_eyre::eyre::Result;
use releasaurus::cli::{Cli, Command, GetCommand, get};
use releasaurus_core::config::resolved::PackageOverrides;
use releasaurus_core::forge::manager::{ForgeManager, ForgeOptions};
use releasaurus_core::orchestrator::Orchestrator;
use releasaurus_core::resolver::Resolver;
use std::collections::HashMap;
use std::rc::Rc;
const DEBUG_ENV_VAR: &str = "RELEASAURUS_DEBUG";
const DRY_RUN_ENV_VAR: &str = "RELEASAURUS_DRY_RUN";
fn silence_logs(cli: &Cli) -> bool {
let mut silent = false;
if let Command::Get { command, .. } = &cli.command {
match command {
GetCommand::NextRelease { out_file, .. } => {
if out_file.is_none() {
silent = true;
}
}
GetCommand::CurrentRelease { out_file, .. } => {
if out_file.is_none() {
silent = true;
}
}
GetCommand::Release { out_file, .. } => {
if out_file.is_none() {
silent = true;
}
}
GetCommand::RecompiledNotes { out_file, .. } => {
if out_file.is_none() {
silent = true;
}
}
}
}
silent
}
fn initialize_logger(cli: &Cli) -> Result<()> {
let silent = silence_logs(cli);
let filter = if silent {
simplelog::LevelFilter::Off
} else if cli.debug {
simplelog::LevelFilter::Debug
} else {
simplelog::LevelFilter::Info
};
let config = simplelog::ConfigBuilder::new()
.add_filter_allow_str("releasaurus")
.build();
simplelog::TermLogger::init(
filter,
config,
simplelog::TerminalMode::Mixed,
simplelog::ColorChoice::Auto,
)?;
Ok(())
}
fn get_dry_run_value(cli: &Cli) -> bool {
if std::env::var(DRY_RUN_ENV_VAR).is_ok() {
return true;
}
match cli.command {
Command::Release { dry_run, .. } => dry_run,
Command::ReleasePR { dry_run, .. } => dry_run,
Command::StartNext { dry_run, .. } => dry_run,
_ => false,
}
}
async fn create_orchestrator(cli: &Cli, dry_run: bool) -> Result<Orchestrator> {
let mut forge = cli.forge_args.forge().await?;
let global_overrides = cli.get_global_overrides();
let package_overrides = cli.get_package_overrides()?;
let commit_modifiers = cli.get_commit_modifiers();
let config = Rc::new(
forge
.load_config(global_overrides.base_branch.clone())
.await?,
);
forge.set_commit_search_depth(config.first_release_search_depth);
forge.set_tag_search_depth(config.tag_search_depth);
let forge_manager = ForgeManager::new(forge, ForgeOptions { dry_run });
log::debug!("global overrides: {:#?}", global_overrides);
log::debug!("package overrides: {:#?}", package_overrides);
log::debug!("commit modifiers: {:#?}", commit_modifiers);
let repo_name = forge_manager.repo_name();
let default_branch = forge_manager.default_branch();
let release_link_base_url = forge_manager.release_link_base_url();
let compare_link_base_url = forge_manager.compare_link_base_url();
let resolver = Resolver::builder()
.commit_modifiers(commit_modifiers)
.global_overrides(global_overrides)
.package_overrides(
package_overrides
.into_iter()
.map(|(k, v)| (k, PackageOverrides::from(v)))
.collect::<HashMap<_, _>>(),
)
.release_link_base_url(release_link_base_url.clone())
.compare_link_base_url(compare_link_base_url.clone())
.repo_default_branch(default_branch)
.repo_name(repo_name)
.toml_config(Rc::clone(&config))
.build()?;
let (resolved_config, resolved_packages) =
resolver.resolve(config.packages.clone())?;
let orchestrator = Orchestrator::builder()
.config(Rc::clone(&resolved_config))
.package_configs(Rc::new(resolved_packages))
.forge(Rc::new(forge_manager))
.build()?;
Ok(orchestrator)
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
let mut cli = Cli::parse();
if std::env::var(DEBUG_ENV_VAR).is_ok() {
cli.debug = true;
}
let dry_run = get_dry_run_value(&cli);
if dry_run {
cli.debug = true;
}
initialize_logger(&cli)?;
let orchestrator = create_orchestrator(&cli, dry_run).await?;
match cli.command {
Command::ReleasePR { package, .. } => {
orchestrator.create_release_prs(package).await?;
Ok(())
}
Command::Release { package, .. } => {
orchestrator.create_releases(package).await?;
Ok(())
}
Command::Get { command } => {
get::execute(orchestrator, command).await?;
Ok(())
}
Command::StartNext { packages, .. } => {
orchestrator.start_next_release(packages).await?;
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_base_args() -> Vec<String> {
vec![
"releasaurus".to_string(),
"--repo".to_string(),
"https://github.com/test/repo".to_string(),
]
}
#[test]
fn silence_logs_returns_true_for_get_next_release_without_out_file() {
let args = [
create_base_args(),
vec!["get".to_string(), "next-release".to_string()],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(silence_logs(&cli));
}
#[test]
fn silence_logs_returns_false_for_get_next_release_with_out_file() {
let args = [
create_base_args(),
vec![
"get".to_string(),
"next-release".to_string(),
"--out-file".to_string(),
"output.json".to_string(),
],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(!silence_logs(&cli));
}
#[test]
fn silence_logs_returns_true_for_get_current_release_without_out_file() {
let args = [
create_base_args(),
vec!["get".to_string(), "current-release".to_string()],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(silence_logs(&cli));
}
#[test]
fn silence_logs_returns_false_for_get_current_release_with_out_file() {
let args = [
create_base_args(),
vec![
"get".to_string(),
"current-release".to_string(),
"--out-file".to_string(),
"output.json".to_string(),
],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(!silence_logs(&cli));
}
#[test]
fn silence_logs_returns_true_for_get_release_without_out_file() {
let args = [
create_base_args(),
vec![
"get".to_string(),
"release".to_string(),
"--tag".to_string(),
"v1.0.0".to_string(),
],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(silence_logs(&cli));
}
#[test]
fn silence_logs_returns_false_for_get_release_with_out_file() {
let args = [
create_base_args(),
vec![
"get".to_string(),
"release".to_string(),
"--tag".to_string(),
"v1.0.0".to_string(),
"--out-file".to_string(),
"output.json".to_string(),
],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(!silence_logs(&cli));
}
#[test]
fn silence_logs_returns_true_for_get_notes_without_out_file() {
let args = [
create_base_args(),
vec![
"get".to_string(),
"notes".to_string(),
"--file".to_string(),
"releases.json".to_string(),
],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(silence_logs(&cli));
}
#[test]
fn silence_logs_returns_false_for_get_notes_with_out_file() {
let args = [
create_base_args(),
vec![
"get".to_string(),
"notes".to_string(),
"--file".to_string(),
"releases.json".to_string(),
"--out-file".to_string(),
"output.json".to_string(),
],
]
.concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(!silence_logs(&cli));
}
#[test]
fn silence_logs_returns_false_for_non_get_commands() {
let test_cases = vec!["release-pr", "release", "start-next"];
for cmd in test_cases {
let args = [create_base_args(), vec![cmd.to_string()]].concat();
let cli = Cli::try_parse_from(args).unwrap();
assert!(
!silence_logs(&cli),
"silence_logs should return false for {} command",
cmd
);
}
}
}