Compare commits
2 changed files with 42 additions and 16 deletions
|
|
@ -192,4 +192,32 @@ impl DagView {
|
||||||
State::Done
|
State::Done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A short human label for the DAG, derived from its node kinds — the
|
||||||
|
/// shared replacement for the old `Template` wire string now that the kind
|
||||||
|
/// isn't sent. Priority-ordered so the most distinctive node wins (an
|
||||||
|
/// approval deploy reads as "deploy" even though it also rebuilds). Purely
|
||||||
|
/// cosmetic (progress/queue display); consumers that need exactness inspect
|
||||||
|
/// the node kinds directly.
|
||||||
|
#[must_use]
|
||||||
|
pub fn label(&self) -> &'static str {
|
||||||
|
let has = |k: &str| self.nodes.iter().any(|n| n.kind == k);
|
||||||
|
if has("approval_deploy") {
|
||||||
|
"deploy"
|
||||||
|
} else if has("meta_lock") {
|
||||||
|
"meta-update"
|
||||||
|
} else if has("create") || has("provision") {
|
||||||
|
"spawn"
|
||||||
|
} else if has("swap") || has("prebuild") || has("post_swap") {
|
||||||
|
"rebuild"
|
||||||
|
} else if has("write_perm_file") {
|
||||||
|
"perm-change"
|
||||||
|
} else if has("signal") || has("drain") {
|
||||||
|
"graceful"
|
||||||
|
} else if has("set_wanted") || has("stop_for_update") {
|
||||||
|
"power"
|
||||||
|
} else {
|
||||||
|
"reconcile"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ async fn wait_for_dags_plain(socket: &Path, ids: Vec<u64>) -> Result<()> {
|
||||||
// sees whether the agent came back.
|
// sees whether the agent came back.
|
||||||
if d.nodes.iter().all(|n| n.state.is_terminal()) {
|
if d.nodes.iter().all(|n| n.state.is_terminal()) {
|
||||||
if d.rollup_state() == hive_sh4re::jobs::State::Failed {
|
if d.rollup_state() == hive_sh4re::jobs::State::Failed {
|
||||||
failed.push(format!("{} {}", d.source.as_str(), dag_agents(d)));
|
failed.push(format!("{} {}", d.label(), dag_agents(d)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
all_terminal = false;
|
all_terminal = false;
|
||||||
|
|
@ -135,7 +135,7 @@ async fn wait_for_dags_animated(socket: &Path, ids: Vec<u64>) -> Result<()> {
|
||||||
hdr.set_message(format!(
|
hdr.set_message(format!(
|
||||||
"{} {} {} · {}",
|
"{} {} {} · {}",
|
||||||
state_glyph(d.rollup_state()),
|
state_glyph(d.rollup_state()),
|
||||||
d.source.as_str(),
|
d.label(),
|
||||||
dag_agents(d),
|
dag_agents(d),
|
||||||
fmt_dur(dag_elapsed(d, now)),
|
fmt_dur(dag_elapsed(d, now)),
|
||||||
));
|
));
|
||||||
|
|
@ -164,7 +164,7 @@ async fn wait_for_dags_animated(socket: &Path, ids: Vec<u64>) -> Result<()> {
|
||||||
}
|
}
|
||||||
if d.nodes.iter().all(|n| n.state.is_terminal()) {
|
if d.nodes.iter().all(|n| n.state.is_terminal()) {
|
||||||
if d.rollup_state() == hive_sh4re::jobs::State::Failed {
|
if d.rollup_state() == hive_sh4re::jobs::State::Failed {
|
||||||
failed.push(format!("{} {}", d.source.as_str(), dag_agents(d)));
|
failed.push(format!("{} {}", d.label(), dag_agents(d)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
all_terminal = false;
|
all_terminal = false;
|
||||||
|
|
@ -290,16 +290,16 @@ fn state_glyph(state: hive_sh4re::jobs::State) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// One progress line for a DAG: roll-up glyph, `source`, agents, then the
|
/// One progress line for a DAG: roll-up glyph, derived label, agents, then
|
||||||
/// node chain — the CLI twin of the dashboard's queue card. The header shows
|
/// the node chain — the CLI twin of the dashboard's queue card. Both the
|
||||||
/// what the backend sends (`source` + the raw node kinds); only the roll-up
|
/// roll-up state and the label are derived from the node set (the wire no
|
||||||
/// state glyph is derived from the node set. Used by the plain (non-TTY) path.
|
/// longer carries them). Used by the plain (non-TTY) path.
|
||||||
fn render_dag_line(d: &hive_sh4re::jobs::DagView) -> String {
|
fn render_dag_line(d: &hive_sh4re::jobs::DagView) -> String {
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
let mut out = format!(
|
let mut out = format!(
|
||||||
"{} {} {:<12}",
|
"{} {} {:<12}",
|
||||||
state_glyph(d.rollup_state()),
|
state_glyph(d.rollup_state()),
|
||||||
d.source.as_str(),
|
d.label(),
|
||||||
dag_agents(d)
|
dag_agents(d)
|
||||||
);
|
);
|
||||||
for (i, n) in d.nodes.iter().enumerate() {
|
for (i, n) in d.nodes.iter().enumerate() {
|
||||||
|
|
@ -337,12 +337,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn render_dag_line_shows_source_and_chain() {
|
fn render_dag_line_shows_chain_with_derived_label_and_state() {
|
||||||
// The header shows what the backend sends: the roll-up state glyph
|
// Roll-up state (Running) + label ("rebuild") are derived from the node
|
||||||
// (derived — Running here) + the DAG `source` ("manual"); the operation
|
// set — the wire no longer carries them. (`Done` nodes are included
|
||||||
// is read off the node chain, not a client-side label. (`Done` nodes
|
// here to exercise glyph rendering; production filters them off.)
|
||||||
// are included here to exercise glyph rendering; production filters
|
|
||||||
// them off.)
|
|
||||||
let dag = DagView {
|
let dag = DagView {
|
||||||
id: 7,
|
id: 7,
|
||||||
source: Source::Manual,
|
source: Source::Manual,
|
||||||
|
|
@ -358,7 +356,7 @@ mod tests {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
let line = render_dag_line(&dag);
|
let line = render_dag_line(&dag);
|
||||||
assert!(line.starts_with("▶ manual alice"), "{line}");
|
assert!(line.starts_with("▶ rebuild alice"), "{line}");
|
||||||
assert!(
|
assert!(
|
||||||
line.contains("✔ prebuild → ✔ stop_for_update → ▶ swap → ⏸ reconcile"),
|
line.contains("✔ prebuild → ✔ stop_for_update → ▶ swap → ⏸ reconcile"),
|
||||||
"{line}"
|
"{line}"
|
||||||
|
|
@ -379,7 +377,7 @@ mod tests {
|
||||||
nodes: vec![failed],
|
nodes: vec![failed],
|
||||||
};
|
};
|
||||||
let line = render_dag_line(&dag);
|
let line = render_dag_line(&dag);
|
||||||
assert!(line.contains("✖ manual"), "{line}");
|
assert!(line.contains("✖ rebuild"), "{line}");
|
||||||
assert!(line.contains("— nix build exploded"), "{line}");
|
assert!(line.contains("— nix build exploded"), "{line}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue