Skip to main content

opal/
naming.rs

1pub fn job_name_slug(name: &str) -> String {
2    let mut slug = String::new();
3    for ch in name.chars() {
4        if ch.is_ascii_alphanumeric() {
5            slug.push(ch.to_ascii_lowercase());
6        } else {
7            match ch {
8                ' ' | '-' | '_' => slug.push('-'),
9                _ => continue,
10            }
11        }
12    }
13
14    if slug.is_empty() {
15        slug.push_str("job");
16    }
17
18    slug
19}
20
21pub fn stage_name_slug(name: &str) -> String {
22    job_name_slug(name)
23}
24
25pub fn project_slug(path: &str) -> String {
26    let mut slug = String::new();
27    for ch in path.chars() {
28        match ch {
29            'a'..='z' | '0'..='9' => slug.push(ch),
30            'A'..='Z' => slug.push(ch.to_ascii_lowercase()),
31            '/' | '_' | '-' => slug.push('-'),
32            _ => continue,
33        }
34    }
35    if slug.is_empty() {
36        slug.push_str("project");
37    }
38    slug
39}
40
41pub fn escape_double_quotes(input: &str) -> String {
42    let mut escaped = String::with_capacity(input.len());
43    for ch in input.chars() {
44        match ch {
45            '"' => escaped.push_str("\\\""),
46            '\\' => escaped.push_str("\\\\"),
47            _ => escaped.push(ch),
48        }
49    }
50    escaped
51}
52
53use crate::ExecutorConfig;
54use sha2::{Digest, Sha256};
55use std::process;
56use std::time::{SystemTime, UNIX_EPOCH};
57
58pub fn generate_run_id(config: &ExecutorConfig) -> String {
59    let pipeline_slug = config
60        .pipeline
61        .file_stem()
62        .and_then(|stem| stem.to_str())
63        .map(job_name_slug)
64        .unwrap_or_else(|| "pipeline".to_string());
65    let nanos = SystemTime::now()
66        .duration_since(UNIX_EPOCH)
67        .map(|d| d.as_nanos())
68        .unwrap_or(0);
69
70    let mut hasher = Sha256::new();
71    hasher.update(pipeline_slug.as_bytes());
72    hasher.update(nanos.to_le_bytes());
73    hasher.update(process::id().to_le_bytes());
74
75    let digest = hasher.finalize();
76    let suffix = format!("{:x}", digest);
77    let short = &suffix[..8];
78    format!("{pipeline_slug}-{short}")
79}