lmrc_gitlab/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, Default)]
53#[serde(rename_all = "snake_case")]
54pub enum VariableType {
55    /// Environment variable (default)
56    #[default]
57    EnvVar,
58    /// File variable (value written to temp file, path in env var)
59    File,
60}
61
62/// Options for creating or updating a CI/CD variable.
63#[derive(Debug, Clone, Default)]
64pub struct VariableOptions {
65    /// Whether the variable is protected
66    pub protected: bool,
67
68    /// Whether to mask the value in logs
69    pub masked: bool,
70
71    /// Whether to disable variable expansion
72    pub raw: bool,
73
74    /// Type of variable
75    pub variable_type: VariableType,
76
77    /// Environment scope
78    pub environment_scope: Option<String>,
79
80    /// Variable description
81    pub description: Option<String>,
82}
83
84impl VariableOptions {
85    /// Create a new VariableOptions with default values.
86    pub fn new() -> Self {
87        Self {
88            protected: false,
89            masked: false,
90            raw: true,
91            variable_type: VariableType::EnvVar,
92            environment_scope: None,
93            description: None,
94        }
95    }
96
97    /// Set the variable as protected.
98    pub fn protected(mut self, protected: bool) -> Self {
99        self.protected = protected;
100        self
101    }
102
103    /// Set whether to mask the value.
104    pub fn masked(mut self, masked: bool) -> Self {
105        self.masked = masked;
106        self
107    }
108
109    /// Set whether to disable variable expansion.
110    pub fn raw(mut self, raw: bool) -> Self {
111        self.raw = raw;
112        self
113    }
114
115    /// Set the variable type.
116    pub fn variable_type(mut self, variable_type: VariableType) -> Self {
117        self.variable_type = variable_type;
118        self
119    }
120
121    /// Set the environment scope.
122    pub fn environment_scope(mut self, scope: impl Into<String>) -> Self {
123        self.environment_scope = Some(scope.into());
124        self
125    }
126
127    /// Set the description.
128    pub fn description(mut self, description: impl Into<String>) -> Self {
129        self.description = Some(description.into());
130        self
131    }
132}
133
134#[cfg(test)]
135mod tests {
136    use super::*;
137
138    #[test]
139    fn test_variable_type_default() {
140        assert_eq!(VariableType::default(), VariableType::EnvVar);
141    }
142
143    #[test]
144    fn test_variable_options_builder() {
145        let opts = VariableOptions::new()
146            .protected(true)
147            .masked(true)
148            .variable_type(VariableType::File)
149            .description("Test variable");
150
151        assert!(opts.protected);
152        assert!(opts.masked);
153        assert_eq!(opts.variable_type, VariableType::File);
154        assert_eq!(opts.description, Some("Test variable".to_string()));
155    }
156}