Skip to main content

max / makenotwork

4.1 KB · 97 lines History Blame Raw
1 //! Daemon-local config (`bento-daemon.toml`) — paths and listen address that
2 //! belong to the machine bentod runs on, not to the build matrix (which lives
3 //! in the separate topology file, see [`crate::topology`]).
4
5 use anyhow::{Context, Result};
6 use serde::Deserialize;
7 use std::path::PathBuf;
8
9 #[derive(Debug, Clone, Deserialize)]
10 pub struct Config {
11 pub listen: String,
12 pub db_path: PathBuf,
13 pub topology_path: PathBuf,
14 /// Root of the Syncthing private layer (`~/Code/_private`); the `secret()`
15 /// host function reads credential files relative to here. Never logged.
16 pub secrets_root: PathBuf,
17 /// Where collected artifacts land (`<dist_root>/<app>/<version>/`).
18 pub dist_root: PathBuf,
19 /// Root for per-step run logs
20 /// (`<logs_root>/<app>/<version>/<target>/<step>.log`).
21 #[serde(default = "default_logs_root")]
22 pub logs_root: PathBuf,
23 /// Override the per-step wall-clock budget (in seconds) for EVERY step,
24 /// replacing the per-kind defaults in `engine::step_budget`. Unset (the
25 /// default) uses those. Mainly an escape hatch for a constrained host or a
26 /// test that needs a short deadline.
27 #[serde(default)]
28 pub step_timeout_secs: Option<u64>,
29 /// Seconds to wait between `notarize` retry attempts. Unset (the default)
30 /// uses the 15-second production backoff; a test drives the retry loop with
31 /// `Some(0)` so it doesn't actually sleep. Same test-seam shape as
32 /// `step_timeout_secs`.
33 #[serde(default)]
34 pub notarize_backoff_secs: Option<u64>,
35 /// Pin every build host to the release tag `v<version>` and verify they all
36 /// report the same commit BEFORE any target builds — so `mbp`/`astra`/`fw13`
37 /// can't each build whatever `main` happened to be at pull time. On by
38 /// default; turn off only to build from an untagged commit (or in tests
39 /// whose repos aren't git checkouts).
40 #[serde(default = "default_true")]
41 pub pin_release_sha: bool,
42 /// The command that installs a service binary and restarts its unit, run on
43 /// the service host with `<staged-binary> <install-path> <unit>` appended.
44 ///
45 /// Bento never installs or restarts anything itself. It stages bytes and
46 /// calls this, and what it calls is a root script whose arguments are
47 /// re-checked on the far side — so the sudoers grant on a production box is
48 /// ONE auditable script rather than a broad `install` + `systemctl` grant.
49 /// Same shape as Sando's `install-companion.sh`.
50 ///
51 /// Configurable because the sudo path differs per host fleet, and because a
52 /// test needs to point it somewhere that is not root. It is read from the
53 /// same trusted daemon config that already names the secrets root, so this
54 /// adds no trust boundary that was not already there.
55 #[serde(default = "default_deploy_installer")]
56 pub deploy_installer: String,
57 }
58
59 fn default_true() -> bool {
60 true
61 }
62
63 fn default_deploy_installer() -> String {
64 "sudo /usr/local/lib/bento/install-service.sh".into()
65 }
66
67 fn default_logs_root() -> PathBuf {
68 PathBuf::from("/srv/bento/logs")
69 }
70
71 impl Config {
72 pub fn load() -> Result<Self> {
73 let path = std::env::var("BENTO_CONFIG").unwrap_or_else(|_| "bento-daemon.toml".into());
74 let raw = std::fs::read_to_string(&path)
75 .with_context(|| format!("reading daemon config at {path}"))?;
76 Ok(toml::from_str(&raw)?)
77 }
78
79 #[cfg(test)]
80 pub fn for_tests(root: &std::path::Path) -> Self {
81 Self {
82 listen: "127.0.0.1:0".into(),
83 db_path: root.join("bento.db"),
84 topology_path: root.join("bento.toml"),
85 secrets_root: root.join("secrets"),
86 dist_root: root.join("dist"),
87 logs_root: root.join("logs"),
88 step_timeout_secs: None,
89 notarize_backoff_secs: None,
90 // Test repos are plain dirs, not git checkouts; the barrier is
91 // exercised by its own tests that build a real tagged repo.
92 pin_release_sha: false,
93 deploy_installer: default_deploy_installer(),
94 }
95 }
96 }
97