ephemeris_forge_forgejo/api/model/branch_rules.rs
1use facet::Facet;
2
3use crate::PushAccess;
4
5/// The subset of the `BranchProtection` response the CLI reads.
6///
7/// Open in the same way as [`super::Repository`]. `created_at` is deliberately
8/// not vendored: the response already arrives in the order Forgejo consults the
9/// rules in, so nothing here has to reconstruct it from a timestamp.
10#[derive(Clone, Debug, Default, Facet)]
11pub struct BranchProtection {
12 /// The rule's name.
13 #[facet(default)]
14 pub rule_name: String,
15 /// Whether the protection also applies to repository administrators.
16 pub apply_to_admins: Option<bool>,
17 /// The teams whose approvals count, when the approvals whitelist is on.
18 pub approvals_whitelist_teams: Option<Vec<String>>,
19 /// The users whose approvals count, when the approvals whitelist is on.
20 pub approvals_whitelist_username: Option<Vec<String>>,
21 /// Whether an official code owner review request blocks merging until
22 /// resolved.
23 pub block_on_official_review_requests: Option<bool>,
24 /// Whether merging is blocked while the branch is behind its base.
25 pub block_on_outdated_branch: Option<bool>,
26 /// Whether a requested change blocks merging until it is resolved.
27 pub block_on_rejected_reviews: Option<bool>,
28 /// Whether a new commit dismisses existing approvals.
29 pub dismiss_stale_approvals: Option<bool>,
30 /// Whether only the approvals whitelist counts toward the required
31 /// approvals.
32 pub enable_approvals_whitelist: Option<bool>,
33 /// Whether only the merge whitelist may merge.
34 pub enable_merge_whitelist: Option<bool>,
35 /// Whether direct pushes to the branch are allowed at all.
36 pub enable_push: Option<bool>,
37 /// Whether only the push whitelist may push.
38 pub enable_push_whitelist: Option<bool>,
39 /// Whether status checks must pass before merging.
40 pub enable_status_check: Option<bool>,
41 /// Whether approvals on an outdated commit stop counting.
42 pub ignore_stale_approvals: Option<bool>,
43 /// The teams that may merge, when the merge whitelist is on.
44 pub merge_whitelist_teams: Option<Vec<String>>,
45 /// The users that may merge, when the merge whitelist is on.
46 pub merge_whitelist_usernames: Option<Vec<String>>,
47 /// Semicolon separated glob patterns for files that only whitelisted
48 /// pushers may change.
49 pub protected_file_patterns: Option<String>,
50 /// Whether deploy keys may push, when the push whitelist is on.
51 pub push_whitelist_deploy_keys: Option<bool>,
52 /// The teams that may push, when the push whitelist is on.
53 pub push_whitelist_teams: Option<Vec<String>>,
54 /// The users that may push, when the push whitelist is on.
55 pub push_whitelist_usernames: Option<Vec<String>>,
56 /// Whether every commit on the branch must be signed.
57 pub require_signed_commits: Option<bool>,
58 /// The number of approving reviews required before merging.
59 pub required_approvals: Option<i64>,
60 /// The status check contexts that must report success.
61 pub status_check_contexts: Option<Vec<String>>,
62 /// Semicolon separated glob patterns for files that any pusher may
63 /// change despite the protected patterns.
64 pub unprotected_file_patterns: Option<String>,
65}
66
67impl BranchProtection {
68 /// The push access the two wire flags describe, when Forgejo reported both.
69 #[must_use]
70 pub fn push_access(&self) -> Option<PushAccess> {
71 Some(PushAccess::from_flags(
72 self.enable_push?,
73 self.enable_push_whitelist?,
74 ))
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::BranchProtection;
81
82 #[test]
83 fn unknown_properties_are_ignored() {
84 let raw = r#"{"rule_name": "main", "branch_name": "main", "created_at": "now"}"#;
85 let rule: BranchProtection = facet_json::from_str(raw).expect("parses");
86 assert_eq!(rule.rule_name, "main");
87 assert_eq!(rule.enable_push, None);
88 }
89}