use anyhow::{Result, anyhow};use async_trait::async_trait;use cynic::{MutationBuilder, QueryBuilder};#[cfg(test)]use mockall::automock;use warp_graphql::mutations::delete_runner::{ DeleteRunner, DeleteRunnerInput, DeleteRunnerResult, DeleteRunnerVariables,};use warp_graphql::mutations::upsert_runner::{ UpsertRunner, UpsertRunnerInput, UpsertRunnerResult, UpsertRunnerVariables,};use warp_graphql::queries::get_runners::{ GetRunners, GetRunnersResult, GetRunnersVariables, Runner, RunnerSortBy,}; use super::ServerApi;use crate::server::graphql::{get_request_context, get_user_facing_error_message};use crate::server::team_scope::RequestTeamScope; /// The result of upserting a runner: the resulting [`Runner`] plus whether the/// operation updated an existing runner (vs. creating a new one).// `upsert_runner`/`delete_runner` back CLI commands that aren't built for wasm, so// this type is unused there while `get_runners` still powers the runner picker.#[cfg_attr(target_family = "wasm", allow(dead_code))]pub struct UpsertedRunner { pub runner: Runner, pub is_update: bool,} /// Client for the Factory GraphQL surface (runner CRUD).#[cfg_attr(test, automock)]#[cfg_attr(not(target_family = "wasm"), async_trait)]#[cfg_attr(target_family = "wasm", async_trait(?Send))]pub trait FactoryClient: 'static + Send + Sync { /// Fetch all runners visible to the caller, optionally sorted. async fn get_runners( &self, sort_by: Option<RunnerSortBy>, team_scope: Option<RequestTeamScope>, ) -> Result<Vec<Runner>>; /// Create or update a runner. `input.uid` is `None` for a create and /// `Some(_)` for an update; this single method backs both CLI commands. #[cfg_attr(target_family = "wasm", allow(dead_code))] async fn upsert_runner( &self, input: UpsertRunnerInput, team_scope: Option<RequestTeamScope>, ) -> Result<UpsertedRunner>; /// Delete a runner by UID, returning the deleted UID on success. #[cfg_attr(target_family = "wasm", allow(dead_code))] async fn delete_runner(&self, uid: String) -> Result<String>;} #[cfg_attr(not(target_family = "wasm"), async_trait)]#[cfg_attr(target_family = "wasm", async_trait(?Send))]impl FactoryClient for ServerApi { async fn get_runners( &self, sort_by: Option<RunnerSortBy>, team_scope: Option<RequestTeamScope>, ) -> Result<Vec<Runner>> { let operation = GetRunners::build(GetRunnersVariables { request_context: get_request_context(), sort_by, }); let response = match team_scope { Some(team_scope) => { self.send_graphql_request_for_team(operation, team_scope) .await? } None => self.send_graphql_request(operation, None).await?, }; match response.get_runners { GetRunnersResult::GetRunnersOutput(output) => Ok(output.runners), GetRunnersResult::UserFacingError(e) => Err(anyhow!(get_user_facing_error_message(e))), GetRunnersResult::Unknown => Err(anyhow!("failed to list runners")), } } async fn upsert_runner( &self, input: UpsertRunnerInput, team_scope: Option<RequestTeamScope>, ) -> Result<UpsertedRunner> { let operation = UpsertRunner::build(UpsertRunnerVariables { input, request_context: get_request_context(), }); let response = match team_scope { Some(team_scope) => { self.send_graphql_request_for_team(operation, team_scope) .await? } None => self.send_graphql_request(operation, None).await?, }; match response.upsert_runner { UpsertRunnerResult::UpsertRunnerOutput(output) => Ok(UpsertedRunner { runner: output.runner, is_update: output.is_update, }), UpsertRunnerResult::UserFacingError(e) => { Err(anyhow!(get_user_facing_error_message(e))) } UpsertRunnerResult::Unknown => Err(anyhow!("failed to upsert runner")), } } async fn delete_runner(&self, uid: String) -> Result<String> { let operation = DeleteRunner::build(DeleteRunnerVariables { input: DeleteRunnerInput { uid: cynic::Id::new(uid), }, request_context: get_request_context(), }); let response = self.send_graphql_request(operation, None).await?; match response.delete_runner { DeleteRunnerResult::DeleteRunnerOutput(output) => { Ok(output.deleted_uid.inner().to_string()) } DeleteRunnerResult::UserFacingError(e) => { Err(anyhow!(get_user_facing_error_message(e))) } DeleteRunnerResult::Unknown => Err(anyhow!("failed to delete runner")), } }}
use anyhow::{Result, anyhow};
use async_trait::async_trait;
use cynic::{MutationBuilder, QueryBuilder};
#[cfg(test)]
use mockall::automock;
use warp_graphql::mutations::delete_runner::{
DeleteRunner, DeleteRunnerInput, DeleteRunnerResult, DeleteRunnerVariables,
};
use warp_graphql::mutations::upsert_runner::{
UpsertRunner, UpsertRunnerInput, UpsertRunnerResult, UpsertRunnerVariables,
};
use warp_graphql::queries::get_runners::{
GetRunners, GetRunnersResult, GetRunnersVariables, Runner, RunnerSortBy,
};
use super::ServerApi;
use crate::server::graphql::{get_request_context, get_user_facing_error_message};
use crate::server::team_scope::RequestTeamScope;
/// The result of upserting a runner: the resulting [`Runner`] plus whether the
/// operation updated an existing runner (vs. creating a new one).
// `upsert_runner`/`delete_runner` back CLI commands that aren't built for wasm, so
// this type is unused there while `get_runners` still powers the runner picker.
#[cfg_attr(target_family = "wasm", allow(dead_code))]
pub struct UpsertedRunner {
pub runner: Runner,
pub is_update: bool,
}
/// Client for the Factory GraphQL surface (runner CRUD).
#[cfg_attr(test, automock)]
#[cfg_attr(not(target_family = "wasm"), async_trait)]
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
pub trait FactoryClient: 'static + Send + Sync {
/// Fetch all runners visible to the caller, optionally sorted.
async fn get_runners(
&self,
sort_by: Option<RunnerSortBy>,
team_scope: Option<RequestTeamScope>,
) -> Result<Vec<Runner>>;
/// Create or update a runner. `input.uid` is `None` for a create and
/// `Some(_)` for an update; this single method backs both CLI commands.
#[cfg_attr(target_family = "wasm", allow(dead_code))]
async fn upsert_runner(
&self,
input: UpsertRunnerInput,
team_scope: Option<RequestTeamScope>,
) -> Result<UpsertedRunner>;
/// Delete a runner by UID, returning the deleted UID on success.
#[cfg_attr(target_family = "wasm", allow(dead_code))]
async fn delete_runner(&self, uid: String) -> Result<String>;
}
#[cfg_attr(not(target_family = "wasm"), async_trait)]
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
impl FactoryClient for ServerApi {
async fn get_runners(
&self,
sort_by: Option<RunnerSortBy>,
team_scope: Option<RequestTeamScope>,
) -> Result<Vec<Runner>> {
let operation = GetRunners::build(GetRunnersVariables {
request_context: get_request_context(),
sort_by,
});
let response = match team_scope {
Some(team_scope) => {
self.send_graphql_request_for_team(operation, team_scope)
.await?
}
None => self.send_graphql_request(operation, None).await?,
};
match response.get_runners {
GetRunnersResult::GetRunnersOutput(output) => Ok(output.runners),
GetRunnersResult::UserFacingError(e) => Err(anyhow!(get_user_facing_error_message(e))),
GetRunnersResult::Unknown => Err(anyhow!("failed to list runners")),
}
}
async fn upsert_runner(
&self,
input: UpsertRunnerInput,
team_scope: Option<RequestTeamScope>,
) -> Result<UpsertedRunner> {
let operation = UpsertRunner::build(UpsertRunnerVariables {
input,
request_context: get_request_context(),
});
let response = match team_scope {
Some(team_scope) => {
self.send_graphql_request_for_team(operation, team_scope)
.await?
}
None => self.send_graphql_request(operation, None).await?,
};
match response.upsert_runner {
UpsertRunnerResult::UpsertRunnerOutput(output) => Ok(UpsertedRunner {
runner: output.runner,
is_update: output.is_update,
}),
UpsertRunnerResult::UserFacingError(e) => {
Err(anyhow!(get_user_facing_error_message(e)))
}
UpsertRunnerResult::Unknown => Err(anyhow!("failed to upsert runner")),
}
}
async fn delete_runner(&self, uid: String) -> Result<String> {
let operation = DeleteRunner::build(DeleteRunnerVariables {
input: DeleteRunnerInput {
uid: cynic::Id::new(uid),
},
request_context: get_request_context(),
});
let response = self.send_graphql_request(operation, None).await?;
match response.delete_runner {
DeleteRunnerResult::DeleteRunnerOutput(output) => {
Ok(output.deleted_uid.inner().to_string())
}
DeleteRunnerResult::UserFacingError(e) => {
Err(anyhow!(get_user_facing_error_message(e)))
}
DeleteRunnerResult::Unknown => Err(anyhow!("failed to delete runner")),
}
}
}