1#![forbid(unsafe_code)]
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7use gitlab::{Variable, VariableType};
8
9pub mod cli;
10pub mod gitlab;
11
12pub const APP: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
14
15pub const APP_UA: &str = concat!(
17 env!("CARGO_PKG_NAME"),
18 "/",
19 env!("CARGO_PKG_VERSION"),
20 " (",
21 env!("CARGO_PKG_REPOSITORY"),
22 ")",
23);
24
25pub type Variables = BTreeMap<VariableKey, VariableValue>;
29
30#[derive(Debug, Default, Serialize, Deserialize)]
32pub struct State {
33 #[serde(default)]
35 pub defaults: Settings,
36
37 #[serde(default)]
39 pub variables: Variables,
40
41 #[serde(default)]
43 pub environments: BTreeMap<String, Variables>,
44}
45
46#[derive(Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
48pub struct Settings {
49 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub masked: Option<bool>,
52
53 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub protected: Option<bool>,
56
57 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub raw: Option<bool>,
60}
61
62impl From<State> for Vec<Variable> {
63 fn from(state: State) -> Self {
64 let mut variables = Vec::new();
65
66 for (key, v) in state.variables {
67 let var = into_variable(key.into(), String::from("*"), v, &state.defaults);
68 variables.push(var);
69 }
70
71 for (env, vars) in state.environments {
72 for (key, v) in vars {
73 let var = into_variable(key.into(), env.clone(), v, &state.defaults);
74 variables.push(var);
75 }
76 }
77 variables
78 }
79}
80
81impl From<Vec<gitlab::Variable>> for State {
82 fn from(variables: Vec<gitlab::Variable>) -> Self {
83 let mut s = Self::default();
84 for v in variables {
85 let env = v.environment_scope.clone();
86 let key = VariableKey(v.key.clone());
87 let value = VariableValue::from(v);
88
89 match env.as_str() {
90 "*" => {
91 s.variables.insert(key, value);
92 }
93 _ => {
94 s.environments.entry(env).or_default().insert(key, value);
95 }
96 }
97 }
98 s
99 }
100}
101
102fn into_variable(
103 key: String,
104 environment_scope: String,
105 value: VariableValue,
106 defaults: &Settings,
107) -> Variable {
108 let VariableValue {
109 value,
110 description,
111 settings: Settings {
112 masked,
113 protected,
114 raw,
115 },
116 variable_type,
117 } = value;
118
119 let masked = masked.unwrap_or(defaults.masked.unwrap_or(false));
121 let protected = protected.unwrap_or(defaults.protected.unwrap_or(false));
122 let raw = raw.unwrap_or(defaults.raw.unwrap_or(false));
123
124 Variable {
125 key,
126 value,
127 description,
128 environment_scope,
129 masked,
130 protected,
131 raw,
132 variable_type,
133 }
134}
135
136#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
144pub struct VariableKey(String);
145
146impl From<VariableKey> for String {
147 fn from(key: VariableKey) -> Self {
148 key.0
149 }
150}
151
152#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
154pub struct VariableValue {
155 pub value: String,
164
165 #[serde(skip_serializing_if = "Option::is_none")]
167 pub description: Option<String>,
168
169 #[serde(
170 rename = "type",
171 default,
172 skip_serializing_if = "VariableType::is_default"
173 )]
174 pub variable_type: VariableType,
175
176 #[serde(flatten)]
177 pub settings: Settings,
178}
179
180impl From<gitlab::Variable> for VariableValue {
181 fn from(value: gitlab::Variable) -> Self {
182 let gitlab::Variable {
183 key: _,
184 value,
185 description,
186 environment_scope: _,
187 masked,
188 protected,
189 raw,
190 variable_type,
191 } = value;
192
193 Self {
194 value,
195 description,
196 settings: Settings {
197 masked: Some(masked),
198 protected: Some(protected),
199 raw: Some(raw),
200 },
201 variable_type,
202 }
203 }
204}