mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
CLI: a failed render under run/exec exits 1, like render --queue (part of #1426)
This commit is contained in:
@@ -493,6 +493,9 @@ fn run(cmd: &str, args: &Args, json_out: bool) -> Result<(), Failure> {
|
||||
};
|
||||
let mut b = backend(args, true)?;
|
||||
let r = b.exec(&id, params)?;
|
||||
if let Some(e) = failed_render(&id, &r) {
|
||||
return Err(Failure::Error(e));
|
||||
}
|
||||
let saved = maybe_save(&mut b, args)?;
|
||||
emit(&with_saved(r, saved), json_out);
|
||||
}
|
||||
@@ -515,6 +518,9 @@ fn run(cmd: &str, args: &Args, json_out: bool) -> Result<(), Failure> {
|
||||
};
|
||||
i += 1;
|
||||
let r = b.exec(id, params).map_err(|e| Failure::Error(format!("{id}: {e}")))?;
|
||||
if let Some(e) = failed_render(id, &r) {
|
||||
return Err(Failure::Error(format!("{id}: {e}")));
|
||||
}
|
||||
if !json_out {
|
||||
emit(&r, false);
|
||||
}
|
||||
@@ -637,6 +643,21 @@ fn positional<const N: usize>(args: &Args, usage: &str) -> Result<[String; N], F
|
||||
Ok(std::array::from_fn(|i| args.pos[i].clone()))
|
||||
}
|
||||
|
||||
/// `renderQueue.render` reports a failed item in its result, not as an error. Under `run`/`exec`
|
||||
/// that item fails the command (#1426), as it fails `render --queue`.
|
||||
fn failed_render(id: &str, r: &Value) -> Option<String> {
|
||||
if id != "renderQueue.render" {
|
||||
return None;
|
||||
}
|
||||
let failed: Vec<String> = r["items"]
|
||||
.as_array()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter_map(|i| Some(format!("{}: {}", i["compName"].as_str().unwrap_or("?"), i["status"].get("Failed")?.as_str().unwrap_or("failed"))))
|
||||
.collect();
|
||||
(!failed.is_empty()).then(|| failed.join("; "))
|
||||
}
|
||||
|
||||
fn with_saved(v: Value, saved: Option<String>) -> Value {
|
||||
match saved {
|
||||
None => v,
|
||||
|
||||
@@ -462,6 +462,32 @@ fn mcp_autosave_is_opt_in_and_rejects_invalid_combinations() {
|
||||
std::fs::remove_dir_all(config).unwrap();
|
||||
}
|
||||
|
||||
/// `run`/`exec renderQueue.render` (#1426): a failed item is a command error, exit 1 like
|
||||
/// `render --queue`, not a success with the failure buried in the JSON.
|
||||
#[test]
|
||||
fn a_failed_render_under_run_and_exec_exits_1() {
|
||||
let root = tmp("render-fails");
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
std::fs::create_dir_all(&root).unwrap();
|
||||
// The output's folder is a file, so the encoder cannot open the output.
|
||||
let blocker = root.join("not-a-folder");
|
||||
std::fs::write(&blocker, "x").unwrap();
|
||||
let out = blocker.join("out.gif");
|
||||
let add = json!({"comp": "T", "format": "gif", "output": out.to_str().unwrap()}).to_string();
|
||||
let project = root.join("q.ecproj");
|
||||
let steps = ["comp.new", r#"{"name":"T","width":16,"height":16,"duration":0.1}"#, "layer.newSolid", "{}", "renderQueue.add", &add];
|
||||
ok_json(&[&["run", "--empty", "--save-as", project.to_str().unwrap()][..], &steps[..]].concat());
|
||||
|
||||
let (code, v) = run_json(&[&["run", "--empty"][..], &steps[..], &["renderQueue.render", r#"{"wait":true}"#][..]].concat());
|
||||
assert_eq!(code, 1, "{v}");
|
||||
let e = v["error"].as_str().unwrap_or_else(|| panic!("{v}"));
|
||||
assert!(e.starts_with("renderQueue.render: T: "), "{e}");
|
||||
|
||||
let (code, v) = run_json(&["exec", "renderQueue.render", "--project", project.to_str().unwrap()]);
|
||||
assert_eq!(code, 1, "{v}");
|
||||
assert!(v["error"].as_str().is_some_and(|e| e.starts_with("T: ")), "{v}");
|
||||
}
|
||||
|
||||
/// `render --bitrate` (#440) targets the bitrate in VP9 WebM.
|
||||
#[test]
|
||||
fn render_bitrate_applies_to_vp9_webm() {
|
||||
|
||||
Reference in New Issue
Block a user