Skip to main content

skipper_core/
config.rs

1use crate::credentials::Credentials;
2
3/// Configuration shared by the resolver and the writer.
4#[derive(Debug, Clone)]
5pub struct SkipperConfig {
6    pub spreadsheet_id: String,
7    pub credentials: Credentials,
8    /// Primary sheet; `None` means the first sheet of the spreadsheet.
9    pub sheet_name: Option<String>,
10    /// Extra read-only sheets merged into the primary (latest date wins).
11    pub reference_sheets: Vec<String>,
12    pub test_id_column: String,
13    pub disabled_until_column: String,
14}
15
16impl SkipperConfig {
17    pub fn new(spreadsheet_id: impl Into<String>, credentials: Credentials) -> Self {
18        SkipperConfig {
19            spreadsheet_id: spreadsheet_id.into(),
20            credentials,
21            sheet_name: None,
22            reference_sheets: Vec::new(),
23            test_id_column: "testId".into(),
24            disabled_until_column: "disabledUntil".into(),
25        }
26    }
27
28    pub fn with_sheet_name(mut self, name: impl Into<String>) -> Self {
29        self.sheet_name = Some(name.into());
30        self
31    }
32
33    pub fn with_reference_sheets<I, S>(mut self, sheets: I) -> Self
34    where
35        I: IntoIterator<Item = S>,
36        S: Into<String>,
37    {
38        self.reference_sheets = sheets.into_iter().map(Into::into).collect();
39        self
40    }
41
42    /// Build a config from the environment:
43    /// `SKIPPER_SPREADSHEET_ID`, credentials from `SKIPPER_CREDENTIALS_FILE`
44    /// (wins) or `GOOGLE_CREDS_B64`, optional `SKIPPER_SHEET_NAME` and
45    /// comma-separated `SKIPPER_REFERENCE_SHEETS`.
46    /// Returns `None` when Skipper is not configured.
47    pub fn from_env() -> Option<Self> {
48        let var = |k: &str| std::env::var(k).ok().filter(|v| !v.trim().is_empty());
49        let id = var("SKIPPER_SPREADSHEET_ID")?;
50        let creds = if let Some(path) = var("SKIPPER_CREDENTIALS_FILE") {
51            Credentials::File(path.into())
52        } else {
53            Credentials::Base64(var("GOOGLE_CREDS_B64")?)
54        };
55        let mut cfg = SkipperConfig::new(id, creds);
56        cfg.sheet_name = var("SKIPPER_SHEET_NAME");
57        if let Some(refs) = var("SKIPPER_REFERENCE_SHEETS") {
58            cfg.reference_sheets = refs
59                .split(',')
60                .map(str::trim)
61                .filter(|s| !s.is_empty())
62                .map(String::from)
63                .collect();
64        }
65        Some(cfg)
66    }
67}