Compare commits
1 Commits
feature/re
...
35b50d802a
| Author | SHA1 | Date | |
|---|---|---|---|
| 35b50d802a |
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -17,12 +17,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.21.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -216,7 +210,6 @@ dependencies = [
|
|||||||
name = "github"
|
name = "github"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
|
||||||
"clap",
|
"clap",
|
||||||
"comfy-table",
|
"comfy-table",
|
||||||
"dirs",
|
"dirs",
|
||||||
@@ -225,7 +218,6 @@ dependencies = [
|
|||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
|
||||||
"util",
|
"util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ serde = { version = "1.0.152", features = ["derive"] }
|
|||||||
serde_json = "1.0.91"
|
serde_json = "1.0.91"
|
||||||
comfy-table = "6.1.4"
|
comfy-table = "6.1.4"
|
||||||
pretty_assertions = "1.3.0"
|
pretty_assertions = "1.3.0"
|
||||||
base64 = "0.21.0"
|
|
||||||
thiserror = "1.0.38"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
mockall = "0.11.2"
|
mockall = "0.11.2"
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use crate::review_backend::{
|
use crate::review_backend::{models::PullRequest, DefaultReviewBackend, DynReviewBackend};
|
||||||
models::{MenuChoice, PullRequest, ReviewMenuChoice},
|
|
||||||
DefaultReviewBackend, DynReviewBackend,
|
|
||||||
};
|
|
||||||
|
|
||||||
use comfy_table::{presets::UTF8_HORIZONTAL_ONLY, Cell, Table};
|
use comfy_table::{presets::UTF8_HORIZONTAL_ONLY, Cell, Row, Table};
|
||||||
use thiserror::Error;
|
#[cfg(test)]
|
||||||
|
use mockall::{automock, mock, predicate::*};
|
||||||
|
|
||||||
pub struct Review {
|
pub struct Review {
|
||||||
backend: DynReviewBackend,
|
backend: DynReviewBackend,
|
||||||
@@ -16,43 +14,24 @@ impl Default for Review {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum ReviewErrors {
|
|
||||||
#[error("user chose to exit")]
|
|
||||||
UserExit,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Review {
|
impl Review {
|
||||||
fn new(backend: DynReviewBackend) -> Self {
|
fn new(backend: DynReviewBackend) -> Self {
|
||||||
Self { backend }
|
Self { backend }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Workflow
|
// Workflow
|
||||||
/// 1. Fetch list of repos
|
// 1. Fetch list of repos
|
||||||
/// 2. Present menu
|
// 2. Present menu
|
||||||
/// 3. Choose begin quick review
|
// 3. Choose begin quick review
|
||||||
/// 4. Present pr and use delta to view changes
|
// 4. Present pr and use delta to view changes
|
||||||
/// 5. Approve, open, skip or quit
|
// 5. Approve, open, skip or quit
|
||||||
/// 6. Repeat from 4
|
// 6. Repeat from 4
|
||||||
fn run(&self, review_requested: Option<String>) -> eyre::Result<()> {
|
fn run(&self, review_requested: Option<String>) -> eyre::Result<()> {
|
||||||
let prs = self.backend.get_prs(review_requested.clone())?;
|
let prs = self.backend.get_prs(review_requested)?;
|
||||||
|
|
||||||
let prs_table = Self::generate_prs_table(&prs);
|
let prs_table = Self::generate_prs_table(&prs);
|
||||||
self.backend.present_prs(prs_table)?;
|
|
||||||
|
|
||||||
match self.backend.present_menu()? {
|
self.backend.present_prs(prs_table)?;
|
||||||
MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit),
|
|
||||||
MenuChoice::Begin => match self.review(&prs)? {
|
|
||||||
Some(choice) => match choice {
|
|
||||||
MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit),
|
|
||||||
MenuChoice::List => return self.run(review_requested.clone()),
|
|
||||||
_ => eyre::bail!("invalid choice"),
|
|
||||||
},
|
|
||||||
None => {}
|
|
||||||
},
|
|
||||||
MenuChoice::Search => todo!(),
|
|
||||||
MenuChoice::List => return self.run(review_requested.clone()),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -63,78 +42,17 @@ impl Review {
|
|||||||
.load_preset(UTF8_HORIZONTAL_ONLY)
|
.load_preset(UTF8_HORIZONTAL_ONLY)
|
||||||
.set_content_arrangement(comfy_table::ContentArrangement::Dynamic)
|
.set_content_arrangement(comfy_table::ContentArrangement::Dynamic)
|
||||||
.set_header(vec![
|
.set_header(vec![
|
||||||
Cell::new("repo").add_attribute(comfy_table::Attribute::Bold),
|
Cell::new("repo"),
|
||||||
Cell::new("title").add_attribute(comfy_table::Attribute::Bold),
|
Cell::new("title"),
|
||||||
Cell::new("number").add_attribute(comfy_table::Attribute::Bold),
|
Cell::new("number"),
|
||||||
])
|
])
|
||||||
.add_rows(prs.iter().take(20).map(|pr| {
|
.add_rows(prs.iter().map(|pr| {
|
||||||
let pr = pr.clone();
|
let pr = pr.clone();
|
||||||
vec![
|
vec![pr.repository.name, pr.title, pr.number.to_string()]
|
||||||
Cell::new(pr.repository.name).fg(comfy_table::Color::Green),
|
|
||||||
Cell::new(pr.title),
|
|
||||||
Cell::new(pr.number.to_string()),
|
|
||||||
]
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
table.to_string()
|
table.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn review(&self, prs: &Vec<PullRequest>) -> eyre::Result<Option<MenuChoice>> {
|
|
||||||
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)? {
|
|
||||||
return Ok(Some(choice));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn review_pr(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
||||||
self.backend.present_diff(pr)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn approve(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
||||||
self.backend.approve(pr)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open_browser(&self, pr: &PullRequest) -> eyre::Result<Option<MenuChoice>> {
|
|
||||||
self.backend.pr_open_browser(pr)?;
|
|
||||||
|
|
||||||
self.present_pr_menu(pr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn present_pr_menu(&self, pr: &PullRequest) -> eyre::Result<Option<MenuChoice>> {
|
|
||||||
self.backend.present_pr(pr)?;
|
|
||||||
|
|
||||||
match self.backend.present_review_menu(pr)? {
|
|
||||||
ReviewMenuChoice::Exit => return Ok(Some(MenuChoice::Exit)),
|
|
||||||
ReviewMenuChoice::List => return Ok(Some(MenuChoice::List)),
|
|
||||||
ReviewMenuChoice::Approve => {
|
|
||||||
self.approve(pr)?;
|
|
||||||
return self.present_pr_menu(pr);
|
|
||||||
}
|
|
||||||
ReviewMenuChoice::Open => return self.open_browser(pr),
|
|
||||||
ReviewMenuChoice::Skip => {}
|
|
||||||
ReviewMenuChoice::Merge => self.merge(pr)?,
|
|
||||||
ReviewMenuChoice::ApproveAndMerge => {
|
|
||||||
self.approve(pr)?;
|
|
||||||
self.merge(pr)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn merge(&self, pr: &PullRequest) -> eyre::Result<()> {
|
|
||||||
self.backend.enable_auto_merge(pr);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl util::Cmd for Review {
|
impl util::Cmd for Review {
|
||||||
@@ -149,16 +67,11 @@ impl util::Cmd for Review {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::review_backend::{
|
use crate::review_backend::{models::Repository, MockReviewBackend};
|
||||||
models::{self, Repository},
|
|
||||||
MockReviewBackend,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use base64::Engine;
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
use mockall::predicate::eq;
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_fetch_prs() {
|
fn can_fetch_prs() {
|
||||||
@@ -186,17 +99,12 @@ mod tests {
|
|||||||
.times(1)
|
.times(1)
|
||||||
.returning(move |_| Ok(backendprs.clone()));
|
.returning(move |_| Ok(backendprs.clone()));
|
||||||
|
|
||||||
backend
|
|
||||||
.expect_present_menu()
|
|
||||||
.times(1)
|
|
||||||
.returning(|| Ok(models::MenuChoice::Exit));
|
|
||||||
|
|
||||||
backend.expect_present_prs().times(1).returning(|_| Ok(()));
|
backend.expect_present_prs().times(1).returning(|_| Ok(()));
|
||||||
|
|
||||||
let review = Review::new(std::sync::Arc::new(backend));
|
let review = Review::new(std::sync::Arc::new(backend));
|
||||||
let res = review.run(Some("kjuulh".into()));
|
review
|
||||||
|
.run(Some("kjuulh".into()))
|
||||||
assert_err::<ReviewErrors, _>(res)
|
.expect("to return a list of pull requests");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -217,41 +125,16 @@ mod tests {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
let expected_table = "─────────────────────────────────────────────
|
||||||
|
repo title number
|
||||||
|
═════════════════════════════════════════════
|
||||||
|
some-name some-title 0
|
||||||
|
─────────────────────────────────────────────
|
||||||
|
some-other-name some-other-title 1
|
||||||
|
─────────────────────────────────────────────";
|
||||||
|
|
||||||
let expected_table = "4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAChtbMW0gcmVwbyAgICAgICAgICAgIBtbMG0gG1sxbSB0aXRsZSAgICAgICAgICAgIBtbMG0gG1sxbSBudW1iZXIgG1swbQrilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAKG1szODs1OzEwbSBzb21lLW5hbWUgICAgICAgG1szOW0gIHNvbWUtdGl0bGUgICAgICAgICAwICAgICAgCuKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAobWzM4OzU7MTBtIHNvbWUtb3RoZXItbmFtZSAbWzM5bSAgc29tZS1vdGhlci10aXRsZSAgIDEgICAgICAK4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA";
|
|
||||||
let output = Review::generate_prs_table(&prs);
|
let output = Review::generate_prs_table(&prs);
|
||||||
|
|
||||||
compare_tables(output, expected_table)
|
assert_eq!(output, expected_table.to_string())
|
||||||
}
|
|
||||||
|
|
||||||
fn compare_tables(actual: String, snapshot: &str) {
|
|
||||||
let b64 = base64::engine::general_purpose::STANDARD_NO_PAD;
|
|
||||||
let snapshot = snapshot.clone().replace("\n", "").replace(" ", "");
|
|
||||||
println!("expected");
|
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
std::str::from_utf8(
|
|
||||||
b64.decode(&snapshot)
|
|
||||||
.expect("table to be decodeable")
|
|
||||||
.as_slice()
|
|
||||||
)
|
|
||||||
.expect("to be utf8")
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("actual");
|
|
||||||
println!("{actual}");
|
|
||||||
|
|
||||||
assert_eq!(b64.encode(actual), snapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_err<TExpected, TVal>(res: eyre::Result<TVal>) {
|
|
||||||
match res {
|
|
||||||
Err(e) => {
|
|
||||||
if !e.is::<ReviewErrors>() {
|
|
||||||
panic!("invalid error: {}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("error not thrown"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
pub mod models;
|
pub mod models;
|
||||||
|
|
||||||
use std::io::Write;
|
use self::models::PullRequest;
|
||||||
|
|
||||||
use self::models::{MenuChoice, PullRequest, ReviewMenuChoice};
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use mockall::{automock, predicate::*};
|
use mockall::{automock, predicate::*};
|
||||||
@@ -10,14 +8,6 @@ use mockall::{automock, predicate::*};
|
|||||||
pub trait ReviewBackend {
|
pub trait ReviewBackend {
|
||||||
fn get_prs(&self, review_request: Option<String>) -> eyre::Result<Vec<PullRequest>>;
|
fn get_prs(&self, review_request: Option<String>) -> eyre::Result<Vec<PullRequest>>;
|
||||||
fn present_prs(&self, table: String) -> eyre::Result<()>;
|
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>;
|
pub type DynReviewBackend = std::sync::Arc<dyn ReviewBackend + Send + Sync>;
|
||||||
@@ -37,7 +27,7 @@ impl ReviewBackend for DefaultReviewBackend {
|
|||||||
review_request.unwrap().as_str(),
|
review_request.unwrap().as_str(),
|
||||||
"--label",
|
"--label",
|
||||||
"dependencies",
|
"dependencies",
|
||||||
//"--checks=pending",
|
"--checks=pending",
|
||||||
"--json",
|
"--json",
|
||||||
"repository,number,title",
|
"repository,number,title",
|
||||||
],
|
],
|
||||||
@@ -52,136 +42,6 @@ impl ReviewBackend for DefaultReviewBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn present_prs(&self, table: String) -> eyre::Result<()> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,20 +12,3 @@ pub struct PullRequest {
|
|||||||
pub number: usize,
|
pub number: usize,
|
||||||
pub repository: Repository,
|
pub repository: Repository,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MenuChoice {
|
|
||||||
Exit,
|
|
||||||
Begin,
|
|
||||||
Search,
|
|
||||||
List,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ReviewMenuChoice {
|
|
||||||
Exit,
|
|
||||||
List,
|
|
||||||
Approve,
|
|
||||||
Open,
|
|
||||||
Skip,
|
|
||||||
Merge,
|
|
||||||
ApproveAndMerge,
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user