Skip to main content

ephemeris_forge_github/
release.rs

1//! Typed GitHub pull-request, ref, and release operations.
2
3use ephemeris_forge::RepoRef;
4use ephemeris_release::{
5    ForgeProposal, ForgeRelease as ReleaseForge, ForgeTags, RemoteAsset, RemoteRelease,
6};
7
8use crate::api::{ForgeError, HttpApi};
9
10/// GitHub release and pull-request operations for the release CLI.
11#[derive(Debug)]
12pub struct Release {
13    api: HttpApi,
14    repository: RepoRef,
15}
16
17impl Release {
18    /// Bind an authenticated API and repository.
19    #[must_use]
20    pub const fn new(api: HttpApi, repository: RepoRef) -> Self {
21        Self { api, repository }
22    }
23}
24
25impl ForgeProposal for Release {
26    type Error = ForgeError;
27
28    async fn proposal_body(&self, head: &str, base: &str) -> Result<Option<String>, Self::Error> {
29        self.api
30            .open_pull_request_body(&self.repository, head, base)
31            .await
32    }
33
34    async fn ensure_proposal(
35        &self,
36        head: &str,
37        base: &str,
38        title: &str,
39        body: &str,
40    ) -> Result<(), Self::Error> {
41        self.api
42            .ensure_pull_request(&self.repository, head, base, title, body)
43            .await
44    }
45}
46
47impl ForgeTags for Release {
48    type Error = ForgeError;
49
50    async fn tag_commit(&self, tag: &str) -> Result<Option<String>, Self::Error> {
51        self.api.tag_commit(&self.repository, tag).await
52    }
53}
54
55impl ReleaseForge for Release {
56    type Error = ForgeError;
57    async fn delete_asset(&self, _release_id: u64, asset_id: u64) -> Result<(), Self::Error> {
58        self.api.delete_asset(&self.repository, asset_id).await
59    }
60    async fn release_by_tag(&self, tag: &str) -> Result<Option<RemoteRelease>, Self::Error> {
61        self.api.release_by_tag(&self.repository, tag).await
62    }
63    async fn create_draft(
64        &self,
65        tag: &str,
66        target_commit: &str,
67        title: &str,
68        notes: &str,
69    ) -> Result<u64, Self::Error> {
70        self.api
71            .create_draft_release(&self.repository, tag, target_commit, title, notes)
72            .await
73    }
74    async fn assets(&self, release_id: u64) -> Result<Vec<RemoteAsset>, Self::Error> {
75        self.api.assets(&self.repository, release_id).await
76    }
77    async fn upload(
78        &self,
79        release_id: u64,
80        filename: &str,
81        bytes: &[u8],
82    ) -> Result<(), Self::Error> {
83        self.api
84            .upload_asset(&self.repository, release_id, filename, bytes.to_vec())
85            .await
86    }
87    async fn asset_bytes(&self, asset: &RemoteAsset) -> Result<Vec<u8>, Self::Error> {
88        self.api.download_asset(&self.repository, asset).await
89    }
90    async fn publish(&self, release_id: u64) -> Result<(), Self::Error> {
91        self.api.publish_release(&self.repository, release_id).await
92    }
93}