use std::collections::BTreeMap;
use anyhow::bail;
use super::*;
#[derive(Debug, Parser)]
pub struct Args {
#[clap(short, long)]
service: Option<String>,
#[clap(trailing_var_arg = true)]
args: Vec<String>,
}
pub async fn command(args: Args, _json: bool) -> Result<()> {
let configs = Configs::new()?;
let client = GQLClient::new_authorized(&configs)?;
let linked_project = configs.get_linked_project()?;
let vars = queries::project::Variables {
id: linked_project.project.to_owned(),
};
let res = post_graphql::<queries::Project, _>(&client, configs.get_backboard(), vars).await?;
let body = res.data.context("Failed to retrieve response body")?;
let mut all_variables = BTreeMap::<String, String>::new();
let plugins: Vec<_> = body
.project
.plugins
.edges
.iter()
.map(|plugin| &plugin.node)
.collect();
for plugin in plugins {
let vars = queries::variables::Variables {
environment_id: linked_project.environment.clone(),
project_id: linked_project.project.clone(),
service_id: None,
plugin_id: Some(plugin.id.clone()),
};
let res =
post_graphql::<queries::Variables, _>(&client, configs.get_backboard(), vars).await?;
let mut body = res.data.context("Failed to retrieve response body")?;
if body.variables.is_empty() {
continue;
}
all_variables.append(&mut body.variables);
}
if let Some(service) = args.service {
let service_id = body
.project
.services
.edges
.iter()
.find(|s| s.node.name == service || s.node.id == service)
.context("Service not found")?;
let vars = queries::variables::Variables {
environment_id: linked_project.environment.clone(),
project_id: linked_project.project.clone(),
service_id: Some(service_id.node.id.clone()),
plugin_id: None,
};
let res =
post_graphql::<queries::Variables, _>(&client, configs.get_backboard(), vars).await?;
let mut body = res.data.context("Failed to retrieve response body")?;
all_variables.append(&mut body.variables);
} else if linked_project.service.is_some() {
let vars = queries::variables::Variables {
environment_id: linked_project.environment.clone(),
project_id: linked_project.project.clone(),
service_id: linked_project.service.clone(),
plugin_id: None,
};
let res =
post_graphql::<queries::Variables, _>(&client, configs.get_backboard(), vars).await?;
let mut body = res.data.context("Failed to retrieve response body")?;
all_variables.append(&mut body.variables);
} else {
let services: Vec<_> = body.project.services.edges.iter().collect();
if services.len() > 1 {
bail!(
"Multiple services found, please link one using {}",
"railway service".bold().dimmed()
);
}
let service_id = services.first().context("No services found")?;
let vars = queries::variables::Variables {
environment_id: linked_project.environment.clone(),
project_id: linked_project.project.clone(),
service_id: Some(service_id.node.id.clone()),
plugin_id: None,
};
let res =
post_graphql::<queries::Variables, _>(&client, configs.get_backboard(), vars).await?;
let mut body = res.data.context("Failed to retrieve response body")?;
all_variables.append(&mut body.variables);
}
tokio::process::Command::new(args.args.first().context("No command provided")?)
.args(args.args[1..].iter())
.envs(all_variables)
.spawn()
.context("Failed to spawn command")?
.wait()
.await
.context("Failed to wait for command")?;
Ok(())
}