199 lines
7.6 KiB
Rust
199 lines
7.6 KiB
Rust
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 = "<dev>";
|
|
|
|
#[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 <contact@kjuulh.io>")
|
|
.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::<bool>("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::<String>("owner").unwrap();
|
|
let repo = sub_matches.get_one::<String>("repo").unwrap();
|
|
let pull_request_id = sub_matches.get_one::<u32>("pull_request_id").unwrap();
|
|
let current_version = sub_matches.get_one::<String>("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::<String>("owner").unwrap();
|
|
let repo = sub_matches.get_one::<String>("repo").unwrap();
|
|
let branch = sub_matches.get_one::<String>("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::<String>("owner").unwrap();
|
|
let repo = sub_matches.get_one::<String>("repo").unwrap();
|
|
let version = sub_matches.get_one::<String>("version").unwrap();
|
|
let branch = sub_matches.get_one::<String>("branch").unwrap();
|
|
let _generate_changelog = sub_matches
|
|
.get_one::<bool>("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(())
|
|
}
|