195 lines
5.6 KiB
Rust
195 lines
5.6 KiB
Rust
pub mod models;
|
|
|
|
use std::io::Write;
|
|
|
|
use self::models::{MenuChoice, PullRequest, ReviewMenuChoice};
|
|
|
|
#[cfg(test)]
|
|
use mockall::{automock, predicate::*};
|
|
#[cfg_attr(test, automock)]
|
|
pub trait ReviewBackend {
|
|
fn get_prs(&self, review_request: Option<String>) -> eyre::Result<Vec<PullRequest>>;
|
|
fn present_prs(&self, table: String) -> eyre::Result<()>;
|
|
fn present_menu(&self) -> eyre::Result<MenuChoice>;
|
|
fn present_diff(&self, pr: &PullRequest) -> eyre::Result<()>;
|
|
fn present_review_menu(&self, pr: &PullRequest) -> eyre::Result<ReviewMenuChoice>;
|
|
fn approve(&self, pr: &PullRequest) -> eyre::Result<()>;
|
|
fn pr_open_browser(&self, pr: &PullRequest) -> eyre::Result<()>;
|
|
fn clear(&self) -> eyre::Result<()>;
|
|
fn enable_auto_merge(&self, pr: &PullRequest) -> eyre::Result<()>;
|
|
fn present_pr(&self, pr: &PullRequest) -> eyre::Result<()>;
|
|
}
|
|
|
|
pub type DynReviewBackend = std::sync::Arc<dyn ReviewBackend + Send + Sync>;
|
|
|
|
#[derive(Default)]
|
|
pub struct DefaultReviewBackend;
|
|
|
|
impl ReviewBackend for DefaultReviewBackend {
|
|
fn get_prs(&self, review_request: Option<String>) -> eyre::Result<Vec<PullRequest>> {
|
|
let raw_prs = util::shell::run_with_input_and_output(
|
|
&[
|
|
"gh",
|
|
"search",
|
|
"prs",
|
|
"--state=open",
|
|
"--review-requested",
|
|
"@me",
|
|
// review_request.unwrap().as_str(),
|
|
"--label",
|
|
"dependencies",
|
|
//"--checks=pending",
|
|
"--json",
|
|
"repository,number,title",
|
|
],
|
|
"".into(),
|
|
)?;
|
|
|
|
let prs_json = std::str::from_utf8(raw_prs.stdout.as_slice())?;
|
|
|
|
let prs: Vec<PullRequest> = serde_json::from_str(prs_json)?;
|
|
|
|
Ok(prs)
|
|
}
|
|
|
|
fn present_prs(&self, table: String) -> eyre::Result<()> {
|
|
println!("{table}");
|
|
Ok(())
|
|
}
|
|
|
|
fn present_menu(&self) -> eyre::Result<MenuChoice> {
|
|
println!("Menu");
|
|
println!("Begin (b), Exit (q), Menu (m), Search (s), List (l)");
|
|
print!("> ");
|
|
std::io::stdout().flush()?;
|
|
|
|
let mut raw_choice = String::new();
|
|
std::io::stdin().read_line(&mut raw_choice)?;
|
|
let choice = match raw_choice.chars().take(1).next() {
|
|
None => models::MenuChoice::Exit,
|
|
Some(raw_choice) => match raw_choice {
|
|
'b' => models::MenuChoice::Begin,
|
|
'q' => models::MenuChoice::Exit,
|
|
'm' => self.present_menu()?,
|
|
's' => models::MenuChoice::Search,
|
|
'l' => models::MenuChoice::List,
|
|
_ => self.present_menu()?,
|
|
},
|
|
};
|
|
|
|
Ok(choice)
|
|
}
|
|
|
|
fn present_diff(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
util::shell::run(
|
|
&[
|
|
"gh",
|
|
"pr",
|
|
"diff",
|
|
pr.number.to_string().as_str(),
|
|
"--repo",
|
|
pr.repository.name.as_str(),
|
|
],
|
|
None,
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn present_review_menu(&self, pr: &PullRequest) -> eyre::Result<ReviewMenuChoice> {
|
|
println!("");
|
|
println!("Review - Menu");
|
|
println!("Approve (a), Merge (m), Approve and auto-merge (c), Skip (s), List (l), Open in browser (o), Exit (q)");
|
|
print!("> ");
|
|
std::io::stdout().flush()?;
|
|
|
|
let mut raw_choice = String::new();
|
|
std::io::stdin().read_line(&mut raw_choice)?;
|
|
let choice = match raw_choice.chars().take(1).next() {
|
|
None => ReviewMenuChoice::Exit,
|
|
Some(raw_choice) => match raw_choice {
|
|
'q' => ReviewMenuChoice::Exit,
|
|
'l' => ReviewMenuChoice::List,
|
|
'a' => ReviewMenuChoice::Approve,
|
|
'o' => ReviewMenuChoice::Open,
|
|
's' | 'n' => ReviewMenuChoice::Skip,
|
|
'm' => ReviewMenuChoice::Merge,
|
|
'c' => ReviewMenuChoice::ApproveAndMerge,
|
|
_ => self.present_review_menu(pr)?,
|
|
},
|
|
};
|
|
|
|
Ok(choice)
|
|
}
|
|
|
|
fn approve(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
util::shell::run(
|
|
&[
|
|
"gh",
|
|
"pr",
|
|
"review",
|
|
pr.number.to_string().as_str(),
|
|
"--approve",
|
|
"--repo",
|
|
pr.repository.name.as_str(),
|
|
],
|
|
None,
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn pr_open_browser(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
util::shell::run(
|
|
&[
|
|
"gh",
|
|
"pr",
|
|
"view",
|
|
pr.number.to_string().as_str(),
|
|
"-w",
|
|
"--repo",
|
|
pr.repository.name.as_str(),
|
|
],
|
|
None,
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn clear(&self) -> eyre::Result<()> {
|
|
print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
|
|
std::io::stdout().flush()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn enable_auto_merge(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
util::shell::run(
|
|
&[
|
|
"gh",
|
|
"pr",
|
|
"merge",
|
|
pr.number.to_string().as_str(),
|
|
"--auto",
|
|
"--repo",
|
|
pr.repository.name.as_str(),
|
|
],
|
|
None,
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn present_pr(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
println!("repo: {} - title: {}", pr.repository.name, pr.title);
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl DefaultReviewBackend {
|
|
pub fn new() -> Self {
|
|
Self {}
|
|
}
|
|
}
|