gitlab_manager/models/
variable.rs

1//! CI/CD variable-related data models.
2
3use serde::{Deserialize, Serialize};
4
5/// A CI/CD variable in a GitLab project.
6///
7/// Variables are used to store configuration and secrets
8/// that can be used in CI/CD pipelines.
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10pub struct Variable {
11    /// Variable name/key (alphanumeric and underscore only)
12    pub key: String,
13
14    /// Variable value
15    pub value: String,
16
17    /// Type of variable (env_var or file)
18    pub variable_type: VariableType,
19
20    /// Whether the variable is protected (only available in protected branches/tags)
21    pub protected: bool,
22
23    /// Whether the variable value should be masked in job logs
24    pub masked: bool,
25
26    /// Whether the variable value should be hidden in the UI
27    #[serde(default)]
28    pub hidden: bool,
29
30    /// Whether to disable variable expansion
31    #[serde(default = "default_raw")]
32    pub raw: bool,
33
34    /// Environment scope for the variable (e.g., "production", "*" for all)
35    #[serde(default = "default_environment_scope")]
36    pub environment_scope: String,
37
38    /// Optional description of the variable
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub description: Option<String>,
41}
42
43fn default_raw() -> bool {
44    true
45}
46
47fn default_environment_scope() -> String {
48    "*".to_string()
49}
50
51/// Type of CI/CD variable.
52#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
53#[serde(rename_all = "snake_case")]
54pub enum VariableType {
55    /// Environment variable (default)
56    EnvVar,
57    /// File variable (value written to temp file, path in env var)
58    File,
59}
60
61impl Default for VariableType {
62    fn default() -> Self {
63        Self::EnvVar
64    }
65}
66
67/// Options for creating or updating a CI/CD variable.
68#[derive(Debug, Clone, Default)]
69pub struct VariableOptions {
70    /// Whether the variable is protected
71    pub protected: bool,
72
73    /// Whether to mask the value in logs
74    pub masked: bool,
75
76    /// Whether to disable variable expansion
77    pub raw: bool,
78
79    /// Type of variable
80    pub variable_type: VariableType,
81
82    /// Environment scope
83    pub environment_scope: Option<String>,
84
85    /// Variable description
86    pub description: Option<String>,
87}
88
89impl VariableOptions {
90    /// Create a new VariableOptions with default values.
91    pub fn new() -> Self {
92        Self {
93            protected: false,
94            masked: false,
95            raw: true,
96            variable_type: VariableType::EnvVar,
97            environment_scope: None,
98            description: None,
99        }
100    }
101
102    /// Set the variable as protected.
103    pub fn protected(mut self, protected: bool) -> Self {
104        self.protected = protected;
105        self
106    }
107
108    /// Set whether to mask the value.
109    pub fn masked(mut self, masked: bool) -> Self {
110        self.masked = masked;
111        self
112    }
113
114    /// Set whether to disable variable expansion.
115    pub fn raw(mut self, raw: bool) -> Self {
116        self.raw = raw;
117        self
118    }
119
120    /// Set the variable type.
121    pub fn variable_type(mut self, variable_type: VariableType) -> Self {
122        self.variable_type = variable_type;
123        self
124    }
125
126    /// Set the environment scope.
127    pub fn environment_scope(mut self, scope: impl Into<String>) -> Self {
128        self.environment_scope = Some(scope.into());
129        self
130    }
131
132    /// Set the description.
133    pub fn description(mut self, description: impl Into<String>) -> Self {
134        self.description = Some(description.into());
135        self
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_variable_type_default() {
145        assert_eq!(VariableType::default(), VariableType::EnvVar);
146    }
147
148    #[test]
149    fn test_variable_options_builder() {
150        let opts = VariableOptions::new()
151            .protected(true)
152            .masked(true)
153            .variable_type(VariableType::File)
154            .description("Test variable");
155
156        assert!(opts.protected);
157        assert!(opts.masked);
158        assert_eq!(opts.variable_type, VariableType::File);
159        assert_eq!(opts.description, Some("Test variable".to_string()));
160    }
161}