use std::path::Path;
pub fn declare_rerun_conditions(_manifest_dir: &Path) {
println!("cargo:rerun-if-env-changed=DEEPSEEK_BUILD_SHA");
println!("cargo:rerun-if-env-changed=GITHUB_SHA");
}
pub fn emit_build_version(_manifest_dir: &Path, package_version: &str) {
let commit = build_commit();
let build_version = commit
.as_ref()
.and_then(|sha| short_sha(sha.clone()))
.map(|sha| format!("{package_version} ({sha})"))
.unwrap_or_else(|| format!("{package_version} (dev)"));
println!("cargo:rustc-env=DEEPSEEK_BUILD_VERSION={build_version}");
if let Some(commit) = commit {
println!("cargo:rustc-env=CODEWHALE_BUILD_COMMIT={commit}");
}
}
pub fn declare_release_sha_rerun() {
println!("cargo:rerun-if-env-changed=DEEPSEEK_BUILD_SHA");
println!("cargo:rerun-if-env-changed=GITHUB_SHA");
}
pub fn emit_release_build_sha() {
if let Some(sha) = release_build_sha(|name| std::env::var(name).ok()) {
println!("cargo:rustc-env=CODEWHALE_RELEASE_BUILD_SHA={sha}");
}
}
#[must_use]
pub fn release_build_sha(read_env: impl Fn(&str) -> Option<String>) -> Option<String> {
read_env("DEEPSEEK_BUILD_SHA")
.and_then(full_sha)
.or_else(|| read_env("GITHUB_SHA").and_then(full_sha))
.and_then(short_sha)
}
fn build_commit() -> Option<String> {
build_commit_with(|name| std::env::var(name).ok())
}
fn build_commit_with(read_env: impl Fn(&str) -> Option<String>) -> Option<String> {
read_env("DEEPSEEK_BUILD_SHA")
.and_then(full_sha)
.or_else(|| read_env("GITHUB_SHA").and_then(full_sha))
}
fn full_sha(value: String) -> Option<String> {
let trimmed = value.trim().to_ascii_lowercase();
if trimmed.len() != 40 || !trimmed.bytes().all(|byte| byte.is_ascii_hexdigit()) {
return None;
}
Some(trimmed)
}
fn short_sha(value: String) -> Option<String> {
let trimmed = value.trim();
if trimmed.is_empty() {
return None;
}
Some(trimmed.chars().take(12).collect())
}
#[cfg(test)]
mod tests {
use super::{full_sha, release_build_sha, short_sha};
#[test]
fn full_commit_requires_exact_forty_hex_characters() {
assert_eq!(
full_sha("ABCDEF0123456789ABCDEF0123456789ABCDEF01".to_string()),
Some("abcdef0123456789abcdef0123456789abcdef01".to_string())
);
assert_eq!(full_sha("abc123".to_string()), None);
assert_eq!(
full_sha("gggggggggggggggggggggggggggggggggggggggg".to_string()),
None
);
assert_eq!(
short_sha("abcdef0123456789abcdef0123456789abcdef01".to_string()),
Some("abcdef012345".to_string())
);
}
#[test]
fn the_release_build_sha_is_absent_for_every_local_build() {
assert_eq!(release_build_sha(|_| None), None);
}
#[test]
fn the_release_build_sha_comes_only_from_a_release_environment() {
let ci = "abcdef0123456789abcdef0123456789abcdef01";
assert_eq!(
release_build_sha(|name| (name == "GITHUB_SHA").then(|| ci.to_string())),
Some("abcdef012345".to_string())
);
assert_eq!(
release_build_sha(|name| match name {
"DEEPSEEK_BUILD_SHA" => Some("f".repeat(40)),
"GITHUB_SHA" => Some(ci.to_string()),
_ => None,
}),
Some("f".repeat(12))
);
assert_eq!(
release_build_sha(|name| (name == "DEEPSEEK_BUILD_SHA").then(|| "abc123".to_string())),
None
);
assert_eq!(
release_build_sha(|name| (name == "CODEWHALE_BUILD_COMMIT").then(|| ci.to_string())),
None
);
}
#[test]
fn the_build_commit_never_reads_the_local_checkout() {
assert_eq!(super::build_commit_with(|_| None), None);
let ci = "abcdef0123456789abcdef0123456789abcdef01";
assert_eq!(
super::build_commit_with(|name| (name == "GITHUB_SHA").then(|| ci.to_string())),
Some(ci.to_string())
);
assert_eq!(
super::build_commit_with(|name| match name {
"DEEPSEEK_BUILD_SHA" => Some("f".repeat(40)),
"GITHUB_SHA" => Some(ci.to_string()),
_ => None,
}),
Some("f".repeat(40))
);
}
}