ref:bfb5d896a647a77d92b57654ee7eecfcc9e34890

fix: add docker pull before run, add local logging to executor

- Pull Docker image explicitly before docker run to avoid silent failures when the image isn't cached locally - Add eprintln logging for job execution mode (docker/bare), image pull status, and job completion status with exit code - Matches the observability the old Elixir runner had via Logger Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SHA: bfb5d896a647a77d92b57654ee7eecfcc9e34890
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-03-11 04:01
Parents: 5f5100f
2 files changed +35 -1
Type
src/runner/executor.rs +30 −1
@@ -24,8 +24,12 @@
match image {
Some(img) => {
eprintln!("Executing (docker): {img} — {command}");
execute_docker(command, img, workspace, env, network, timeout, log_reporter).await
}
None => execute_bare(command, workspace, env, timeout, log_reporter).await,
None => {
eprintln!("Executing (bare): {command}");
execute_bare(command, workspace, env, timeout, log_reporter).await
}
}
}
@@ -39,6 +43,31 @@
timeout: u64,
log_reporter: &LogReporter,
) -> Result<ExecResult, Box<dyn std::error::Error + Send + Sync>> {
// Pull image first to ensure it's available
eprintln!("Pulling image: {image}");
log_reporter
.append(&format!("Pulling image: {image}"))
.await;
let pull_output = std::process::Command::new("docker")
.args(["pull", image])
.output();
match pull_output {
Ok(output) if output.status.success() => {
eprintln!("Image ready: {image}");
}
Ok(output) => {
let stderr = String::from_utf8_lossy(&output.stderr);
let msg = format!("Warning: docker pull failed: {stderr}");
eprintln!("{msg}");
log_reporter.append(&msg).await;
}
Err(e) => {
let msg = format!("Warning: docker pull error: {e}");
eprintln!("{msg}");
log_reporter.append(&msg).await;
}
}
let workspace_str = workspace.to_str().unwrap_or(".");
let mut args = vec![
src/runner/loop_runner.rs +5 −0
@@ -300,5 +300,10 @@
}
};
eprintln!(
"Job {} {status} (exit_code: {})",
&job_id[..8.min(job_id.len())],
exit_code.unwrap_or(-1)
);
update_job_status(client, config, job_id, status, exit_code).await;
}