gitlab/api/projects/releases/links/
create.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7use crate::api::common::{self, NameOrId};
8use crate::api::endpoint_prelude::*;
9use derive_builder::Builder;
10
11use super::LinkType;
12
13/// Create a link to an asset for a release.
14#[derive(Debug, Builder, Clone)]
15#[builder(setter(strip_option))]
16pub struct CreateReleaseLink<'a> {
17    /// The project to query for the packages.
18    #[builder(setter(into))]
19    project: NameOrId<'a>,
20
21    /// The tag associated with the release.
22    #[builder(setter(into))]
23    tag_name: Cow<'a, str>,
24
25    /// The name of the link.
26    ///
27    /// Link names must be unique in the release.
28    #[builder(setter(into))]
29    name: Cow<'a, str>,
30
31    /// The URL of the link.
32    ///
33    /// Link URLs must be unique in the release.
34    #[builder(setter(into))]
35    url: Cow<'a, str>,
36
37    /// Optional path for a direct asset link.
38    #[builder(setter(into), default)]
39    direct_asset_path: Option<Cow<'a, str>>,
40
41    /// The type of the link: other, runbook, image, package.
42    ///
43    /// Defaults to other.
44    #[builder(setter(into), default)]
45    link_type: Option<LinkType>,
46}
47
48impl<'a> CreateReleaseLink<'a> {
49    /// Create a builder for the endpoint.
50    pub fn builder() -> CreateReleaseLinkBuilder<'a> {
51        CreateReleaseLinkBuilder::default()
52    }
53}
54
55impl Endpoint for CreateReleaseLink<'_> {
56    fn method(&self) -> Method {
57        Method::POST
58    }
59
60    fn endpoint(&self) -> Cow<'static, str> {
61        format!(
62            "projects/{}/releases/{}/assets/links",
63            self.project,
64            common::path_escaped(self.tag_name.as_ref()),
65        )
66        .into()
67    }
68
69    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
70        let mut params = FormParams::default();
71
72        params
73            .push("name", &self.name)
74            .push("url", &self.url)
75            .push_opt("direct_asset_path", self.direct_asset_path.as_ref())
76            .push_opt("link_type", self.link_type);
77
78        params.into_body()
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use http::Method;
85
86    use crate::{
87        api::{
88            self,
89            projects::releases::links::{CreateReleaseLinkBuilderError, LinkType},
90            Query,
91        },
92        test::client::{ExpectedUrl, SingleTestClient},
93    };
94
95    use super::CreateReleaseLink;
96
97    #[test]
98    fn project_is_needed() {
99        let err = CreateReleaseLink::builder()
100            .tag_name("1.2.3")
101            .name("test")
102            .url("test.com/file")
103            .build()
104            .unwrap_err();
105
106        crate::test::assert_missing_field!(err, CreateReleaseLinkBuilderError, "project");
107    }
108
109    #[test]
110    fn tag_name_is_needed() {
111        let err = CreateReleaseLink::builder()
112            .project(1)
113            .name("test")
114            .url("test.com/file")
115            .build()
116            .unwrap_err();
117
118        crate::test::assert_missing_field!(err, CreateReleaseLinkBuilderError, "tag_name");
119    }
120
121    #[test]
122    fn name_is_needed() {
123        let err = CreateReleaseLink::builder()
124            .project(1)
125            .tag_name("1.2.3")
126            .url("test.com/file")
127            .build()
128            .unwrap_err();
129
130        crate::test::assert_missing_field!(err, CreateReleaseLinkBuilderError, "name");
131    }
132
133    #[test]
134    fn url_is_needed() {
135        let err = CreateReleaseLink::builder()
136            .project(1)
137            .tag_name("1.2.3")
138            .name("test")
139            .build()
140            .unwrap_err();
141
142        crate::test::assert_missing_field!(err, CreateReleaseLinkBuilderError, "url");
143    }
144
145    #[test]
146    fn required_parameter_are_sufficient() {
147        CreateReleaseLink::builder()
148            .project(1)
149            .tag_name("1.2.3")
150            .name("test")
151            .url("test.com/file")
152            .build()
153            .unwrap();
154    }
155
156    #[test]
157    fn endpoint() {
158        let endpoint = ExpectedUrl::builder()
159            .method(Method::POST)
160            .endpoint("projects/1337/releases/1.2.3%2001/assets/links")
161            .body_str(concat!("name=test", "&url=test.com%2Ffile"))
162            .content_type("application/x-www-form-urlencoded")
163            .build()
164            .unwrap();
165        let client = SingleTestClient::new_raw(endpoint, "");
166
167        let endpoint = CreateReleaseLink::builder()
168            .project(1337)
169            .tag_name("1.2.3 01")
170            .name("test")
171            .url("test.com/file")
172            .build()
173            .unwrap();
174        api::ignore(endpoint).query(&client).unwrap();
175    }
176
177    #[test]
178    fn endpoint_direct_asset_path() {
179        let endpoint = ExpectedUrl::builder()
180            .method(Method::POST)
181            .endpoint("projects/1337/releases/1.2.3%2001/assets/links")
182            .body_str(concat!(
183                "name=test",
184                "&url=test.com%2Ffile",
185                "&direct_asset_path=path%2Fto%2Ffile",
186            ))
187            .content_type("application/x-www-form-urlencoded")
188            .build()
189            .unwrap();
190        let client = SingleTestClient::new_raw(endpoint, "");
191
192        let endpoint = CreateReleaseLink::builder()
193            .project(1337)
194            .tag_name("1.2.3 01")
195            .name("test")
196            .url("test.com/file")
197            .direct_asset_path("path/to/file")
198            .build()
199            .unwrap();
200        api::ignore(endpoint).query(&client).unwrap();
201    }
202
203    #[test]
204    fn endpoint_link_type() {
205        let endpoint = ExpectedUrl::builder()
206            .method(Method::POST)
207            .endpoint("projects/1337/releases/1.2.3%2001/assets/links")
208            .body_str(concat!(
209                "name=test",
210                "&url=test.com%2Ffile",
211                "&link_type=other",
212            ))
213            .content_type("application/x-www-form-urlencoded")
214            .build()
215            .unwrap();
216        let client = SingleTestClient::new_raw(endpoint, "");
217
218        let endpoint = CreateReleaseLink::builder()
219            .project(1337)
220            .tag_name("1.2.3 01")
221            .name("test")
222            .url("test.com/file")
223            .link_type(LinkType::Other)
224            .build()
225            .unwrap();
226        api::ignore(endpoint).query(&client).unwrap();
227    }
228}