huskies: merge 987

This commit is contained in:
dave
2026-05-13 16:26:09 +00:00
parent 430079ecbc
commit c3c9db3d8b
13 changed files with 662 additions and 311 deletions
+25 -95
View File
@@ -6,7 +6,7 @@ use std::process::Command;
use std::sync::Mutex;
use super::super::gates::run_project_tests;
use super::{MergeReport, SquashMergeResult};
use super::{MergeReport, MergeResult};
use crate::config::ProjectConfig;
/// Global lock ensuring only one squash-merge runs at a time.
@@ -21,7 +21,7 @@ pub(crate) fn run_squash_merge(
project_root: &Path,
branch: &str,
story_id: &str,
) -> Result<SquashMergeResult, String> {
) -> Result<MergeResult, String> {
// Acquire the merge lock so concurrent calls don't clobber each other.
let _lock = MERGE_LOCK
.lock()
@@ -48,18 +48,11 @@ pub(crate) fn run_squash_merge(
.parse()
.unwrap_or(1); // parse failure → don't false-positive; let merge proceed
if ahead == 0 {
return Ok(SquashMergeResult {
success: false,
had_conflicts: false,
conflicts_resolved: false,
conflict_details: None,
return Ok(MergeResult::NoCommits {
output: format!(
"{story_id}: no commits to merge — feature branch '{branch}' \
has 0 commits ahead of '{base_branch}'"
),
gates_passed: false,
gate_failure_kind: None,
no_commits: true,
});
}
}
@@ -115,9 +108,6 @@ pub(crate) fn run_squash_merge(
all_output.push_str(&merge_stderr);
all_output.push('\n');
let conflicts_resolved = false;
let mut conflict_details: Option<String> = None;
if !merge.status.success() {
all_output.push_str(
"=== Conflicts detected — aborting merge. Use `start_agent mergemaster` \
@@ -125,20 +115,12 @@ pub(crate) fn run_squash_merge(
);
let details =
format!("Merge conflicts in branch '{branch}':\n{merge_stdout}{merge_stderr}");
conflict_details = Some(details);
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts: true,
conflicts_resolved,
conflict_details,
return Ok(MergeResult::Conflict {
details: Some(details),
output: all_output,
gates_passed: false,
gate_failure_kind: None,
no_commits: false,
});
}
let had_conflicts = false;
// ── Commit in the temporary worktree ──────────────────────────
all_output.push_str("=== git commit ===\n");
@@ -169,27 +151,16 @@ pub(crate) fn run_squash_merge(
all_output
.push_str("=== Nothing to commit — feature branch already merged into base ===\n");
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: true,
had_conflicts: false,
return Ok(MergeResult::Success {
conflicts_resolved: false,
conflict_details: None,
output: all_output,
gates_passed: true,
gate_failure_kind: None,
no_commits: false,
gate_output: all_output,
});
}
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
conflict_details,
return Ok(MergeResult::Other {
output: all_output,
gates_passed: false,
gate_failure_kind: None,
no_commits: false,
conflict_details: None,
});
}
@@ -211,19 +182,13 @@ pub(crate) fn run_squash_merge(
"=== Merge commit contains only .huskies/ file moves, no code changes ===\n",
);
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
return Ok(MergeResult::Other {
output: all_output,
conflict_details: Some(
"Feature branch has no code changes outside .huskies/ — only \
pipeline file moves were found."
.to_string(),
),
output: all_output,
gates_passed: false,
gate_failure_kind: None,
no_commits: false,
});
}
}
@@ -280,29 +245,17 @@ pub(crate) fn run_squash_merge(
"=== Quality gates FAILED — aborting fast-forward, master unchanged ===\n",
);
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
conflict_details,
return Ok(MergeResult::GateFailure {
output: all_output,
gates_passed: false,
gate_failure_kind: outcome.failure_kind,
no_commits: false,
failure_kind: outcome.failure_kind,
});
}
Err(e) => {
all_output.push_str(&format!("Gate check error: {e}\n"));
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
conflict_details,
return Ok(MergeResult::GateFailure {
output: all_output,
gates_passed: false,
gate_failure_kind: None,
no_commits: false,
failure_kind: None,
});
}
}
@@ -335,17 +288,11 @@ pub(crate) fn run_squash_merge(
.output();
all_output.push_str("=== Cherry-pick failed — aborting, master unchanged ===\n");
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
return Ok(MergeResult::Other {
output: all_output,
conflict_details: Some(format!(
"Cherry-pick of squash commit failed (conflict with master?):\n{cp_stderr}"
)),
output: all_output,
gates_passed: true,
gate_failure_kind: None,
no_commits: false,
});
}
@@ -372,17 +319,11 @@ pub(crate) fn run_squash_merge(
'{current_branch}'. Cherry-pick landed on wrong branch. ===\n"
));
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
return Ok(MergeResult::Other {
output: all_output,
conflict_details: Some(format!(
"Cherry-pick landed on '{current_branch}' instead of '{base_branch}'"
)),
output: all_output,
gates_passed: true,
gate_failure_kind: None,
no_commits: false,
});
}
@@ -408,17 +349,11 @@ pub(crate) fn run_squash_merge(
"=== VERIFICATION FAILED: cherry-pick produced no code changes on master. ===\n",
);
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
return Ok(SquashMergeResult {
success: false,
had_conflicts,
conflicts_resolved,
return Ok(MergeResult::Other {
output: all_output,
conflict_details: Some(
"Cherry-pick commit contains no code changes (empty diff)".to_string(),
),
output: all_output,
gates_passed: true,
gate_failure_kind: None,
no_commits: false,
});
}
@@ -430,15 +365,10 @@ pub(crate) fn run_squash_merge(
cleanup_merge_workspace(project_root, &merge_wt_path, &merge_branch);
all_output.push_str("=== Merge-queue cleanup complete ===\n");
Ok(SquashMergeResult {
success: true,
had_conflicts,
conflicts_resolved,
conflict_details,
output: all_output,
gates_passed: true,
gate_failure_kind: None,
no_commits: false,
Ok(MergeResult::Success {
conflicts_resolved: false,
conflict_details: None,
gate_output: all_output,
})
}