Skip to main content

ephemeris_forge_github/api/model/
environments.rs

1use facet::Facet;
2
3use crate::{
4    BranchPolicyType, DeploymentBranchPolicy, EnvironmentReviewer, EnvironmentReviewerType,
5};
6
7/// A branch policy as GitHub reports it.
8#[derive(Clone, Debug, Eq, Facet, PartialEq)]
9pub struct BranchPolicy {
10    /// The id GitHub gave the policy.
11    pub id: u64,
12    /// The name pattern.
13    pub name: String,
14    /// Whether the pattern matches branches or tags. GitHub omits it for
15    /// branch policies that predate tag policies.
16    #[facet(rename = "type", default = BranchPolicyType::Branch)]
17    pub kind: BranchPolicyType,
18}
19
20/// A deployment environment, with its protection rules in the shape of the
21/// configuration.
22#[derive(Clone, Debug, Eq, Facet, PartialEq)]
23pub struct Environment {
24    /// The environment's name.
25    pub name: String,
26    /// Minutes to wait before a deployment starts.
27    #[facet(default)]
28    pub wait_timer: u32,
29    /// Whether the person who started a deployment cannot approve it.
30    #[facet(default)]
31    pub prevent_self_review: bool,
32    /// The users and teams that approve deployments.
33    #[facet(default)]
34    pub reviewers: Vec<EnvironmentReviewer>,
35    /// Which branches may deploy. Null allows every branch.
36    #[facet(default)]
37    pub deployment_branch_policy: Option<DeploymentBranchPolicy>,
38    /// The branch policies. Empty unless custom branch policies are on.
39    #[facet(default)]
40    pub branch_policies: Vec<BranchPolicy>,
41    /// The types of protection rules this model does not know.
42    #[facet(default)]
43    pub unknown_rules: Vec<String>,
44}
45
46#[derive(Facet)]
47pub(crate) struct EnvironmentPage {
48    #[facet(default)]
49    pub(crate) environments: Vec<EnvironmentResponse>,
50}
51
52#[derive(Facet)]
53pub(crate) struct BranchPolicyPage {
54    #[facet(default)]
55    pub(crate) branch_policies: Vec<BranchPolicy>,
56}
57
58#[derive(Facet)]
59pub(crate) struct EnvironmentResponse {
60    name: String,
61    #[facet(default)]
62    protection_rules: Vec<RuleResponse>,
63    #[facet(default)]
64    deployment_branch_policy: Option<DeploymentBranchPolicy>,
65}
66
67#[derive(Facet)]
68struct RuleResponse {
69    #[facet(rename = "type")]
70    kind: String,
71    #[facet(default)]
72    wait_timer: Option<u32>,
73    #[facet(default)]
74    prevent_self_review: Option<bool>,
75    #[facet(default)]
76    reviewers: Vec<ReviewerResponse>,
77}
78
79#[derive(Facet)]
80struct ReviewerResponse {
81    #[facet(rename = "type")]
82    kind: EnvironmentReviewerType,
83    reviewer: ReviewerId,
84}
85
86#[derive(Facet)]
87struct ReviewerId {
88    id: u64,
89}
90
91impl From<EnvironmentResponse> for Environment {
92    fn from(response: EnvironmentResponse) -> Self {
93        let mut environment = Self {
94            name: response.name,
95            wait_timer: 0,
96            prevent_self_review: false,
97            reviewers: Vec::new(),
98            deployment_branch_policy: response.deployment_branch_policy,
99            branch_policies: Vec::new(),
100            unknown_rules: Vec::new(),
101        };
102        for rule in response.protection_rules {
103            match rule.kind.as_str() {
104                "wait_timer" => environment.wait_timer = rule.wait_timer.unwrap_or(0),
105                "required_reviewers" => {
106                    environment.prevent_self_review = rule.prevent_self_review.unwrap_or(false);
107                    environment.reviewers = rule
108                        .reviewers
109                        .into_iter()
110                        .map(|reviewer| EnvironmentReviewer {
111                            kind: reviewer.kind,
112                            id: reviewer.reviewer.id,
113                        })
114                        .collect();
115                }
116                "branch_policy" => {}
117                _ => environment.unknown_rules.push(rule.kind),
118            }
119        }
120        environment
121    }
122}