diff --git a/crates/github/src/review.rs b/crates/github/src/review.rs index 86f8d92..fe5689e 100644 --- a/crates/github/src/review.rs +++ b/crates/github/src/review.rs @@ -1,5 +1,5 @@ use crate::review_backend::{ - models::{MenuChoice, PullRequest, ReviewMenuChoice}, + models::{MenuChoice, MergeStrategy, PullRequest, ReviewMenuChoice}, DefaultReviewBackend, DynReviewBackend, }; @@ -34,7 +34,11 @@ impl Review { /// 4. Present pr and use delta to view changes /// 5. Approve, open, skip or quit /// 6. Repeat from 4 - fn run(&self, review_requested: Option) -> eyre::Result<()> { + fn run( + &self, + review_requested: Option, + merge_strategy: &Option, + ) -> eyre::Result<()> { let prs = self.backend.get_prs(review_requested.clone())?; let prs_table = Self::generate_prs_table(&prs); @@ -42,16 +46,16 @@ impl Review { match self.backend.present_menu()? { MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit), - MenuChoice::Begin => match self.review(&prs)? { + MenuChoice::Begin => match self.review(&prs, &merge_strategy)? { Some(choice) => match choice { MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit), - MenuChoice::List => return self.run(review_requested.clone()), + MenuChoice::List => return self.run(review_requested.clone(), merge_strategy), _ => eyre::bail!("invalid choice"), }, None => {} }, MenuChoice::Search => todo!(), - MenuChoice::List => return self.run(review_requested.clone()), + MenuChoice::List => return self.run(review_requested.clone(), merge_strategy), } Ok(()) @@ -79,12 +83,16 @@ impl Review { table.to_string() } - fn review(&self, prs: &Vec) -> eyre::Result> { + fn review( + &self, + prs: &Vec, + merge_strategy: &Option, + ) -> eyre::Result> { for pr in prs { self.backend.clear()?; self.backend.present_pr(pr)?; self.review_pr(pr)?; - if let Some(choice) = self.present_pr_menu(pr)? { + if let Some(choice) = self.present_pr_menu(pr, merge_strategy)? { return Ok(Some(choice)); } } @@ -103,13 +111,21 @@ impl Review { Ok(()) } - fn open_browser(&self, pr: &PullRequest) -> eyre::Result> { + fn open_browser( + &self, + pr: &PullRequest, + merge_strategy: &Option, + ) -> eyre::Result> { self.backend.pr_open_browser(pr)?; - self.present_pr_menu(pr) + self.present_pr_menu(pr, merge_strategy) } - fn present_pr_menu(&self, pr: &PullRequest) -> eyre::Result> { + fn present_pr_menu( + &self, + pr: &PullRequest, + merge_strategy: &Option, + ) -> eyre::Result> { self.backend.present_pr(pr)?; match self.backend.present_review_menu(pr)? { @@ -117,33 +133,58 @@ impl Review { ReviewMenuChoice::List => return Ok(Some(MenuChoice::List)), ReviewMenuChoice::Approve => { self.approve(pr)?; - return self.present_pr_menu(pr); + return self.present_pr_menu(pr, merge_strategy); } - ReviewMenuChoice::Open => return self.open_browser(pr), + ReviewMenuChoice::Open => return self.open_browser(pr, merge_strategy), ReviewMenuChoice::Skip => {} - ReviewMenuChoice::Merge => self.merge(pr)?, + ReviewMenuChoice::Merge => self.merge(pr, merge_strategy)?, ReviewMenuChoice::ApproveAndMerge => { self.approve(pr)?; - self.merge(pr)?; + self.merge(pr, merge_strategy)?; } } Ok(None) } - fn merge(&self, pr: &PullRequest) -> eyre::Result<()> { - self.backend.enable_auto_merge(pr); + fn merge(&self, pr: &PullRequest, merge_strategy: &Option) -> eyre::Result<()> { + self.backend.enable_auto_merge(pr, merge_strategy)?; Ok(()) } } impl util::Cmd for Review { fn cmd() -> eyre::Result { - Ok(clap::Command::new("review")) + Ok(clap::Command::new("review") + .arg( + clap::Arg::new("review-requested") + .long("review-requested") + .default_value("@me") + .help("which user or team to pull reviews from"), + ) + .arg( + clap::Arg::new("merge-strategy") + .long("merge-strategy") + .help( + "when merging which merge strategy to use, possible values: [squash, merge]", + ), + )) } - fn exec(_: &clap::ArgMatches) -> eyre::Result<()> { - Self::default().run(Some("lunarway/squad-aura".into())) + fn exec(args: &clap::ArgMatches) -> eyre::Result<()> { + let request_requested = args + .get_one::("review-requested") + .map(|r| r.clone()); + + let squash = args + .get_one::("merge-strategy") + .and_then(|s| match s.as_str() { + "squash" => Some(MergeStrategy::Squash), + "merge" => Some(MergeStrategy::MergeCommit), + _ => None, + }); + + Self::default().run(request_requested, &squash) } } @@ -194,7 +235,7 @@ mod tests { backend.expect_present_prs().times(1).returning(|_| Ok(())); let review = Review::new(std::sync::Arc::new(backend)); - let res = review.run(Some("kjuulh".into())); + let res = review.run(None, None); assert_err::(res) } diff --git a/crates/github/src/review_backend/mod.rs b/crates/github/src/review_backend/mod.rs index 7da84fc..ca7ec4f 100644 --- a/crates/github/src/review_backend/mod.rs +++ b/crates/github/src/review_backend/mod.rs @@ -2,7 +2,7 @@ pub mod models; use std::io::Write; -use self::models::{MenuChoice, PullRequest, ReviewMenuChoice}; +use self::models::{MenuChoice, MergeStrategy, PullRequest, ReviewMenuChoice}; #[cfg(test)] use mockall::{automock, predicate::*}; @@ -16,7 +16,11 @@ pub trait ReviewBackend { 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 enable_auto_merge( + &self, + pr: &PullRequest, + merge_strategy: &Option, + ) -> eyre::Result<()>; fn present_pr(&self, pr: &PullRequest) -> eyre::Result<()>; } @@ -34,11 +38,9 @@ impl ReviewBackend for DefaultReviewBackend { "prs", "--state=open", "--review-requested", - "@me", - // review_request.unwrap().as_str(), + review_request.unwrap_or("@me".into()).as_str(), "--label", "dependencies", - //"--checks=pending", "--json", "repository,number,title", ], @@ -163,19 +165,30 @@ impl ReviewBackend for DefaultReviewBackend { 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, - )?; + fn enable_auto_merge( + &self, + pr: &PullRequest, + merge_strategy: &Option, + ) -> eyre::Result<()> { + let number = pr.number.to_string(); + let mut args = vec![ + "gh", + "pr", + "merge", + number.as_str(), + "--auto", + "--repo", + pr.repository.name.as_str(), + ]; + + if let Some(merge_strategy) = merge_strategy { + match merge_strategy { + MergeStrategy::Squash => args.push("--squash"), + MergeStrategy::MergeCommit => args.push("--merge"), + } + } + + util::shell::run(args.as_slice(), None)?; Ok(()) } diff --git a/crates/github/src/review_backend/models.rs b/crates/github/src/review_backend/models.rs index e50fffb..2d06dea 100644 --- a/crates/github/src/review_backend/models.rs +++ b/crates/github/src/review_backend/models.rs @@ -13,6 +13,12 @@ pub struct PullRequest { pub repository: Repository, } +#[derive(Debug, Clone)] +pub enum MergeStrategy { + Squash, + MergeCommit, +} + pub enum MenuChoice { Exit, Begin,