fix(missions): create /mission before copying the checkout in

`copy_in` cannot create its own destination, so a mission whose container
had no /mission directory failed its checkout sync outright. In copy mode
that is how the agent gets the code at all, so the phase launched against
an empty tree.

Exec `mkdir -p /mission` as root first. Idempotent, and it costs one exec
on a path that already shells out.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-16 07:25:58 -07:00
co-authored by Claude Opus 5
parent 6e8785f159
commit 85a6038c08
+23
View File
@@ -272,6 +272,29 @@ pub async fn sync_in(container: &str, mission_id: uuid::Uuid) -> Result<(), Stri
.map_err(|e| format!("create empty workspace {}: {e}", repo.display()))?;
}
let docker = crate::container_exec::connect()?;
// `upload_to_container` requires the DESTINATION to exist: uploading into
// `/mission` when the container has no `/mission` fails with
// "404 Could not find the file /mission in container", which reads like a
// missing source file rather than a missing target directory. Nothing else
// creates it — not the image, not the container spec (in copy mode there is
// no `/mission` bind) — so create it here, immediately before the copy that
// depends on it.
let mkdir = [
"mkdir".to_string(),
"-p".to_string(),
CONTAINER_MISSION_DIR.to_string(),
];
if let Err(e) = crate::container_exec::exec_as_root(
&docker,
container,
None,
&mkdir,
std::time::Duration::from_secs(20),
)
.await
{
return Err(format!("create {CONTAINER_MISSION_DIR} in {container}: {e}"));
}
copy_in(&docker, container, &repo, "repo").await
}