use anyhow::Result;
use clap::{Parser, Subcommand};
use colored::Colorize;
use std::path::PathBuf;
use github_app_forge::{client, flow, manifest, sink};
#[derive(Parser)]
#[command(
name = "github-app-forge",
version,
about = "Declarative GitHub App lifecycle management via Manifest flow"
)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
Validate {
#[arg(value_name = "MANIFEST")]
manifest: PathBuf,
},
Create {
#[arg(value_name = "MANIFEST")]
manifest: PathBuf,
#[arg(long)]
sink: Option<String>,
#[arg(long)]
no_install: bool,
},
Install {
#[arg(long)]
app: String,
#[arg(long)]
owner: String,
#[arg(long, value_delimiter = ',')]
repos: Vec<String>,
#[arg(long, value_name = "PATH")]
credentials: PathBuf,
},
Rotate {
#[arg(long, value_name = "PATH")]
credentials: PathBuf,
#[arg(long)]
sink: String,
},
Values {
#[arg(long, value_name = "PATH")]
credentials: PathBuf,
},
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Command::Validate { manifest } => {
let m = manifest::load(&manifest)?;
println!("{} {}", "OK".green(), format_args!("manifest valid: {}", m.name));
let json = m.manifest_json("http://localhost:0/cb")?;
let pretty = serde_json::to_string_pretty(&serde_json::from_str::<serde_json::Value>(&json)?)?;
println!("--- GitHub-bound JSON (preview) ---\n{pretty}");
Ok(())
}
Command::Create { manifest, sink, no_install } => {
let m = manifest::load(&manifest)?;
let sink_override = sink.as_deref();
flow::run(&m, sink_override, no_install).await
}
Command::Install { app, owner, repos, credentials } => {
let creds = sink::load_credentials(&credentials)?;
client::install_on_repos(&creds, &owner, &app, &repos).await
}
Command::Rotate { credentials, sink } => {
let creds = sink::load_credentials(&credentials)?;
let sink_cfg = sink::parse_cli_sink(&sink)?;
client::rotate_private_key(&creds, &sink_cfg).await
}
Command::Values { credentials } => {
let creds = sink::load_credentials(&credentials)?;
sink::emit_helmrelease_values(&creds);
Ok(())
}
}
}