use clap::Subcommand;
use crate::client;
use crate::config::ProjectConfig;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("no deployment matching {0}")]
NoMatch(String),
#[error(transparent)]
Client(#[from] crate::client::ClientError),
}
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, clap::Args)]
pub struct AliasArgs {
#[arg(long, env = "BOATRAMP_SERVER", global = true)]
server: Option<String>,
#[arg(long, env = "BOATRAMP_SITE", global = true)]
site: Option<String>,
#[command(subcommand)]
command: AliasCommand,
}
#[derive(Debug, Subcommand)]
enum AliasCommand {
Set {
name: String,
deployment: String,
},
Rm {
name: String,
},
Ls,
}
pub async fn run(args: AliasArgs, config: &ProjectConfig) -> Result<()> {
let (server, site) = client::resolve_target(args.server, args.site, config)?;
let cp = client::ControlPlane::new(
server,
client::http_client(client::token(config).as_deref()),
client::resolve_project(config),
);
match args.command {
AliasCommand::Ls => {
let aliases = cp.list_aliases(&site).await?;
if aliases.is_empty() {
println!("no aliases for {site}");
}
for (name, id) in &aliases {
println!("{name} -> {}", short(id));
}
}
AliasCommand::Set { name, deployment } => {
let list = cp.fetch_deployments(&site).await?;
let id =
resolve_id(&list, &deployment).ok_or_else(|| Error::NoMatch(deployment.clone()))?;
cp.set_alias(&site, &name, &id).await?;
println!("alias {name} -> {} for {site}", short(&id));
}
AliasCommand::Rm { name } => {
cp.remove_alias(&site, &name).await?;
println!("removed alias {name} from {site}");
}
}
Ok(())
}
fn short(id: &str) -> &str {
&id[..id.len().min(12)]
}
fn resolve_id(list: &boatramp_core::deploy::DeploymentList, wanted: &str) -> Option<String> {
if list.deployments.iter().any(|e| e.id == wanted) {
return Some(wanted.to_string());
}
let mut matches = list.deployments.iter().filter(|e| e.id.starts_with(wanted));
if let Some(first) = matches.next() {
return matches.next().is_none().then(|| first.id.clone());
}
if wanted.len() == 64 && wanted.bytes().all(|b| b.is_ascii_hexdigit()) {
return Some(wanted.to_string());
}
None
}