fix(#1115): commit perm+topology changes under META_LOCK to prevent dirty working tree
This commit is contained in:
parent
057c673be8
commit
ed50b858c5
3 changed files with 83 additions and 12 deletions
|
|
@ -325,6 +325,71 @@ pub async fn lock_update_hyperhive() -> Result<()> {
|
|||
git_commit(&dir, "bump hyperhive").await
|
||||
}
|
||||
|
||||
/// Write the tool-groups file for `agent` and commit it atomically
|
||||
/// under `META_LOCK`. Ensures the JSON change is staged + committed
|
||||
/// before the next `prepare_deploy` or `sync_agents` runs, so the
|
||||
/// working tree is never left dirty by an untimely PermChange write.
|
||||
pub async fn commit_tool_groups(agent: &str, groups: &[String]) -> Result<()> {
|
||||
let _guard = META_LOCK.lock().await;
|
||||
crate::tool_groups::set_groups(agent, groups)?;
|
||||
let dir = meta_dir();
|
||||
if crate::tool_groups::tool_groups_path().exists() {
|
||||
git(&dir, &["add", "tool-groups.json"]).await?;
|
||||
}
|
||||
if has_staged_changes(&dir).await? {
|
||||
git_commit(&dir, &format!("set tool-groups for {agent}")).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write the capabilities file for `agent` and commit it atomically
|
||||
/// under `META_LOCK`. Same rationale as `commit_tool_groups`.
|
||||
pub async fn commit_capabilities(agent: &str, caps: &[String]) -> Result<()> {
|
||||
let _guard = META_LOCK.lock().await;
|
||||
crate::capabilities::set_caps(agent, caps)
|
||||
.map_err(|e| anyhow::anyhow!("set capabilities for {agent}: {e}"))?;
|
||||
let dir = meta_dir();
|
||||
if crate::capabilities::capabilities_path().exists() {
|
||||
git(&dir, &["add", "capabilities.json"]).await?;
|
||||
}
|
||||
if has_staged_changes(&dir).await? {
|
||||
git_commit(&dir, &format!("set capabilities for {agent}")).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write the topology file and commit it atomically under `META_LOCK`.
|
||||
/// Returns `Err(String)` on validation failure (unknown agent, cycle,
|
||||
/// etc.) — same shape as `topology::set_parent` — so callers can
|
||||
/// surface the error as a user-visible message. Git failures are
|
||||
/// logged as warnings and don't propagate: the topology write already
|
||||
/// succeeded, and `sync_agents` will pick up any un-committed change
|
||||
/// on the next run as a safety net.
|
||||
pub async fn commit_topology(child: &str, new_parent: Option<&str>) -> std::result::Result<(), String> {
|
||||
let _guard = META_LOCK.lock().await;
|
||||
crate::topology::set_parent(child, new_parent)?;
|
||||
let dir = meta_dir();
|
||||
let stage = async {
|
||||
git(&dir, &["add", "topology.json"]).await?;
|
||||
if has_staged_changes(&dir).await? {
|
||||
git_commit(
|
||||
&dir,
|
||||
&format!(
|
||||
"topology: {} → {}",
|
||||
child,
|
||||
new_parent.unwrap_or("<root>")
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
Ok::<_, anyhow::Error>(())
|
||||
};
|
||||
if let Err(e) = stage.await {
|
||||
tracing::warn!(%child, ?new_parent, error = ?e, "commit_topology: topology written but git commit failed (sync_agents will recover)");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_flake(
|
||||
hyperhive_flake: &str,
|
||||
nixpkgs_flake: &str,
|
||||
|
|
|
|||
Loading…
Reference in a new issue