manager_server: fetch+tag at request_apply_commit submit
submit_apply_commit (1) queues the approval row, (2) git-fetches the manager-supplied sha from proposed into applied, pins it as refs/tags/proposal/<id>, (3) persists the resolved sha on the row via approvals.set_fetched_sha. from this point on the proposal is immutable from the manager's perspective: amends or force-pushes in proposed do not change what hive-c0re will build. fetch failures mark the row failed and surface the error to the manager so a phantom pending entry can't linger.
This commit is contained in:
parent
8cb8fcedad
commit
35b0edaf27
1 changed files with 63 additions and 3 deletions
|
|
@ -258,9 +258,9 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
|
|||
}
|
||||
ManagerRequest::RequestApplyCommit { agent, commit_ref } => {
|
||||
tracing::info!(%agent, %commit_ref, "manager: request_apply_commit");
|
||||
match coord.approvals.submit(agent, commit_ref) {
|
||||
Ok(id) => {
|
||||
tracing::info!(%id, %agent, %commit_ref, "approval queued");
|
||||
match submit_apply_commit(coord, agent, commit_ref).await {
|
||||
Ok((id, sha)) => {
|
||||
tracing::info!(%id, %agent, manager_ref = %commit_ref, %sha, "approval queued + proposal tag planted");
|
||||
ManagerResponse::Ok
|
||||
}
|
||||
Err(e) => ManagerResponse::Err {
|
||||
|
|
@ -271,6 +271,66 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
|
|||
}
|
||||
}
|
||||
|
||||
/// Submit-time half of the apply flow: queue the approval row, then
|
||||
/// fetch the manager's commit from the proposed repo into applied and
|
||||
/// pin it as `refs/tags/proposal/<id>`. From this point on the manager
|
||||
/// repo is irrelevant for this approval — even if the manager amends
|
||||
/// or force-pushes, the canonical sha hive-c0re will eventually
|
||||
/// approve/deny lives in applied's object DB.
|
||||
///
|
||||
/// If anything fails after the row is inserted (sha missing in
|
||||
/// proposed, fs error, git plumbing crash) we mark the row failed and
|
||||
/// surface the error to the manager. We don't try to roll the row
|
||||
/// back — the failure is part of the audit trail.
|
||||
async fn submit_apply_commit(
|
||||
coord: &Arc<Coordinator>,
|
||||
agent: &str,
|
||||
commit_ref: &str,
|
||||
) -> anyhow::Result<(i64, String)> {
|
||||
let proposed_dir = crate::coordinator::Coordinator::agent_proposed_dir(agent);
|
||||
let applied_dir = crate::coordinator::Coordinator::agent_applied_dir(agent);
|
||||
if !proposed_dir.exists() {
|
||||
anyhow::bail!(
|
||||
"proposed repo missing for agent '{agent}' (expected at {})",
|
||||
proposed_dir.display()
|
||||
);
|
||||
}
|
||||
if !applied_dir.join(".git").exists() {
|
||||
anyhow::bail!(
|
||||
"applied repo at {} is uninitialised — spawn the agent first",
|
||||
applied_dir.display()
|
||||
);
|
||||
}
|
||||
let id = coord
|
||||
.approvals
|
||||
.submit(agent, commit_ref)
|
||||
.map_err(|e| anyhow::anyhow!("queue approval row: {e:#}"))?;
|
||||
let tag = format!("proposal/{id}");
|
||||
let sha = match crate::lifecycle::git_fetch_to_tag(
|
||||
&applied_dir,
|
||||
&proposed_dir,
|
||||
commit_ref,
|
||||
&tag,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
// Surface the failure on the approval row so the
|
||||
// dashboard reflects it instead of leaving a phantom
|
||||
// pending entry. The note doubles as the operator-visible
|
||||
// explanation of why the approval can't be approved.
|
||||
let _ = coord.approvals.mark_failed(id, &format!("{e:#}"));
|
||||
return Err(anyhow::anyhow!("git_fetch_to_tag: {e:#}"));
|
||||
}
|
||||
};
|
||||
coord
|
||||
.approvals
|
||||
.set_fetched_sha(id, &sha)
|
||||
.map_err(|e| anyhow::anyhow!("persist fetched_sha: {e:#}"))?;
|
||||
Ok((id, sha))
|
||||
}
|
||||
|
||||
/// On `AskOperator { ttl_seconds: Some(n) }`, sleep n seconds and then
|
||||
/// try to resolve the question with `[expired]`. If the operator (or
|
||||
/// any other path) already answered it, `answer()` returns Err and
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue