use std::process::Command; use anyhow::Context as _; trait SuccessExt { fn success(&mut self) -> anyhow::Result<()>; } impl SuccessExt for Command { fn success(&mut self) -> anyhow::Result<()> { if !self.status()?.success() { anyhow::bail!("Command returned unsuccessfully"); } Ok(()) } } pub struct RenderedTree { repo_dir: std::path::PathBuf, dot_file: std::path::PathBuf, svg_file: std::path::PathBuf, } pub async fn render( _ctx: &crate::Context, tree: &crate::tree::Tree, ) -> anyhow::Result { let repo_dir = std::path::PathBuf::from("render-git"); if repo_dir.is_dir() { log::info!("Found old {repo_dir:?} repository, removing..."); std::fs::remove_dir_all(&repo_dir).context("Failed to remove stale render repository")?; } std::fs::create_dir(&repo_dir).context("Failed creating directory for rendered graph")?; let dot_file = repo_dir.join("techtree.dot"); let svg_file = repo_dir.join("techtree.svg"); let dot_source = tree.to_dot(); std::fs::write(&dot_file, dot_source.as_bytes()) .context("Failed to write `dot` source file")?; Command::new("dot") .args(["-T", "svg"]) .arg("-o") .arg(&svg_file) .arg(&dot_file) .success() .context("Failed to generate svg graph from dot source")?; Ok(RenderedTree { repo_dir, dot_file, svg_file, }) } pub async fn publish(ctx: &crate::Context, rendered: &RenderedTree) -> anyhow::Result<()> { Command::new("git") .arg("-C") .arg(&rendered.repo_dir) .arg("init") .arg("--initial-branch=render") .arg("--quiet") .success() .context("Failed to initialize render repository")?; Command::new("git") .arg("-C") .arg(&rendered.repo_dir) .args(["config", "user.email", "git@fa-fo.de"]) .success() .context("Failed to configure identity for render repo")?; Command::new("git") .arg("-C") .arg(&rendered.repo_dir) .args(["config", "user.name", "Forgejo Actions"]) .success() .context("Failed to configure identity for render repo")?; Command::new("git") .arg("-C") .arg(&rendered.repo_dir) .arg("add") .arg(rendered.dot_file.strip_prefix(&rendered.repo_dir).unwrap()) .arg(rendered.svg_file.strip_prefix(&rendered.repo_dir).unwrap()) .success() .context("Failed to add generated graph files to git index")?; Command::new("git") .arg("-C") .arg(&rendered.repo_dir) .arg("commit") .args(["-m", &format!("Updated techtree at {}", ctx.timestamp)]) .success() .context("Failed to add generated graph files to git index")?; Command::new("git") .arg("-C") .arg(&rendered.repo_dir) .arg("push") .arg("--force") .arg("--quiet") .arg(ctx.repo_auth_url.to_string()) .arg("HEAD:refs/heads/render") .status() .context("Failed to push rendered graph to forgejo repository")?; Ok(()) }