huskies: merge 498_bug_stale_merge_job_lock_prevents_new_merges_after_agent_dies

This commit is contained in:
dave
2026-04-10 18:51:07 +00:00
parent 6f7a0c7708
commit bc2b1e244c
2 changed files with 74 additions and 0 deletions
+64
View File
@@ -212,6 +212,70 @@ mod tests {
.unwrap();
}
// ── bug 498: stale Running job blocks retry ───────────────────────────────
/// Regression test for bug 498: a Running merge job left behind by a killed
/// mergemaster must not block the next call to start_merge_agent_work.
///
/// Before the fix: start_merge_agent_work would return "Merge already in
/// progress" when a Running entry existed, even after the mergemaster died.
/// After the fix: the entry is cleared when the mergemaster exits, so a new
/// call succeeds.
#[tokio::test]
async fn stale_running_merge_job_is_cleared_and_retry_succeeds() {
use tempfile::tempdir;
let tmp = tempdir().unwrap();
let repo = tmp.path();
init_git_repo(repo);
let pool = Arc::new(AgentPool::new_test(3001));
// Inject a stale Running entry, simulating a mergemaster that died
// before the merge pipeline completed.
{
let mut jobs = pool.merge_jobs.lock().unwrap();
jobs.insert(
"77_story_stale".to_string(),
MergeJob {
story_id: "77_story_stale".to_string(),
status: MergeJobStatus::Running,
},
);
}
// With a stale Running entry, start_merge_agent_work must be blocked.
let blocked = pool.start_merge_agent_work(repo, "77_story_stale");
assert!(
blocked.is_err(),
"start_merge_agent_work must be blocked while Running job exists"
);
let err_msg = blocked.unwrap_err();
assert!(
err_msg.contains("already in progress"),
"unexpected error: {err_msg}"
);
// Simulate the mergemaster exit path: clear the stale Running entry.
{
let mut jobs = pool.merge_jobs.lock().unwrap();
if let Some(job) = jobs.get("77_story_stale")
&& matches!(job.status, MergeJobStatus::Running)
{
jobs.remove("77_story_stale");
}
}
// After clearing, start_merge_agent_work must succeed (it will fail
// the pipeline because there's no feature branch, but it must not be
// blocked by "Merge already in progress").
let result = pool.start_merge_agent_work(repo, "77_story_stale");
assert!(
result.is_ok(),
"start_merge_agent_work must succeed after stale Running job is cleared; got: {result:?}"
);
}
// ── merge_agent_work tests ────────────────────────────────────────────────
/// Helper: start a merge and poll until terminal state.