fix(#2971): thread the queue node id into nix_logged

`nix_logged` wrote its `build_logs` row with `node_id = None`, so a deploy's
eval/relock log was reachable from the agent+kind+time listing but not from
the queue node that ran it.

The comment justifying the `None` said both callers are "reached from outside
the queue as well as from inside it". That is no longer true: `verify_commit`
and `prepare_deploy` have exactly one caller each, and both sit under the
`MergeVerify` / `DeployApply` arms of `exec.rs`'s node dispatch, where the
`NodeId` is already in scope.

Threads `Option<u64>` from the dispatch down, mirroring `prebuild_toplevel`'s
existing `Some(id.get())` at exec.rs:241. Kept as `Option` rather than a bare
`u64` because `meta::prepare_deploy` / `meta::verify_commit` are public API and
a future non-queue caller has no node to name; the comment now says that
instead of the stale claim.

No behaviour change beyond the log row gaining its node link.
This commit is contained in:
atlas 2026-08-03 17:47:07 +02:00 committed by mara
commit 6ce71556e2
3 changed files with 51 additions and 22 deletions

View file

@ -213,7 +213,11 @@ fn deploy_ctx(coord: &Coordinator, approval_id: i64) -> Result<DeployCtx> {
/// fails, if the reviewed head does not descend from `applied/main`, or if the
/// eval-verify of the reviewed commit fails. Every one of these leaves the forge
/// and `main` untouched, so the node is safely retryable.
pub async fn run_deploy_merge_verify(coord: &Arc<Coordinator>, approval_id: i64) -> Result<()> {
pub async fn run_deploy_merge_verify(
coord: &Arc<Coordinator>,
approval_id: i64,
node_id: Option<u64>,
) -> Result<()> {
let ctx = deploy_ctx(coord, approval_id)?;
let pr = ctx.pr;
let reviewed = ctx.reviewed.as_str();
@ -250,9 +254,14 @@ pub async fn run_deploy_merge_verify(coord: &Arc<Coordinator>, approval_id: i64)
}
// 4. Eval-verify BEFORE the irreversible merge (bad nix fails fast here).
crate::meta::verify_commit(ctx.approval.agent.as_str(), &ctx.applied_dir, reviewed)
.await
.map_err(|e| anyhow::anyhow!("verify merge head {reviewed}: {e:#}"))?;
crate::meta::verify_commit(
ctx.approval.agent.as_str(),
&ctx.applied_dir,
reviewed,
node_id,
)
.await
.map_err(|e| anyhow::anyhow!("verify merge head {reviewed}: {e:#}"))?;
Ok(())
}
@ -275,7 +284,11 @@ pub async fn run_deploy_merge_verify(coord: &Arc<Coordinator>, approval_id: i64)
/// fast-forwarding `applied/main` / `meta::prepare_deploy` fails. From the merge
/// onward a failure is *not* retryable on its own — [`run_deploy_tail`] runs
/// `AfterAny` to compensate.
pub async fn run_deploy_apply(coord: &Arc<Coordinator>, approval_id: i64) -> Result<()> {
pub async fn run_deploy_apply(
coord: &Arc<Coordinator>,
approval_id: i64,
node_id: Option<u64>,
) -> Result<()> {
let ctx = deploy_ctx(coord, approval_id)?;
let agent = ctx.approval.agent.as_str();
let pr = ctx.pr;
@ -300,7 +313,7 @@ pub async fn run_deploy_apply(coord: &Arc<Coordinator>, approval_id: i64) -> Res
Err(e) => bail!("ff-merge PR #{pr}: {e}"),
}
prepare_applied_target(agent, &ctx.applied_dir, &ctx.reviewed, &prev_main).await
prepare_applied_target(agent, &ctx.applied_dir, &ctx.reviewed, &prev_main, node_id).await
}
/// `DeployTail` node body — compensation + bookkeeping, `AfterAny` the apply
@ -817,6 +830,7 @@ async fn prepare_applied_target(
applied_dir: &std::path::Path,
target: &str,
expected_main: &str,
node_id: Option<u64>,
) -> Result<()> {
// Fast-forward applied/main to target + sync the working tree. Meta input
// pins `?ref=main`, so this is what makes nix re-lock to the target commit
@ -840,7 +854,7 @@ async fn prepare_applied_target(
// Phase 1 of the meta two-phase deploy: relock without committing. The
// staged lock then stays uncommitted across the whole appended rebuild —
// which is why the `MetaWindow` is held by the deploy root, not by a node.
crate::meta::prepare_deploy(agent)
crate::meta::prepare_deploy(agent, node_id)
.await
.map_err(|e| anyhow::anyhow!("meta prepare_deploy: {e:#}"))
}