feat(#1116): stream nixos-container create/update output live into build_logs

This commit is contained in:
damocles 2026-06-03 10:17:44 +02:00
commit 68451eb205
4 changed files with 335 additions and 46 deletions

View file

@ -87,11 +87,23 @@ pub enum PrivRequest {
/// `nixos-container update <name> --flake <flake_ref>`
/// The flake ref is derived from `name` by hive-priv.
UpdateContainer { name: String },
/// When `stream` is `true`, hive-priv sends `PrivEvent::Line` messages
/// as the process runs, then a terminal `PrivEvent::Done`.
UpdateContainer {
name: String,
#[serde(default)]
stream: bool,
},
/// `nixos-container create <name> --flake <flake_ref>`
/// The flake ref is derived from `name` by hive-priv.
CreateContainer { name: String },
/// When `stream` is `true`, hive-priv sends `PrivEvent::Line` messages
/// as the process runs, then a terminal `PrivEvent::Done`.
CreateContainer {
name: String,
#[serde(default)]
stream: bool,
},
/// `nixos-container destroy <name>`
DestroyContainer { name: String },
@ -199,3 +211,44 @@ pub struct PrivResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
// ---------------------------------------------------------------------------
// Streaming protocol
// ---------------------------------------------------------------------------
/// Which output stream a `PrivStreamLine` came from.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PrivStream {
Stdout,
Stderr,
}
/// A single line forwarded from a streaming privileged operation.
/// Wire shape: `{"stream":"stdout","data":"..."}` — distinct from
/// `PrivResponse` (which has `ok` but not `stream`/`data`) so that
/// `PrivEvent` can disambiguate with `#[serde(untagged)]`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PrivStreamLine {
pub stream: PrivStream,
pub data: String,
}
/// An event in the streaming protocol used by long-running priv ops.
///
/// Wire format (multiple JSON lines over one connection):
/// - Zero or more `Line` events as the subprocess runs.
/// - One terminal `Done` event carrying the final status.
///
/// Non-streaming ops (and old hive-priv) send exactly one `Done` line,
/// which is wire-identical to a bare `PrivResponse` — so old `call()`
/// callers that deserialise straight to `PrivResponse` continue to work
/// with new hive-priv's terminal event.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PrivEvent {
/// A line of output from the running subprocess.
Line(PrivStreamLine),
/// Terminal event: the operation has finished.
Done(PrivResponse),
}