diff --git a/backend/src/services/git.rs b/backend/src/services/git.rs index 50125ed..dc00b78 100644 --- a/backend/src/services/git.rs +++ b/backend/src/services/git.rs @@ -130,17 +130,38 @@ fn remote_callbacks() -> git2::RemoteCallbacks<'static> { let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(move |_url, username_from_url, _allowed_types| { - let username = username_from_url.unwrap_or(auth.username.as_str()); + // Always prefer configured username (env-driven). + // Some remotes embed a username in URL; that can cause auth mismatches. + let username = auth.username.as_str(); + if let Some(url_user) = username_from_url { + if url_user != username { + tracing::warn!( + "Remote URL username '{}' differs from IRONPAD_GIT_SSH_USERNAME '{}'; using env value", + url_user, + username + ); + } + } if let Some(private_key) = auth.private_key.as_deref() { let public_key: Option<&Path> = auth.public_key.as_deref(); let passphrase = auth.passphrase.as_deref(); - if let Ok(cred) = git2::Cred::ssh_key(username, public_key, private_key, passphrase) { - return Ok(cred); + match git2::Cred::ssh_key(username, public_key, private_key, passphrase) { + Ok(cred) => return Ok(cred), + Err(e) => { + tracing::warn!( + "SSH key auth from file failed for user '{}', key '{}': {}", + username, + private_key.display(), + e + ); + } } - - tracing::warn!("SSH key auth from file failed, falling back to SSH agent"); + } else { + tracing::warn!( + "IRONPAD_GIT_SSH_PRIVATE_KEY not set or file missing; falling back to SSH agent" + ); } git2::Cred::ssh_key_from_agent(username)