Skip to main content

ephemeris_forge_github/api/model/
actions.rs

1/// The route and wire type of each Actions settings group.
2pub mod routes;
3
4use std::num::NonZeroU32;
5
6use facet::Facet;
7
8use crate::config::actions::{
9    Access, AccessLevel, ActionScope, AllowList, ApprovalPolicy, ArtifactAndLogRetention, Cache,
10    ForkPrContributorApproval, ForkPrWorkflowsPrivateRepos, OidcSubject, Permissions,
11    TokenPermissions, Workflow,
12};
13
14/// GitHub omits `allowed_actions` when Actions is disabled, which reads as the
15/// default of `all`.
16#[derive(Clone, Copy, Debug, Facet)]
17pub struct PermissionsResponse {
18    enabled: bool,
19    #[facet(default)]
20    allowed_actions: Option<ActionScope>,
21    #[facet(default)]
22    sha_pinning_required: bool,
23}
24
25impl From<PermissionsResponse> for Permissions {
26    fn from(response: PermissionsResponse) -> Self {
27        Self {
28            enabled: response.enabled,
29            allowed_actions: response.allowed_actions.unwrap_or(ActionScope::All),
30            sha_pinning_required: response.sha_pinning_required,
31        }
32    }
33}
34
35/// What GitHub answers with for one Actions settings group.
36#[derive(Clone, Debug, Facet)]
37#[expect(clippy::struct_field_names, reason = "the field names are GitHub's")]
38pub struct AllowListResponse {
39    #[facet(default)]
40    github_owned_allowed: bool,
41    #[facet(default)]
42    verified_allowed: bool,
43    #[facet(default)]
44    patterns_allowed: Vec<String>,
45}
46
47impl From<AllowListResponse> for AllowList {
48    fn from(response: AllowListResponse) -> Self {
49        Self {
50            github_owned_allowed: response.github_owned_allowed,
51            verified_allowed: response.verified_allowed,
52            patterns_allowed: response.patterns_allowed,
53        }
54        .normalized()
55    }
56}
57
58/// What GitHub answers with for one Actions settings group.
59#[derive(Clone, Copy, Debug, Facet)]
60pub struct WorkflowResponse {
61    default_workflow_permissions: TokenPermissions,
62    #[facet(default)]
63    can_approve_pull_request_reviews: bool,
64}
65
66impl From<WorkflowResponse> for Workflow {
67    fn from(response: WorkflowResponse) -> Self {
68        Self {
69            default_workflow_permissions: response.default_workflow_permissions,
70            can_approve_pull_request_reviews: response.can_approve_pull_request_reviews,
71        }
72    }
73}
74
75/// What GitHub answers with for one Actions settings group.
76#[derive(Clone, Copy, Debug, Facet)]
77pub struct AccessResponse {
78    access_level: AccessLevel,
79}
80
81impl From<AccessResponse> for Access {
82    fn from(response: AccessResponse) -> Self {
83        Self {
84            access_level: response.access_level,
85        }
86    }
87}
88
89/// What GitHub answers with for one Actions settings group.
90#[derive(Clone, Copy, Debug, Facet)]
91pub struct RetentionResponse {
92    days: NonZeroU32,
93}
94
95impl From<RetentionResponse> for ArtifactAndLogRetention {
96    fn from(response: RetentionResponse) -> Self {
97        Self {
98            days: response.days,
99        }
100    }
101}
102
103/// What GitHub answers with for one Actions settings group.
104#[derive(Clone, Copy, Debug, Facet)]
105pub struct ContributorApprovalResponse {
106    approval_policy: ApprovalPolicy,
107}
108
109impl From<ContributorApprovalResponse> for ForkPrContributorApproval {
110    fn from(response: ContributorApprovalResponse) -> Self {
111        Self {
112            approval_policy: response.approval_policy,
113        }
114    }
115}
116
117/// What GitHub answers with for one Actions settings group.
118#[derive(Clone, Copy, Debug, Facet)]
119#[expect(
120    clippy::struct_excessive_bools,
121    reason = "this mirrors GitHub's response, whose plain bools are the point"
122)]
123pub struct ForkWorkflowsResponse {
124    run_workflows_from_fork_pull_requests: bool,
125    #[facet(default)]
126    send_write_tokens_to_workflows: bool,
127    #[facet(default)]
128    send_secrets_and_variables: bool,
129    #[facet(default)]
130    require_approval_for_fork_pr_workflows: bool,
131}
132
133impl From<ForkWorkflowsResponse> for ForkPrWorkflowsPrivateRepos {
134    fn from(response: ForkWorkflowsResponse) -> Self {
135        Self {
136            run_workflows_from_fork_pull_requests: response.run_workflows_from_fork_pull_requests,
137            send_write_tokens_to_workflows: response.send_write_tokens_to_workflows,
138            send_secrets_and_variables: response.send_secrets_and_variables,
139            require_approval_for_fork_pr_workflows: response.require_approval_for_fork_pr_workflows,
140        }
141    }
142}
143
144/// What GitHub answers with for one Actions settings group.
145#[derive(Clone, Copy, Debug, Facet)]
146pub struct CacheRetentionResponse {
147    pub(crate) max_cache_retention_days: NonZeroU32,
148}
149
150/// What GitHub answers with for one Actions settings group.
151#[derive(Clone, Copy, Debug, Facet)]
152pub struct CacheStorageResponse {
153    pub(crate) max_cache_size_gb: NonZeroU32,
154}
155
156impl Cache {
157    pub(crate) const fn from_responses(
158        retention: CacheRetentionResponse,
159        storage: CacheStorageResponse,
160    ) -> Self {
161        Self {
162            max_cache_retention_days: retention.max_cache_retention_days,
163            max_cache_size_gb: storage.max_cache_size_gb,
164        }
165    }
166}
167
168/// GitHub answers `include_claim_keys` as null while the default subject is in
169/// use.
170#[derive(Clone, Debug, Facet)]
171pub struct OidcSubjectResponse {
172    use_default: bool,
173    #[facet(default)]
174    include_claim_keys: Option<Vec<String>>,
175    #[facet(default)]
176    use_immutable_subject: bool,
177}
178
179impl From<OidcSubjectResponse> for OidcSubject {
180    fn from(response: OidcSubjectResponse) -> Self {
181        Self {
182            use_default: response.use_default,
183            include_claim_keys: response.include_claim_keys.unwrap_or_default(),
184            use_immutable_subject: response.use_immutable_subject,
185        }
186    }
187}