ephemeris_forge_github/config/
environments.rs1use std::collections::BTreeMap;
2
3use ephemeris_forge::{Mode, non_empty_name};
4use facet::Facet;
5
6use super::ConfigError;
7
8const MAX_WAIT_TIMER: u32 = 43_200;
9const MAX_REVIEWERS: usize = 6;
10
11non_empty_name! {
12 pub struct EnvironmentName;
14 pub error EmptyEnvironmentName("environment name cannot be empty");
16}
17
18#[derive(Clone, Copy, Debug, Eq, Facet, Ord, PartialEq, PartialOrd)]
20#[repr(u8)]
21pub enum EnvironmentReviewerType {
22 #[facet(rename = "User")]
24 User,
25 #[facet(rename = "Team")]
27 Team,
28}
29
30#[derive(Clone, Copy, Debug, Eq, Facet, Ord, PartialEq, PartialOrd)]
32#[facet(deny_unknown_fields)]
33pub struct EnvironmentReviewer {
34 #[facet(rename = "type")]
36 pub kind: EnvironmentReviewerType,
37 pub id: u64,
39}
40
41#[derive(Clone, Copy, Debug, Eq, Facet, PartialEq)]
43#[facet(deny_unknown_fields)]
44pub struct DeploymentBranchPolicy {
45 pub protected_branches: bool,
47 pub custom_branch_policies: bool,
49}
50
51#[derive(Clone, Copy, Debug, Eq, Facet, Ord, PartialEq, PartialOrd)]
53#[repr(u8)]
54pub enum BranchPolicyType {
55 #[facet(rename = "branch")]
57 Branch,
58 #[facet(rename = "tag")]
60 Tag,
61}
62
63#[derive(Clone, Debug, Eq, Facet, Ord, PartialEq, PartialOrd)]
65#[facet(deny_unknown_fields)]
66pub struct BranchPolicy {
67 pub name: String,
69 #[facet(rename = "type")]
71 pub kind: BranchPolicyType,
72}
73
74#[derive(Clone, Debug, Eq, Facet, PartialEq)]
76#[facet(deny_unknown_fields)]
77pub struct Environment {
78 pub wait_timer: u32,
80 pub prevent_self_review: bool,
82 pub reviewers: Vec<EnvironmentReviewer>,
84 pub deployment_branch_policy: Option<DeploymentBranchPolicy>,
86 pub branch_policies: Vec<BranchPolicy>,
88}
89
90#[derive(Clone, Debug, Eq, Facet, PartialEq)]
92#[facet(deny_unknown_fields)]
93pub struct Environments {
94 pub mode: Mode,
96 pub environments: BTreeMap<EnvironmentName, Environment>,
98}
99
100impl Environment {
101 fn validate(&self, name: &EnvironmentName) -> Result<(), ConfigError> {
102 if self.wait_timer > MAX_WAIT_TIMER {
103 return Err(ConfigError::EnvironmentWaitTimer {
104 environment: name.clone(),
105 minutes: self.wait_timer,
106 });
107 }
108 if self.reviewers.len() > MAX_REVIEWERS {
109 return Err(ConfigError::TooManyEnvironmentReviewers {
110 environment: name.clone(),
111 count: self.reviewers.len(),
112 });
113 }
114 let policy = self.deployment_branch_policy;
115 if policy.is_some_and(|policy| policy.protected_branches && policy.custom_branch_policies) {
116 return Err(ConfigError::ConflictingDeploymentBranchPolicy {
117 environment: name.clone(),
118 });
119 }
120 if !self.branch_policies.is_empty()
121 && !policy.is_some_and(|policy| policy.custom_branch_policies)
122 {
123 return Err(ConfigError::BranchPoliciesWithoutCustom {
124 environment: name.clone(),
125 });
126 }
127 Ok(())
128 }
129}
130
131impl Environments {
132 pub fn validate(&self) -> Result<(), ConfigError> {
137 self.environments
138 .iter()
139 .try_for_each(|(name, environment)| environment.validate(name))
140 }
141}