harmont_cli/orchestrator/
cache.rs1use anyhow::Result;
12use hm_plugin_protocol::{CacheDecision, CommandStep, SnapshotRef};
13
14use crate::orchestrator::docker_client::DockerClient;
15
16fn cache_image_tag(step: &CommandStep) -> Option<String> {
27 let cache = step.cache.as_ref()?;
28 if cache.policy == "none" {
29 return None;
30 }
31 let key = cache.key.as_deref()?;
32 let safe = sanitize_for_tag(&step.key);
33 let short = &key[..key.len().min(16)];
34 Some(format!("harmont-local/{safe}:{short}"))
35}
36
37fn sanitize_for_tag(s: &str) -> String {
38 s.chars()
39 .map(|c| {
40 if c.is_ascii_alphanumeric() || c == '_' || c == '-' {
41 c
42 } else {
43 '-'
44 }
45 })
46 .collect()
47}
48
49pub async fn decide(docker: &DockerClient, step: &CommandStep) -> Result<CacheDecision> {
58 let Some(tag) = cache_image_tag(step) else {
59 return Ok(CacheDecision::MissNoCommit);
60 };
61 if docker.image_exists(&tag).await? {
62 Ok(CacheDecision::Hit {
63 tag: SnapshotRef(tag),
64 })
65 } else {
66 Ok(CacheDecision::MissBuildAs {
67 tag: SnapshotRef(tag),
68 })
69 }
70}
71
72#[cfg(test)]
73#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
74mod tests {
75 use super::*;
76 use hm_plugin_protocol::Cache;
77
78 fn step(cache: Option<Cache>) -> CommandStep {
79 CommandStep {
80 key: "build".into(),
81 label: None,
82 cmd: "true".into(),
83 builds_in: None,
84 image: None,
85 env: None,
86 timeout_seconds: None,
87 cache,
88 runner: None,
89 runner_args: None,
90 }
91 }
92
93 #[test]
94 fn no_cache_yields_none() {
95 assert!(cache_image_tag(&step(None)).is_none());
96 }
97
98 #[test]
99 fn policy_none_yields_none() {
100 let s = step(Some(Cache {
101 policy: "none".into(),
102 key: Some("abcdef".into()),
103 }));
104 assert!(cache_image_tag(&s).is_none());
105 }
106
107 #[test]
108 fn ttl_with_key_yields_tag() {
109 let s = step(Some(Cache {
110 policy: "ttl".into(),
111 key: Some("0123456789abcdefffff".into()),
112 }));
113 let tag = cache_image_tag(&s).unwrap();
114 assert!(tag.starts_with("harmont-local/build:"));
115 }
116}