mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(relay): auto-create git_repo_path so kind:30617 init can't silently fail (#545)
This commit is contained in:
@@ -287,6 +287,19 @@ impl Config {
|
||||
let git_repo_path: std::path::PathBuf = std::env::var("SPROUT_GIT_REPO_PATH")
|
||||
.unwrap_or_else(|_| "./repos".to_string())
|
||||
.into();
|
||||
// Ensure the git repo root exists. The smart-HTTP transport and the
|
||||
// kind:30617 side-effect handler both canonicalize this path; if it's
|
||||
// missing, all git operations 500 with "git service misconfigured" and
|
||||
// repo announcements silently fail to create their bare repo on disk.
|
||||
// Bootstrapping here makes the relay self-provision its own data dir
|
||||
// (matches how we treat other relay-owned paths) rather than requiring
|
||||
// ops to mkdir it out of band.
|
||||
if let Err(e) = std::fs::create_dir_all(&git_repo_path) {
|
||||
return Err(ConfigError::InvalidValue(format!(
|
||||
"SPROUT_GIT_REPO_PATH={} could not be created: {e}",
|
||||
git_repo_path.display()
|
||||
)));
|
||||
}
|
||||
let git_max_pack_bytes: u64 = std::env::var("SPROUT_GIT_MAX_PACK_BYTES")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
@@ -440,6 +453,52 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_repo_path_is_created_if_missing() {
|
||||
let _guard = ENV_MUTEX.lock().unwrap();
|
||||
// Pick a path under temp_dir that definitely doesn't exist yet.
|
||||
let base = std::env::temp_dir().join(format!(
|
||||
"sprout-test-git-repo-path-{}-{}",
|
||||
std::process::id(),
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos()
|
||||
));
|
||||
let nested = base.join("nested").join("repos");
|
||||
assert!(!nested.exists(), "test precondition: path must not exist");
|
||||
|
||||
std::env::set_var("SPROUT_GIT_REPO_PATH", &nested);
|
||||
let result = Config::from_env();
|
||||
std::env::remove_var("SPROUT_GIT_REPO_PATH");
|
||||
|
||||
let config = result.expect("config should self-bootstrap missing git_repo_path");
|
||||
assert_eq!(config.git_repo_path, nested);
|
||||
assert!(
|
||||
nested.is_dir(),
|
||||
"git_repo_path should exist after config load"
|
||||
);
|
||||
|
||||
// Cleanup.
|
||||
let _ = std::fs::remove_dir_all(&base);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn git_repo_path_unwritable_returns_error() {
|
||||
let _guard = ENV_MUTEX.lock().unwrap();
|
||||
// Try to create a path under a regular file — must fail.
|
||||
// Using /dev/null as the parent guarantees create_dir_all fails on unix.
|
||||
let bogus = std::path::PathBuf::from("/dev/null/cannot-create-here");
|
||||
std::env::set_var("SPROUT_GIT_REPO_PATH", &bogus);
|
||||
let result = Config::from_env();
|
||||
std::env::remove_var("SPROUT_GIT_REPO_PATH");
|
||||
assert!(
|
||||
matches!(result, Err(ConfigError::InvalidValue(ref msg)) if msg.contains("SPROUT_GIT_REPO_PATH")),
|
||||
"expected InvalidValue mentioning SPROUT_GIT_REPO_PATH, got {result:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_domain_explicit_override_wins() {
|
||||
let _guard = ENV_MUTEX.lock().unwrap();
|
||||
|
||||
@@ -1620,6 +1620,20 @@ async fn handle_git_repo_announcement(event: &Event, state: &Arc<AppState>) -> a
|
||||
|
||||
// Resolve repo path.
|
||||
let git_repo_root = &state.config.git_repo_path;
|
||||
|
||||
// Defensive: ensure the configured root exists. Config bootstrap creates
|
||||
// this at startup, but a misconfigured deployment or out-of-band deletion
|
||||
// would otherwise cause every canonicalize() below to fail and the
|
||||
// side-effect to be silently swallowed by the ingest pipeline, leaving the
|
||||
// repo announcement stored but no bare repo on disk (push then 500s with
|
||||
// "git service misconfigured").
|
||||
if let Err(e) = std::fs::create_dir_all(git_repo_root) {
|
||||
return Err(anyhow::anyhow!(
|
||||
"failed to ensure git_repo_path {} exists: {e}",
|
||||
git_repo_root.display()
|
||||
));
|
||||
}
|
||||
|
||||
let repo_dir = git_repo_root
|
||||
.join(&owner_hex)
|
||||
.join(format!("{repo_id}.git"));
|
||||
|
||||
Reference in New Issue
Block a user