Skip to main content

zixcel_github/
action.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
4pub struct PermissionRequirement {
5    pub resource: &'static str,
6    pub operation: &'static str,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(tag = "state", rename_all = "kebab-case", deny_unknown_fields)]
11pub enum GitHubRemoteExpectation {
12    Absent,
13    Exact { commit_sha256: String },
14}
15
16#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(tag = "type", rename_all = "kebab-case", deny_unknown_fields)]
18pub enum GitHubAction {
19    ObserveRepositoryMetadata,
20    ListIssues {
21        maximum_items: u16,
22    },
23    ListPullRequests {
24        maximum_items: u16,
25    },
26    ListReleases {
27        maximum_items: u16,
28    },
29    ListWorkflowRuns {
30        maximum_items: u16,
31    },
32    ListWorkflowArtifacts {
33        workflow_run_id: String,
34        maximum_items: u16,
35    },
36    DownloadWorkflowArtifact {
37        workflow_run_id: String,
38        artifact_id: String,
39        expected_digest_sha256: Option<String>,
40    },
41    CreatePrivateRepository {
42        default_branch: String,
43    },
44    PushRepositorySnapshot {
45        snapshot_ref: String,
46        snapshot_digest_sha256: String,
47        expected_remote: GitHubRemoteExpectation,
48    },
49    DeleteRepository {
50        expected_repository_id: String,
51        backup_digest_sha256: String,
52    },
53    CreateIssue {
54        title: String,
55        body_artifact_ref: String,
56    },
57    CreatePullRequest {
58        base: String,
59        head: String,
60        title: String,
61        body_artifact_ref: String,
62    },
63    DispatchWorkflow {
64        workflow_ref: String,
65        git_ref: String,
66        inputs_artifact_ref: Option<String>,
67    },
68}
69
70impl GitHubAction {
71    #[must_use]
72    pub const fn required_permission(&self) -> PermissionRequirement {
73        use GitHubAction::*;
74        match self {
75            ObserveRepositoryMetadata => {
76                permission("github-repository-metadata", "inspect-metadata")
77            }
78            ListIssues { .. } => permission("github-issue-observation", "list-records"),
79            ListPullRequests { .. } => {
80                permission("github-pull-request-observation", "list-records")
81            }
82            ListReleases { .. } => permission("github-release-observation", "list-records"),
83            ListWorkflowRuns { .. } => {
84                permission("github-workflow-run-observation", "list-records")
85            }
86            ListWorkflowArtifacts { .. } => {
87                permission("github-actions-artifact-observation", "list-records")
88            }
89            DownloadWorkflowArtifact { .. } => {
90                permission("github-actions-artifact", "download-artifact")
91            }
92            CreatePrivateRepository { .. } => {
93                permission("github-private-repository", "create-private-resource")
94            }
95            PushRepositorySnapshot { .. } => {
96                permission("github-repository-content", "publish-artifact")
97            }
98            DeleteRepository { .. } => {
99                permission("github-repository-administration", "delete-resource")
100            }
101            CreateIssue { .. } => permission("github-issue-creation", "create-work-item"),
102            CreatePullRequest { .. } => {
103                permission("github-pull-request-creation", "create-review-request")
104            }
105            DispatchWorkflow { .. } => permission("github-workflow", "dispatch-operation"),
106        }
107    }
108}
109
110const fn permission(resource: &'static str, operation: &'static str) -> PermissionRequirement {
111    PermissionRequirement {
112        resource,
113        operation,
114    }
115}
116
117impl GitHubAction {
118    pub fn kind(&self) -> &'static str {
119        match self {
120            Self::ObserveRepositoryMetadata => "observe-repository-metadata",
121            Self::ListIssues { .. } => "list-issues",
122            Self::ListPullRequests { .. } => "list-pull-requests",
123            Self::ListReleases { .. } => "list-releases",
124            Self::ListWorkflowRuns { .. } => "list-workflow-runs",
125            Self::ListWorkflowArtifacts { .. } => "list-workflow-artifacts",
126            Self::DownloadWorkflowArtifact { .. } => "download-workflow-artifact",
127            Self::CreatePrivateRepository { .. } => "create-private-repository",
128            Self::PushRepositorySnapshot { .. } => "push-repository-snapshot",
129            Self::DeleteRepository { .. } => "delete-repository",
130            Self::CreateIssue { .. } => "create-issue",
131            Self::CreatePullRequest { .. } => "create-pull-request",
132            Self::DispatchWorkflow { .. } => "dispatch-workflow",
133        }
134    }
135    pub fn is_read_only(&self) -> bool {
136        matches!(
137            self,
138            Self::ObserveRepositoryMetadata
139                | Self::ListIssues { .. }
140                | Self::ListPullRequests { .. }
141                | Self::ListReleases { .. }
142                | Self::ListWorkflowRuns { .. }
143                | Self::ListWorkflowArtifacts { .. }
144                | Self::DownloadWorkflowArtifact { .. }
145        )
146    }
147}