@@ -46,6 +46,36 @@
#[arg(long)]
labels: Option<String>,
},
/// Close an issue
Close {
/// Issue number
number: u32,
/// Repository (org/repo)
#[arg(long)]
repo: Option<String>,
},
/// Reopen a closed issue
Reopen {
/// Issue number
number: u32,
/// Repository (org/repo)
#[arg(long)]
repo: Option<String>,
},
/// Edit an issue's title or body
Edit {
/// Issue number
number: u32,
/// Repository (org/repo)
#[arg(long)]
repo: Option<String>,
/// New title
#[arg(long)]
title: Option<String>,
/// New body
#[arg(long)]
body: Option<String>,
},
}
#[derive(Debug, Deserialize)]
@@ -81,5 +111,13 @@
body,
labels,
} => create(repo.as_deref(), &title, &body, labels.as_deref()).await,
IssueCommand::Close { number, repo } => close_issue(repo.as_deref(), number).await,
IssueCommand::Reopen { number, repo } => reopen_issue(repo.as_deref(), number).await,
IssueCommand::Edit {
number,
repo,
title,
body,
} => edit_issue(repo.as_deref(), number, title.as_deref(), body.as_deref()).await,
}
}
@@ -226,5 +264,64 @@
);
}
Ok(())
}
async fn close_issue(repo: Option<&str>, number: u32) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_config()?;
let (org, name) = config::resolve_repo(repo)?;
let _resp: serde_json::Value = client
.patch(
&format!("/{org}/{name}/issues/{number}"),
&serde_json::json!({"state": "closed"}),
)
.await?;
output::success(&format!("Closed issue #{number}"));
Ok(())
}
async fn reopen_issue(repo: Option<&str>, number: u32) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_config()?;
let (org, name) = config::resolve_repo(repo)?;
let _resp: serde_json::Value = client
.patch(
&format!("/{org}/{name}/issues/{number}"),
&serde_json::json!({"state": "open"}),
)
.await?;
output::success(&format!("Reopened issue #{number}"));
Ok(())
}
async fn edit_issue(
repo: Option<&str>,
number: u32,
title: Option<&str>,
body: Option<&str>,
) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_config()?;
let (org, name) = config::resolve_repo(repo)?;
let mut payload = serde_json::Map::new();
if let Some(t) = title {
payload.insert("title".into(), serde_json::json!(t));
}
if let Some(b) = body {
payload.insert("body".into(), serde_json::json!(b));
}
if payload.is_empty() {
output::warn("Nothing to update — specify --title or --body");
return Ok(());
}
let _resp: serde_json::Value = client
.patch(
&format!("/{org}/{name}/issues/{number}"),
&serde_json::Value::Object(payload),
)
.await?;
output::success(&format!("Updated issue #{number}"));
Ok(())
}