kranz_cli/
ticket_notes.rs1use anyhow::{bail, Result};
8use kranz_engine::ticket::Ticket;
9use kranz_engine::ticket_notes::{self, TicketNote};
10use std::path::Path;
11
12const AUTHOR_ENV: &str = "KRANZ_NOTE_AUTHOR";
14
15pub fn note_author() -> String {
18 std::env::var(AUTHOR_ENV)
19 .ok()
20 .map(|a| a.trim().to_string())
21 .filter(|a| !a.is_empty())
22 .unwrap_or_else(|| "operator".to_string())
23}
24
25pub fn cmd_ticket_note(repo: &Path, slug: &str, text: &str) -> Result<String> {
29 let path = Ticket::tickets_dir(repo).join(format!("{slug}.md"));
30 if !path.is_file() {
31 bail!("ticket '{slug}' not found at {}", path.display());
32 }
33 let note = ticket_notes::append_note(repo, slug, ¬e_author(), text)?;
34 Ok(format!("noted on '{slug}' at {}\n", note.ts.to_rfc3339()))
35}
36
37pub fn cmd_ticket_notes(repo: &Path, slug: &str) -> Result<String> {
39 let notes = ticket_notes::read_notes(repo, slug)?;
40 Ok(render_ticket_notes(slug, ¬es))
41}
42
43pub fn render_ticket_notes(slug: &str, notes: &[TicketNote]) -> String {
46 if notes.is_empty() {
47 return format!("no notes on '{slug}'\n");
48 }
49 let mut out = format!("notes on '{slug}' ({}):\n", notes.len());
50 for note in notes {
51 out.push_str(&format!(
52 "{} {}: {}\n",
53 note.ts.to_rfc3339(),
54 note.author,
55 note.text
56 ));
57 }
58 out
59}