use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum MockEnvironmentName {
Dev,
Test,
Prod,
}
impl MockEnvironmentName {
pub fn as_str(&self) -> &'static str {
match self {
MockEnvironmentName::Dev => "dev",
MockEnvironmentName::Test => "test",
MockEnvironmentName::Prod => "prod",
}
}
#[allow(clippy::should_implement_trait)]
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"dev" => Some(MockEnvironmentName::Dev),
"test" => Some(MockEnvironmentName::Test),
"prod" => Some(MockEnvironmentName::Prod),
_ => None,
}
}
pub fn promotion_order() -> Vec<Self> {
vec![
MockEnvironmentName::Dev,
MockEnvironmentName::Test,
MockEnvironmentName::Prod,
]
}
pub fn next(&self) -> Option<Self> {
match self {
MockEnvironmentName::Dev => Some(MockEnvironmentName::Test),
MockEnvironmentName::Test => Some(MockEnvironmentName::Prod),
MockEnvironmentName::Prod => None,
}
}
pub fn previous(&self) -> Option<Self> {
match self {
MockEnvironmentName::Dev => None,
MockEnvironmentName::Test => Some(MockEnvironmentName::Dev),
MockEnvironmentName::Prod => Some(MockEnvironmentName::Test),
}
}
}
impl std::fmt::Display for MockEnvironmentName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PromotionEntityType {
Scenario,
Persona,
Config,
}
impl std::fmt::Display for PromotionEntityType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PromotionEntityType::Scenario => write!(f, "scenario"),
PromotionEntityType::Persona => write!(f, "persona"),
PromotionEntityType::Config => write!(f, "config"),
}
}
}
#[allow(clippy::too_many_arguments)]
#[async_trait::async_trait]
pub trait PromotionService: Send + Sync {
async fn promote_entity(
&self,
workspace_id: uuid::Uuid,
entity_type: PromotionEntityType,
entity_id: String,
entity_version: Option<String>,
from_environment: MockEnvironmentName,
to_environment: MockEnvironmentName,
promoted_by: uuid::Uuid,
comments: Option<String>,
) -> crate::Result<uuid::Uuid>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PromotionStatus {
Pending,
Approved,
Rejected,
Completed,
Failed,
}
impl std::fmt::Display for PromotionStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PromotionStatus::Pending => write!(f, "pending"),
PromotionStatus::Approved => write!(f, "approved"),
PromotionStatus::Rejected => write!(f, "rejected"),
PromotionStatus::Completed => write!(f, "completed"),
PromotionStatus::Failed => write!(f, "failed"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PromotionRequest {
pub entity_type: PromotionEntityType,
pub entity_id: String,
pub entity_version: Option<String>,
pub workspace_id: String,
pub from_environment: MockEnvironmentName,
pub to_environment: MockEnvironmentName,
pub requires_approval: bool,
pub approval_required_reason: Option<String>,
pub comments: Option<String>,
#[serde(default)]
pub metadata: std::collections::HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PromotionHistory {
pub entity_type: PromotionEntityType,
pub entity_id: String,
pub workspace_id: String,
pub promotions: Vec<PromotionHistoryEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PromotionHistoryEntry {
pub promotion_id: String,
pub entity_type: PromotionEntityType,
pub entity_id: String,
pub entity_version: Option<String>,
pub from_environment: MockEnvironmentName,
pub to_environment: MockEnvironmentName,
pub promoted_by: String,
pub approved_by: Option<String>,
pub status: PromotionStatus,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub comments: Option<String>,
pub pr_url: Option<String>,
#[serde(default)]
pub metadata: std::collections::HashMap<String, serde_json::Value>,
}