c0re: reject apply_commit on duplicate flake inputs (#317)
This commit is contained in:
parent
7b4917b256
commit
45833d0793
3 changed files with 307 additions and 2 deletions
|
|
@ -633,14 +633,34 @@ async fn submit_apply_commit(
|
|||
.approvals
|
||||
.set_fetched_sha(id, &sha)
|
||||
.map_err(|e| anyhow::anyhow!("persist fetched_sha: {e:#}"))?;
|
||||
// #317 dedup gate: parse the just-fetched flake.lock and reject if
|
||||
// the agent declared two inputs that resolve to the same upstream
|
||||
// (a missing `follows` directive). Runs after `set_fetched_sha` so
|
||||
// the failed approval row carries the sha that broke — handy when
|
||||
// the manager needs to inspect the bad commit.
|
||||
let sha_short = sha[..sha.len().min(12)].to_owned();
|
||||
if let Err(e) = crate::flake_check::check_no_duplicate_inputs(&applied_dir, &tag).await {
|
||||
let note = format!("{e:#}");
|
||||
let _ = coord.approvals.mark_failed(id, ¬e);
|
||||
coord.emit_approval_resolved(
|
||||
id,
|
||||
agent,
|
||||
"apply_commit",
|
||||
Some(sha_short.clone()),
|
||||
"failed",
|
||||
Some(note),
|
||||
description.map(str::to_owned),
|
||||
);
|
||||
return Err(anyhow::anyhow!("flake dedup check: {e:#}"));
|
||||
}
|
||||
// Mirror the freshly-planted proposal/<id> tag to the forge.
|
||||
if let Err(e) = crate::forge::push_config(agent).await {
|
||||
tracing::warn!(%agent, %id, error = ?e, "forge: push_config after submit failed");
|
||||
}
|
||||
// Phase 5b: surface the new pending approval on the dashboard
|
||||
// event channel. Compute the diff once here so live subscribers
|
||||
// get a fully-formed row without a snapshot refetch.
|
||||
let sha_short = sha[..sha.len().min(12)].to_owned();
|
||||
// get a fully-formed row without a snapshot refetch. `sha_short`
|
||||
// is reused from the dedup gate above.
|
||||
let diff = crate::dashboard::approval_diff(agent, id).await;
|
||||
coord.emit_approval_added(
|
||||
id,
|
||||
|
|
|
|||
Loading…
Reference in a new issue