1use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14#[serde(rename_all = "lowercase")]
15pub enum MockEnvironmentName {
16 Dev,
18 Test,
20 Prod,
22}
23
24impl MockEnvironmentName {
25 pub fn as_str(&self) -> &'static str {
27 match self {
28 MockEnvironmentName::Dev => "dev",
29 MockEnvironmentName::Test => "test",
30 MockEnvironmentName::Prod => "prod",
31 }
32 }
33
34 #[allow(clippy::should_implement_trait)]
36 pub fn from_str(s: &str) -> Option<Self> {
37 match s.to_lowercase().as_str() {
38 "dev" => Some(MockEnvironmentName::Dev),
39 "test" => Some(MockEnvironmentName::Test),
40 "prod" => Some(MockEnvironmentName::Prod),
41 _ => None,
42 }
43 }
44
45 pub fn promotion_order() -> Vec<Self> {
47 vec![
48 MockEnvironmentName::Dev,
49 MockEnvironmentName::Test,
50 MockEnvironmentName::Prod,
51 ]
52 }
53
54 pub fn next(&self) -> Option<Self> {
56 match self {
57 MockEnvironmentName::Dev => Some(MockEnvironmentName::Test),
58 MockEnvironmentName::Test => Some(MockEnvironmentName::Prod),
59 MockEnvironmentName::Prod => None,
60 }
61 }
62
63 pub fn previous(&self) -> Option<Self> {
65 match self {
66 MockEnvironmentName::Dev => None,
67 MockEnvironmentName::Test => Some(MockEnvironmentName::Dev),
68 MockEnvironmentName::Prod => Some(MockEnvironmentName::Test),
69 }
70 }
71}
72
73impl std::fmt::Display for MockEnvironmentName {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{}", self.as_str())
76 }
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
81#[serde(rename_all = "lowercase")]
82pub enum PromotionEntityType {
83 Scenario,
85 Persona,
87 Config,
89}
90
91impl std::fmt::Display for PromotionEntityType {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 match self {
94 PromotionEntityType::Scenario => write!(f, "scenario"),
95 PromotionEntityType::Persona => write!(f, "persona"),
96 PromotionEntityType::Config => write!(f, "config"),
97 }
98 }
99}
100
101#[allow(clippy::too_many_arguments)]
106#[async_trait::async_trait]
107pub trait PromotionService: Send + Sync {
108 async fn promote_entity(
110 &self,
111 workspace_id: uuid::Uuid,
112 entity_type: PromotionEntityType,
113 entity_id: String,
114 entity_version: Option<String>,
115 from_environment: MockEnvironmentName,
116 to_environment: MockEnvironmentName,
117 promoted_by: uuid::Uuid,
118 comments: Option<String>,
119 ) -> crate::Result<uuid::Uuid>;
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
124#[serde(rename_all = "lowercase")]
125pub enum PromotionStatus {
126 Pending,
128 Approved,
130 Rejected,
132 Completed,
134 Failed,
136}
137
138impl std::fmt::Display for PromotionStatus {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 match self {
141 PromotionStatus::Pending => write!(f, "pending"),
142 PromotionStatus::Approved => write!(f, "approved"),
143 PromotionStatus::Rejected => write!(f, "rejected"),
144 PromotionStatus::Completed => write!(f, "completed"),
145 PromotionStatus::Failed => write!(f, "failed"),
146 }
147 }
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct PromotionRequest {
153 pub entity_type: PromotionEntityType,
155 pub entity_id: String,
157 pub entity_version: Option<String>,
159 pub workspace_id: String,
161 pub from_environment: MockEnvironmentName,
163 pub to_environment: MockEnvironmentName,
165 pub requires_approval: bool,
167 pub approval_required_reason: Option<String>,
169 pub comments: Option<String>,
171 #[serde(default)]
173 pub metadata: std::collections::HashMap<String, serde_json::Value>,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct PromotionHistory {
179 pub entity_type: PromotionEntityType,
181 pub entity_id: String,
183 pub workspace_id: String,
185 pub promotions: Vec<PromotionHistoryEntry>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct PromotionHistoryEntry {
192 pub promotion_id: String,
194 pub entity_type: PromotionEntityType,
196 pub entity_id: String,
198 pub entity_version: Option<String>,
200 pub from_environment: MockEnvironmentName,
202 pub to_environment: MockEnvironmentName,
204 pub promoted_by: String,
206 pub approved_by: Option<String>,
208 pub status: PromotionStatus,
210 pub timestamp: chrono::DateTime<chrono::Utc>,
212 pub comments: Option<String>,
214 pub pr_url: Option<String>,
216 #[serde(default)]
218 pub metadata: std::collections::HashMap<String, serde_json::Value>,
219}