huskies: merge 1074
This commit is contained in:
@@ -17,6 +17,20 @@ fn run(cmd: &str, args: &[&str], dir: &Path) {
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=PROFILE");
|
||||
|
||||
// Embed the current git commit hash at compile time so `get_version` always
|
||||
// reflects the binary that is actually running, not a potentially-stale file.
|
||||
println!("cargo:rerun-if-changed=../.git/HEAD");
|
||||
println!("cargo:rerun-if-changed=../.git/refs/");
|
||||
let git_hash = std::process::Command::new("git")
|
||||
.args(["rev-parse", "--short", "HEAD"])
|
||||
.output()
|
||||
.ok()
|
||||
.filter(|o| o.status.success())
|
||||
.and_then(|o| String::from_utf8(o.stdout).ok())
|
||||
.map(|s| s.trim().to_string())
|
||||
.unwrap_or_else(|| "unknown".to_string());
|
||||
println!("cargo:rustc-env=BUILD_GIT_HASH={git_hash}");
|
||||
println!("cargo:rerun-if-changed=../frontend/package.json");
|
||||
println!("cargo:rerun-if-changed=../frontend/package-lock.json");
|
||||
println!("cargo:rerun-if-changed=../frontend/vite.config.ts");
|
||||
|
||||
@@ -123,11 +123,10 @@ pub(crate) fn tool_dump_crdt(args: &Value) -> Result<String, String> {
|
||||
|
||||
/// MCP tool: return the server version, build hash, and running port.
|
||||
pub(crate) fn tool_get_version(ctx: &AppContext) -> Result<String, String> {
|
||||
let build_hash =
|
||||
std::fs::read_to_string(".huskies/build_hash").unwrap_or_else(|_| "unknown".to_string());
|
||||
let build_hash = option_env!("BUILD_GIT_HASH").unwrap_or("unknown");
|
||||
serde_json::to_string_pretty(&json!({
|
||||
"version": env!("CARGO_PKG_VERSION"),
|
||||
"build_hash": build_hash.trim(),
|
||||
"build_hash": build_hash,
|
||||
"port": ctx.services.agents.port(),
|
||||
}))
|
||||
.map_err(|e| format!("Serialization error: {e}"))
|
||||
@@ -312,4 +311,33 @@ mod tests {
|
||||
let result = tool_get_server_logs(&json!({"lines": 9999})).unwrap();
|
||||
let _ = result;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_get_version_ignores_build_hash_file_and_reports_compile_time_value() {
|
||||
// Regression: get_version must NOT read .huskies/build_hash at runtime.
|
||||
// Write a deliberately wrong value to the file and assert get_version
|
||||
// returns the compile-time hash, not the file content.
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let huskies_dir = dir.path().join(".huskies");
|
||||
std::fs::create_dir_all(&huskies_dir).unwrap();
|
||||
std::fs::write(huskies_dir.join("build_hash"), "wrong_hash_sentinel_xyz").unwrap();
|
||||
|
||||
let ctx = crate::http::test_helpers::test_ctx(dir.path());
|
||||
let result = tool_get_version(&ctx).expect("tool_get_version must not fail");
|
||||
let parsed: serde_json::Value = serde_json::from_str(&result).expect("must be valid JSON");
|
||||
|
||||
let returned_hash = parsed["build_hash"]
|
||||
.as_str()
|
||||
.expect("build_hash must be a string");
|
||||
assert_ne!(
|
||||
returned_hash, "wrong_hash_sentinel_xyz",
|
||||
"get_version must not read .huskies/build_hash; got '{returned_hash}'"
|
||||
);
|
||||
// The returned hash must equal the compile-time value.
|
||||
let compile_time_hash = option_env!("BUILD_GIT_HASH").unwrap_or("unknown");
|
||||
assert_eq!(
|
||||
returned_hash, compile_time_hash,
|
||||
"get_version must return compile-time BUILD_GIT_HASH"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -82,12 +82,10 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
});
|
||||
|
||||
// Log version and build hash so we can verify what's running.
|
||||
let build_hash =
|
||||
std::fs::read_to_string(".huskies/build_hash").unwrap_or_else(|_| "unknown".to_string());
|
||||
slog!(
|
||||
"[startup] huskies v{} (build {})",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
build_hash.trim()
|
||||
option_env!("BUILD_GIT_HASH").unwrap_or("unknown")
|
||||
);
|
||||
|
||||
let app_state = Arc::new(SessionState::default());
|
||||
|
||||
Reference in New Issue
Block a user