ephemeris_forge/
release.rs1use facet::Facet;
4use reqwest::Method;
5
6use crate::codec::encode;
7use crate::repo::RepoRef;
8use crate::segment::path_segment;
9use crate::transport::{Http, TransportError};
10
11#[derive(Debug, Facet)]
13pub struct PullRequestCreate<'a> {
14 pub title: &'a str,
16 pub body: &'a str,
18 pub head: &'a str,
20 pub base: &'a str,
22}
23
24#[derive(Debug, Facet)]
26struct PullRequestUpdate<'a> {
27 title: &'a str,
28 body: &'a str,
29}
30
31impl PullRequestCreate<'_> {
32 pub async fn ensure(
38 &self,
39 http: &Http,
40 repository: &RepoRef,
41 current: Option<u64>,
42 ) -> Result<(), TransportError> {
43 let (method, path, body) = current.map_or_else(
44 || (Method::POST, repository.path("pulls"), encode(self)),
45 |number| {
46 let update = PullRequestUpdate {
47 title: self.title,
48 body: self.body,
49 };
50 (
51 Method::PATCH,
52 repository.path(&format!("pulls/{number}")),
53 encode(&update),
54 )
55 },
56 );
57 http.send(method, &path, Some(&body)).await?;
58 Ok(())
59 }
60}
61
62#[derive(Debug, Facet)]
64pub struct DraftRelease<'a> {
65 pub tag_name: &'a str,
67 pub target_commitish: &'a str,
69 pub name: &'a str,
71 pub body: &'a str,
73 pub draft: bool,
75 pub prerelease: bool,
77}
78
79impl<'a> DraftRelease<'a> {
80 #[must_use]
82 pub const fn new(tag: &'a str, target_commit: &'a str, title: &'a str, notes: &'a str) -> Self {
83 Self {
84 tag_name: tag,
85 target_commitish: target_commit,
86 name: title,
87 body: notes,
88 draft: true,
89 prerelease: false,
90 }
91 }
92
93 pub async fn create(&self, http: &Http, repository: &RepoRef) -> Result<u64, TransportError> {
98 let path = repository.path("releases");
99 let release: ReleaseWire = http.json(Method::POST, &path, Some(&encode(self))).await?;
100 Ok(release.id)
101 }
102}
103
104#[derive(Clone, Copy, Debug, Facet)]
106pub struct PublishRelease {
107 pub draft: bool,
109}
110
111#[derive(Debug, Facet)]
113pub struct ReleaseWire {
114 pub id: u64,
116 pub draft: bool,
118 #[facet(default)]
120 pub upload_url: String,
121}
122
123impl ReleaseWire {
124 pub async fn by_tag(
129 http: &Http,
130 repository: &RepoRef,
131 tag: &str,
132 ) -> Result<Option<Self>, TransportError> {
133 let path = repository.path(&format!("releases/tags/{}", path_segment(tag)));
134 http.json_optional(Method::GET, &path, None).await
135 }
136}
137
138#[derive(Debug, Facet)]
140pub struct AssetWire {
141 pub id: u64,
143 pub name: String,
145 pub size: u64,
147 #[facet(default)]
149 pub digest: Option<String>,
150 #[facet(default)]
152 pub browser_download_url: String,
153}
154
155#[derive(Debug, Facet)]
157pub struct RefObject {
158 pub sha: String,
160 #[facet(rename = "type", default)]
162 pub kind: String,
163}
164
165#[derive(Debug, Facet)]
167pub struct ObjectWire {
168 pub object: RefObject,
170}
171
172impl RefObject {
173 pub async fn peel(self, http: &Http, repository: &RepoRef) -> Result<String, TransportError> {
178 if self.kind != "tag" {
179 return Ok(self.sha);
180 }
181 let path = repository.path(&format!("git/tags/{}", self.sha));
182 let annotated: ObjectWire = http.json(Method::GET, &path, None).await?;
183 Ok(annotated.object.sha)
184 }
185}