mod gitea; mod semantic; mod validate_pr; use clap::Command; use tracing_subscriber::{filter::LevelFilter, EnvFilter}; use self::gitea::{get_highest_semver_from_tags, ReleaseRequest, UpdateReleaseRequest}; const VERSION: &'static str = ""; #[tokio::main] async fn main() -> eyre::Result<()> { if let Err(e) = dotenv::dotenv() { tracing::debug!(error = e.to_string(), "could not load.env") } color_eyre::install().unwrap(); let matches = clap::Command::new("releaser") .version(VERSION) .author("kjuulh ") .about("A CLI app for releasing software and managing versions") .arg( clap::Arg::new("quiet") .long("quiet") .short('q') .action(clap::ArgAction::SetTrue), ) .subcommand(Command::new("release").about("Release the software")) .subcommand( Command::new("validate").about("Validate the semantic versioning of the software"), ) .subcommand( Command::new("validate:pr") .about("Validate the semantic versioning of the software") .arg(clap::Arg::new("owner").long("owner").required(true)) .arg(clap::Arg::new("repo").long("repo").required(true)) .arg( clap::Arg::new("pull_request_id") .long("pull-request-id") .required(true) .value_parser(clap::value_parser!(u32).range(0..)), ) .arg( clap::Arg::new("current_version") .long("current-version") .required(true), ), ) .subcommand( Command::new("bump") .about("Bump the semantic versioning in git tags") .arg(clap::Arg::new("owner").long("owner").required(true)) .arg(clap::Arg::new("repo").long("repo").required(true)) .arg(clap::Arg::new("branch").long("branch").required(true)), ) .subcommand( Command::new("release:gitea") .about("Create a release on gitea") .arg(clap::Arg::new("owner").long("owner").required(true)) .arg(clap::Arg::new("repo").long("repo").required(true)) .arg(clap::Arg::new("version").long("version").required(true)) .arg(clap::Arg::new("branch").long("branch").required(true)) .arg( clap::Arg::new("generate-changelog") .long("generate-changelog") .action(clap::ArgAction::SetTrue), ), ) .get_matches(); let quiet = matches.get_one::("quiet"); match quiet { Some(true) => {} _ => { tracing_subscriber::fmt() .pretty() .with_env_filter( EnvFilter::from_default_env().add_directive(LevelFilter::INFO.into()), ) .init(); } } let base_url = &std::env::var("GITEA_BASE_URL").unwrap(); let token = &std::env::var("GITEA_ACCESS_TOKEN").unwrap(); match matches.subcommand() { Some(("release", _sub_matches)) => {} Some(("validate", _sub_matches)) => {} Some(("validate:pr", sub_matches)) => { let owner = sub_matches.get_one::("owner").unwrap(); let repo = sub_matches.get_one::("repo").unwrap(); let pull_request_id = sub_matches.get_one::("pull_request_id").unwrap(); let current_version = sub_matches.get_one::("current_version").unwrap(); match validate_pr::validate_pr(&owner, &repo, *pull_request_id, ¤t_version) .await? { Some(version) => { tracing::info!(version = version, "bumping version"); print!("{}\n", version) } None => tracing::info!(version = current_version, "no version bump required!"), } } Some(("bump", sub_matches)) => { let owner = sub_matches.get_one::("owner").unwrap(); let repo = sub_matches.get_one::("repo").unwrap(); let branch = sub_matches.get_one::("branch").unwrap(); let default_version = "0.0.0"; let _version = match get_highest_semver_from_tags(base_url, owner, repo, token).await { Ok((version, tag)) => { tracing::debug!(version = version.to_string(), "got tag from repo"); match validate_pr::validate_commits( &owner, &repo, &tag.commit.sha, branch, &version.to_string(), ) .await? { Some(version) => { tracing::info!(version = version, "bumping version"); print!("{}\n", version) } None => { tracing::info!(version = default_version, "no version bump required!") } } version.to_string() } _ => default_version.to_string(), }; } Some(("release:gitea", sub_matches)) => { let default_generate_changelog = false; let owner = sub_matches.get_one::("owner").unwrap(); let repo = sub_matches.get_one::("repo").unwrap(); let version = sub_matches.get_one::("version").unwrap(); let branch = sub_matches.get_one::("branch").unwrap(); let _generate_changelog = sub_matches .get_one::("generate-changelog") .unwrap_or(&default_generate_changelog); match crate::gitea::is_newest_release_draft(base_url, owner, repo, token).await { Ok((true, release)) => { let _resp = crate::gitea::modify_release( base_url, owner, repo, token, release.id, &UpdateReleaseRequest { body: None, draft: Some(release.draft), tag_name: Some(version.clone()), name: Some(version.clone()), prerelease: None, target_commitish: Some(branch.clone()), }, ) .await?; tracing::info!("updated release") } _ => { let resp = crate::gitea::create_gitea_release( base_url, owner, repo, token, &ReleaseRequest { tag_name: version.clone(), target_commitish: branch.clone(), name: version.clone(), body: "".into(), draft: true, prerelease: false, }, ) .await?; tracing::info!(url = resp.url, "created release") } } } _ => unreachable!(), } Ok(()) }