test: assert the deploy subtree's phase order and tail-on-failure
Two cases, both pinning the load-bearing property that the tail is reached on every path: a failed apply (AfterAny dep is terminal) and a failed verify (apply is cancel-cascaded, tail still claimable). Both assert the DAG rolls up to Failed — an Ok tail must not launder a failed deploy into a success.
This commit is contained in:
parent
816006fd48
commit
8499c793fe
1 changed files with 82 additions and 0 deletions
|
|
@ -926,6 +926,88 @@ fn cancelled_dag_finalizes_with_terminal_rollup() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- approval deploy subtree ----
|
||||||
|
|
||||||
|
/// The config-PR deploy is a subtree, not one opaque node. The
|
||||||
|
/// resource-holding root completes immediately (its `Finishing` state is the
|
||||||
|
/// parent gate that releases the children), then the phases run strictly in
|
||||||
|
/// order — and the `AfterAny` tail still runs when the irreversible half fails,
|
||||||
|
/// because it's the node that compensates for it.
|
||||||
|
#[test]
|
||||||
|
fn deploy_dag_runs_phases_in_order_and_tails_a_failed_apply() {
|
||||||
|
let q = JobQueue::new(1);
|
||||||
|
let id = submit(
|
||||||
|
&q,
|
||||||
|
templates::approval_deploy("agent-a", 7, "approval #7".to_owned()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let root = claim_one(&q);
|
||||||
|
assert!(
|
||||||
|
matches!(root.kind, NodeKind::DeployWindow { .. }),
|
||||||
|
"root claims first: it holds the meta window for the whole subtree"
|
||||||
|
);
|
||||||
|
q.complete_node(id, root.node_id, Ok(()));
|
||||||
|
|
||||||
|
let verify = claim_one(&q);
|
||||||
|
assert!(matches!(verify.kind, NodeKind::MergeVerify { .. }));
|
||||||
|
q.complete_node(id, verify.node_id, Ok(()));
|
||||||
|
|
||||||
|
let apply = claim_one(&q);
|
||||||
|
assert!(matches!(apply.kind, NodeKind::DeployApply { .. }));
|
||||||
|
q.complete_node(
|
||||||
|
id,
|
||||||
|
apply.node_id,
|
||||||
|
Err("nixos-container update blew up".into()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let tail = claim_one(&q);
|
||||||
|
assert!(
|
||||||
|
matches!(tail.kind, NodeKind::DeployTail { .. }),
|
||||||
|
"AfterAny tail runs on a failed apply — that's the whole point of it"
|
||||||
|
);
|
||||||
|
q.complete_node(id, tail.node_id, Ok(()));
|
||||||
|
|
||||||
|
let summary = q.terminal_summary(id).expect("dag terminal");
|
||||||
|
assert_eq!(
|
||||||
|
summary.state,
|
||||||
|
State::Failed,
|
||||||
|
"an Ok tail must not launder a failed deploy into a success"
|
||||||
|
);
|
||||||
|
assert_eq!(summary.approval_id, Some(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A pre-merge rejection (drift gate, eval failure) cancel-cascades the
|
||||||
|
/// irreversible half via its `AfterOk` edge, but the tail is still reached —
|
||||||
|
/// it owns the forge mirror, not just compensation.
|
||||||
|
#[test]
|
||||||
|
fn deploy_dag_skips_apply_but_still_runs_tail_when_verify_fails() {
|
||||||
|
let q = JobQueue::new(1);
|
||||||
|
let id = submit(
|
||||||
|
&q,
|
||||||
|
templates::approval_deploy("agent-a", 9, "approval #9".to_owned()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let root = claim_one(&q);
|
||||||
|
q.complete_node(id, root.node_id, Ok(()));
|
||||||
|
let verify = claim_one(&q);
|
||||||
|
q.complete_node(
|
||||||
|
id,
|
||||||
|
verify.node_id,
|
||||||
|
Err("PR head drifted since review".into()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let tail = claim_one(&q);
|
||||||
|
assert!(
|
||||||
|
matches!(tail.kind, NodeKind::DeployTail { .. }),
|
||||||
|
"apply is cancel-cascaded, so the tail is the next claimable node"
|
||||||
|
);
|
||||||
|
q.complete_node(id, tail.node_id, Ok(()));
|
||||||
|
|
||||||
|
let summary = q.terminal_summary(id).expect("dag terminal");
|
||||||
|
assert_eq!(summary.state, State::Failed);
|
||||||
|
assert_eq!(summary.approval_id, Some(9));
|
||||||
|
}
|
||||||
|
|
||||||
// ---- steps, build logs, history ----
|
// ---- steps, build logs, history ----
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue