gitlab/api/projects/pipelines/
create.rs1use derive_builder::Builder;
8
9use crate::api::common::NameOrId;
10use crate::api::endpoint_prelude::*;
11
12#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
14#[non_exhaustive]
15pub enum PipelineVariableType {
16 #[default]
20 EnvVar,
21 File,
26}
27
28impl PipelineVariableType {
29 fn as_str(self) -> &'static str {
31 match self {
32 PipelineVariableType::EnvVar => "env_var",
33 PipelineVariableType::File => "file",
34 }
35 }
36}
37
38#[derive(Debug, Clone, Builder)]
40pub struct PipelineVariable<'a> {
41 #[builder(setter(into))]
43 pub key: Cow<'a, str>,
44 #[builder(setter(into))]
46 pub value: Cow<'a, str>,
47 #[builder(default)]
49 pub variable_type: PipelineVariableType,
50}
51
52impl<'a> PipelineVariable<'a> {
53 pub fn builder() -> PipelineVariableBuilder<'a> {
55 PipelineVariableBuilder::default()
56 }
57}
58
59#[derive(Debug, Builder, Clone)]
61pub struct CreatePipeline<'a> {
62 #[builder(setter(into))]
64 project: NameOrId<'a>,
65
66 #[builder(setter(into))]
68 ref_: Cow<'a, str>,
69
70 #[builder(setter(name = "_variables"), default, private)]
72 variables: Vec<PipelineVariable<'a>>,
73}
74
75impl<'a> CreatePipeline<'a> {
76 pub fn builder() -> CreatePipelineBuilder<'a> {
78 CreatePipelineBuilder::default()
79 }
80}
81
82impl<'a> CreatePipelineBuilder<'a> {
83 pub fn variable(&mut self, variable: PipelineVariable<'a>) -> &mut Self {
85 self.variables.get_or_insert_with(Vec::new).push(variable);
86 self
87 }
88
89 pub fn variables<I, V>(&mut self, iter: I) -> &mut Self
91 where
92 I: Iterator<Item = V>,
93 V: Into<PipelineVariable<'a>>,
94 {
95 self.variables
96 .get_or_insert_with(Vec::new)
97 .extend(iter.map(Into::into));
98 self
99 }
100}
101
102impl Endpoint for CreatePipeline<'_> {
103 fn method(&self) -> Method {
104 Method::POST
105 }
106
107 fn endpoint(&self) -> Cow<'static, str> {
108 format!("projects/{}/pipeline", self.project).into()
109 }
110
111 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
112 let mut params = FormParams::default();
113
114 params.push("ref", &self.ref_);
115
116 self.variables.iter().for_each(|variable| {
117 params.extend(
118 [
119 ("variables[][key]", variable.key.as_ref()),
120 ("variables[][value]", variable.value.as_ref()),
121 (
122 "variables[][variable_type]",
123 variable.variable_type.as_str(),
124 ),
125 ]
126 .iter()
127 .cloned(),
128 );
129 });
130
131 params.into_body()
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use http::Method;
138
139 use crate::api::projects::pipelines::{
140 CreatePipeline, CreatePipelineBuilderError, PipelineVariable, PipelineVariableBuilderError,
141 PipelineVariableType,
142 };
143 use crate::api::{self, Query};
144 use crate::test::client::{ExpectedUrl, SingleTestClient};
145
146 #[test]
147 fn pipeline_variable_type_default() {
148 assert_eq!(
149 PipelineVariableType::default(),
150 PipelineVariableType::EnvVar,
151 );
152 }
153
154 #[test]
155 fn pipeline_variable_type_as_str() {
156 let items = &[
157 (PipelineVariableType::EnvVar, "env_var"),
158 (PipelineVariableType::File, "file"),
159 ];
160
161 for (i, s) in items {
162 assert_eq!(i.as_str(), *s);
163 }
164 }
165
166 #[test]
167 fn pipeline_variable_key_and_value_are_necessary() {
168 let err = PipelineVariable::builder().build().unwrap_err();
169 crate::test::assert_missing_field!(err, PipelineVariableBuilderError, "key");
170 }
171
172 #[test]
173 fn pipeline_variable_key_is_necessary() {
174 let err = PipelineVariable::builder()
175 .value("value")
176 .build()
177 .unwrap_err();
178 crate::test::assert_missing_field!(err, PipelineVariableBuilderError, "key");
179 }
180
181 #[test]
182 fn pipeline_variable_value_is_necessary() {
183 let err = PipelineVariable::builder().key("key").build().unwrap_err();
184 crate::test::assert_missing_field!(err, PipelineVariableBuilderError, "value");
185 }
186
187 #[test]
188 fn pipeline_variable_key_and_value_are_sufficient() {
189 PipelineVariable::builder()
190 .key("key")
191 .value("value")
192 .build()
193 .unwrap();
194 }
195
196 #[test]
197 fn project_and_ref_are_needed() {
198 let err = CreatePipeline::builder().build().unwrap_err();
199 crate::test::assert_missing_field!(err, CreatePipelineBuilderError, "project");
200 }
201
202 #[test]
203 fn project_is_needed() {
204 let err = CreatePipeline::builder()
205 .ref_("testref")
206 .build()
207 .unwrap_err();
208 crate::test::assert_missing_field!(err, CreatePipelineBuilderError, "project");
209 }
210
211 #[test]
212 fn ref_is_needed() {
213 let err = CreatePipeline::builder().project(1).build().unwrap_err();
214 crate::test::assert_missing_field!(err, CreatePipelineBuilderError, "ref_");
215 }
216
217 #[test]
218 fn project_and_ref_are_sufficient() {
219 CreatePipeline::builder()
220 .project(1)
221 .ref_("testref")
222 .build()
223 .unwrap();
224 }
225
226 #[test]
227 fn endpoint() {
228 let endpoint = ExpectedUrl::builder()
229 .method(Method::POST)
230 .endpoint("projects/simple%2Fproject/pipeline")
231 .content_type("application/x-www-form-urlencoded")
232 .body_str("ref=master")
233 .build()
234 .unwrap();
235 let client = SingleTestClient::new_raw(endpoint, "");
236
237 let endpoint = CreatePipeline::builder()
238 .project("simple/project")
239 .ref_("master")
240 .build()
241 .unwrap();
242 api::ignore(endpoint).query(&client).unwrap();
243 }
244
245 #[test]
246 fn endpoint_pipeline_variables() {
247 let endpoint = ExpectedUrl::builder()
248 .method(Method::POST)
249 .endpoint("projects/1/pipeline")
250 .content_type("application/x-www-form-urlencoded")
251 .body_str(concat!(
252 "ref=master",
253 "&variables%5B%5D%5Bkey%5D=key",
254 "&variables%5B%5D%5Bvalue%5D=value",
255 "&variables%5B%5D%5Bvariable_type%5D=env_var",
256 "&variables%5B%5D%5Bkey%5D=file",
257 "&variables%5B%5D%5Bvalue%5D=contents",
258 "&variables%5B%5D%5Bvariable_type%5D=file",
259 ))
260 .build()
261 .unwrap();
262 let client = SingleTestClient::new_raw(endpoint, "");
263
264 let endpoint = CreatePipeline::builder()
265 .project(1)
266 .ref_("master")
267 .variable(
268 PipelineVariable::builder()
269 .key("key")
270 .value("value")
271 .build()
272 .unwrap(),
273 )
274 .variables(
275 [PipelineVariable::builder()
276 .key("file")
277 .value("contents")
278 .variable_type(PipelineVariableType::File)
279 .build()
280 .unwrap()]
281 .iter()
282 .cloned(),
283 )
284 .build()
285 .unwrap();
286 api::ignore(endpoint).query(&client).unwrap();
287 }
288}