use std::fmt;
use std::path::PathBuf;
use ring::rand::{SecureRandom, SystemRandom};
pub fn generate_ci_passphrase() -> String {
let rng = SystemRandom::new();
let mut bytes = [0u8; 24];
#[allow(clippy::expect_used)]
rng.fill(&mut bytes).expect("system CSPRNG unavailable");
bytes.iter().map(|b| format!("{b:02x}")).collect()
}
#[derive(Debug, Clone)]
pub enum CiEnvironment {
GitHubActions,
GitLabCi,
Custom {
name: String,
},
Unknown,
}
#[derive(Clone)]
pub struct CiIdentityConfig {
pub ci_environment: CiEnvironment,
pub registry_path: PathBuf,
pub keychain_file: PathBuf,
pub passphrase: String,
}
impl fmt::Debug for CiIdentityConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CiIdentityConfig")
.field("ci_environment", &self.ci_environment)
.field("registry_path", &self.registry_path)
.field("keychain_file", &self.keychain_file)
.field("passphrase", &"[REDACTED]")
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ci_passphrase_is_unique_per_call() {
assert_ne!(generate_ci_passphrase(), generate_ci_passphrase());
}
#[test]
fn ci_passphrase_is_strong() {
let p = generate_ci_passphrase();
assert!(p.len() >= 32, "passphrase too short ({} chars)", p.len());
}
}