ref:1d3e677f097079897bd0d4d82ad436c6a9aabce5

feat(epic): add `anvil epic auto-close` subcommand

Toggle the per-epic auto_close_on_complete flag from the CLI: anvil epic auto-close 107 --on anvil epic auto-close 107 --off --on and --off are mutually exclusive (clap conflicts_with). Wraps the existing PATCH /:org/:repo/issues/:number endpoint with the new auto_close_on_complete field landed on the server side in fangorn/anvil 4581edc. Companion CLI work for the per-epic auto-close toggle in fangorn/anvil#118.
SHA: 1d3e677f097079897bd0d4d82ad436c6a9aabce5
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-05-01 14:34
Parents: 94b2339
1 files changed +49 -0
Type
src/commands/epic.rs +49 −0
@@ -80,6 +80,23 @@
#[arg(long)]
unmark: bool,
},
/// Toggle whether closing the last open child auto-closes the epic
/// (and reopening one auto-reopens it). On by default.
#[command(name = "auto-close")]
AutoClose {
/// Epic issue number
number: u32,
/// Repository (org/repo)
#[arg(long)]
repo: Option<String>,
/// Set on. Mutually exclusive with --off.
#[arg(long, conflicts_with = "off")]
on: bool,
/// Set off. Mutually exclusive with --on.
#[arg(long)]
off: bool,
},
}
#[derive(Debug, Deserialize)]
@@ -127,5 +144,11 @@
repo,
unmark,
} => mark(repo.as_deref(), number, unmark).await,
EpicCommand::AutoClose {
number,
repo,
on,
off,
} => set_auto_close(repo.as_deref(), number, on, off).await,
}
}
@@ -319,5 +342,31 @@
.await?;
output::success(&format!("Removed child {child} from epic #{epic_number}"));
Ok(())
}
async fn set_auto_close(
repo: Option<&str>,
number: u32,
on: bool,
off: bool,
) -> Result<(), Box<dyn std::error::Error>> {
if !on && !off {
return Err("Pass --on or --off".into());
}
let client = Client::from_config()?;
let (org, name) = config::resolve_repo(repo)?;
let value = on && !off;
let _resp: serde_json::Value = client
.patch(
&format!("/{org}/{name}/issues/{number}"),
&serde_json::json!({"auto_close_on_complete": value}),
)
.await?;
let label = if value { "on" } else { "off" };
output::success(&format!("Set auto-close {label} for epic #{number}"));
Ok(())
}