Files
gt-tool/src/main.rs
Robert Garrett bbf1eecc52 Rename the user-agent string, include pkg version
It's no longer a test agent, it's the release one. We're including the
package version (as specified in Cargo.toml).
2025-06-01 15:03:08 -05:00

132 lines
4.7 KiB
Rust

use gt_tools::cli::Args;
use gt_tools::structs::release::{CreateReleaseOption, Release};
use clap::Parser;
use reqwest::header;
use reqwest::header::ACCEPT;
#[tokio::main]
async fn main() -> Result<(), gt_tools::Error> {
let args = Args::parse();
let mut headers = reqwest::header::HeaderMap::new();
headers.append(ACCEPT, header::HeaderValue::from_static("application/json"));
// Gitea expects to see "token " for token auth.
if let Ok(token) = std::env::var("RELEASE_KEY_GITEA") {
let token = format!("token {token}");
headers.append("Authorization", token.parse().unwrap());
}
let client = reqwest::Client::builder()
.user_agent(format!(
"gt-tools-agent-{}",
env!("CARGO_PKG_VERSION")
))
.default_headers(headers)
.build()?;
match args.command {
gt_tools::cli::Commands::ListReleases => {
let releases =
gt_tools::api::release::list_releases(&client, &args.gitea_url, &args.repo).await?;
for release in releases {
println!("{:?}", release);
}
}
gt_tools::cli::Commands::CreateRelease {
name,
body,
draft,
prerelease,
tag_name,
target_commitish,
} => {
let submission = CreateReleaseOption {
body,
draft,
name,
prerelease,
tag_name,
target_commitish,
};
gt_tools::api::release::create_release(
&client,
&args.gitea_url,
&args.repo,
submission,
)
.await?;
}
gt_tools::cli::Commands::UploadRelease {
tag_name,
create,
files,
} => {
println!("Uploading files to a release!");
println!("Release Tag: {tag_name}");
println!("Creating?: {create}");
println!("Files...");
for file in &files {
println!("--- {file}");
}
// TODO: Pre-create the release, if it doesn't exist.
// There's only Gitea APIs to get all releases, or one by-id.
// Grab all, find the one that matches the input tag.
// Scream if there are multiple matches.
let release_candidates =
gt_tools::api::release::list_releases(&client, &args.gitea_url, &args.repo).await?;
if let Some(release) = match_release_by_tag(&tag_name, release_candidates) {
gt_tools::api::release_attachment::create_release_attachment(
&client,
&args.gitea_url,
&args.repo,
release.id,
files,
)
.await?;
} else {
println!("ERR: Couldn't find a release matching the tag \"{tag_name}\".");
}
}
}
Ok(())
}
// Util to scan a release list for a given tag. Returns Some(release) if found,
// None if not, and crashes the program if multiple are found.
//
// The Gitea webpage won't create multiple releases for a given tag, but the
// API might... And someone could always fiddle with the database directly.
// Until I find a guarantee of any particular behavior, I'm going to assume it
// *can* happen and crash when it does. Clearly it isn't supposed to, so I'm
// not going to meaningfully handle it, only prevent garbage from propagating.
fn match_release_by_tag(tag: &String, releases: Vec<Release>) -> Option<Release> {
let mut release: Option<Release> = None;
for rel in releases {
if rel.tag_name == *tag {
// Only store the value if one hasn't been stored already
if let Some(first_release) = &release {
// if there was already a match, begin the error diagnostic creation.
let first_id = first_release.id;
let second_id = rel.id;
assert!(
first_id != second_id,
"FAILURE: Found the same release ID twice while scanning for duplicate tags. How did we get the same one twice?"
);
eprintln!("ERROR: Two releases have been found for the tag \"{tag}\".");
eprintln!("ERROR: first ID: {first_id}");
eprintln!("ERROR: second ID: {second_id}");
panic!("ERROR: Nonsense detected, I'm bailing out!");
} else {
// else, store our first (and hopefully only) match
release = Some(rel);
}
}
}
return release;
}