Watch
0
0
Fork
You've already forked hyperhive
0

download an agent's cached closure in prebuild, building locally when that fails

This commit is contained in:
atlas 2026-10-28 02:02:29 +01:00
commit c16cf1756f

View file

@ -751,6 +751,29 @@ async fn wait_bounded(
Ok(None)
}
/// Log and record a prebuild's stdout; the last non-empty line is the
/// toplevel `nix build --print-out-paths` printed.
async fn pump_prebuild_stdout(
stdout: tokio::process::ChildStdout,
cmdline: String,
logs: Option<std::sync::Arc<crate::build_logs::BuildLogs>>,
log_id: Option<i64>,
) -> Option<String> {
use tokio::io::{AsyncBufReadExt, BufReader};
let mut lines = BufReader::new(stdout).lines();
let mut out_path = None;
while let Ok(Some(line)) = lines.next_line().await {
tracing::info!(target: "nix-prebuild", cmdline = %cmdline, "{line}");
if !line.trim().is_empty() {
out_path = Some(line.trim().to_owned());
}
if let (Some(h), Some(id)) = (&logs, log_id) {
h.append_stdout(id, &line);
}
}
out_path
}
/// Pre-build `system.build.toplevel` against `meta#<name>` so the
/// subsequent `nixos-container update` finds the result cached and
/// skips straight to the profile-swap. Store-warming only — container
@ -761,7 +784,13 @@ async fn wait_bounded(
/// `node_id` is the queue node this build belongs to, when there is one —
/// it is stored on the `build_logs` row so the dashboard can find the log
/// from the node. Pass `None` for builds that run outside the queue.
pub async fn prebuild_toplevel(name: &str, flake_ref: &str, node_id: Option<u64>) -> Result<()> {
///
/// Returns the toplevel `nix build` printed, `None` if it printed nothing.
pub async fn prebuild_toplevel(
name: &str,
flake_ref: &str,
node_id: Option<u64>,
) -> Result<Option<String>> {
use tokio::io::{AsyncBufReadExt, BufReader};
// Split `<root>#<name>` so we can re-emit with the explicit
// `nixosConfigurations.<name>` segment. The flake_ref shape is
@ -814,17 +843,12 @@ pub async fn prebuild_toplevel(name: &str, flake_ref: &str, node_id: Option<u64>
let stdout = child.stdout.take().expect("piped stdout");
let stderr = child.stderr.take().expect("piped stderr");
let stdout_cmdline = cmdline.clone();
let stdout_logs = logs.clone();
let pump_stdout = tokio::spawn(async move {
let mut lines = BufReader::new(stdout).lines();
while let Ok(Some(line)) = lines.next_line().await {
tracing::info!(target: "nix-prebuild", cmdline = %stdout_cmdline, "{line}");
if let (Some(h), Some(id)) = (&stdout_logs, log_id) {
h.append_stdout(id, &line);
}
}
});
let pump_stdout = tokio::spawn(pump_prebuild_stdout(
stdout,
cmdline.clone(),
logs.clone(),
log_id,
));
let stderr_cmdline = cmdline.clone();
let stderr_logs = logs.clone();
@ -860,7 +884,7 @@ pub async fn prebuild_toplevel(name: &str, flake_ref: &str, node_id: Option<u64>
None => bail!("prebuild {cmdline} timed out after {secs}s; killed it"),
}
};
let _ = pump_stdout.await;
let out_path = pump_stdout.await.ok().flatten();
let _ = pump_stderr.await;
let ok = status.success();
@ -880,7 +904,7 @@ pub async fn prebuild_toplevel(name: &str, flake_ref: &str, node_id: Option<u64>
None => bail!("prebuild {cmdline} failed ({status})"),
}
}
Ok(())
Ok(out_path)
}
pub async fn list() -> Result<Vec<String>> {