From f3adc2ffa5b34f943120832568c667a29c952835 Mon Sep 17 00:00:00 2001 From: clabby Date: Mon, 4 Nov 2024 11:28:12 -0500 Subject: [PATCH 1/3] feat: Add issue + assignee select in PR submission update --- Cargo.lock | 266 ++----------------------------- Cargo.toml | 2 +- src/subcommands/remote/submit.rs | 103 +++++++++++- 3 files changed, 109 insertions(+), 262 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22ffbc7..d899c0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,15 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -113,33 +104,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "aws-lc-rs" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" -dependencies = [ - "aws-lc-sys", - "mirai-annotations", - "paste", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", - "libc", - "paste", -] - [[package]] name = "backtrace" version = "0.3.71" @@ -167,29 +131,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.79", - "which", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -231,15 +172,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -259,17 +191,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "4.5.19" @@ -333,15 +254,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "cmake" -version = "0.1.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.2" @@ -419,12 +331,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "dyn-clone" version = "1.0.17" @@ -474,12 +380,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures" version = "0.3.31" @@ -621,12 +521,6 @@ dependencies = [ "url", ] -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "hashbrown" version = "0.15.0" @@ -645,15 +539,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "http" version = "1.1.0" @@ -841,15 +726,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" @@ -889,18 +765,6 @@ dependencies = [ "simple_asn1", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.159" @@ -921,16 +785,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "libloading" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - [[package]] name = "libssh2-sys" version = "0.3.0" @@ -985,12 +839,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.4" @@ -1024,12 +872,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "newline-converter" version = "0.3.0" @@ -1039,16 +881,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nu-ansi-term" version = "0.50.1" @@ -1103,9 +935,9 @@ dependencies = [ [[package]] name = "octocrab" -version = "0.41.0" +version = "0.41.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dada65f156e4100376ceeaeadae1b4d35ab9cdf4236cfc92fde0d06b930c3b7" +checksum = "e2dfd11f6efbd39491d71a3864496f0b6f45e2d01b73b26c55d631c4e0dafaef" dependencies = [ "arc-swap", "async-trait", @@ -1134,7 +966,7 @@ dependencies = [ "serde_urlencoded", "snafu", "tokio", - "tower 0.4.13", + "tower", "tower-http", "tracing", "url", @@ -1190,12 +1022,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "pem" version = "3.0.4" @@ -1262,16 +1088,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "prettyplease" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" -dependencies = [ - "proc-macro2", - "syn 2.0.79", -] - [[package]] name = "proc-macro2" version = "1.0.86" @@ -1299,35 +1115,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "regex" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - [[package]] name = "ring" version = "0.17.8" @@ -1349,12 +1136,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustix" version = "0.38.37" @@ -1374,9 +1155,9 @@ version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ - "aws-lc-rs", "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1417,7 +1198,6 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1446,9 +1226,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "secrecy" -version = "0.8.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" dependencies = [ "zeroize", ] @@ -1880,23 +1660,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.5.1" @@ -1907,8 +1670,11 @@ dependencies = [ "futures-util", "pin-project-lite", "sync_wrapper", + "tokio", + "tokio-util", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -1924,7 +1690,7 @@ dependencies = [ "http-body", "iri-string", "pin-project-lite", - "tower 0.5.1", + "tower", "tower-layer", "tower-service", "tracing", @@ -2113,18 +1879,6 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 1ee0e31..8741739 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ publish = false # Core tokio = { version = "1.39", features = ["full"] } git2 = "0.19" -octocrab = "0.41" +octocrab = "0.41.2" thiserror = "1.0" # CLI diff --git a/src/subcommands/remote/submit.rs b/src/subcommands/remote/submit.rs index 874ecad..50f4a60 100644 --- a/src/subcommands/remote/submit.rs +++ b/src/subcommands/remote/submit.rs @@ -10,6 +10,7 @@ use clap::Args; use git2::BranchType; use nu_ansi_term::Color; use octocrab::{issues::IssueHandler, models::CommentId, pulls::PullRequestHandler, Octocrab}; +use std::fmt::Display; /// CLI arguments for the `submit` subcommand. #[derive(Debug, Clone, Eq, PartialEq, Args)] @@ -28,6 +29,7 @@ impl SubmitCmd { .build()?; let (owner, repo) = ctx.owner_and_repository()?; let mut pulls = gh_client.pulls(&owner, &repo); + let mut issues = gh_client.issues(&owner, &repo); // Resolve the active stack. let stack = ctx.discover_stack()?; @@ -41,13 +43,12 @@ impl SubmitCmd { "\nšŸ™ Submitting changes to remote `{}`...", Color::Blue.paint("origin") ); - self.submit_stack(&mut ctx, &mut pulls, &owner, &repo) + self.submit_stack(&mut ctx, &mut pulls, &mut issues, &owner, &repo) .await?; // Update the stack navigation comments on the PRs. println!("\nšŸ“ Updating stack navigation comments..."); - self.update_pr_comments(&mut ctx, gh_client.issues(owner, repo), &stack) - .await?; + self.update_pr_comments(&mut ctx, issues, &stack).await?; println!("\nšŸ§™šŸ’« All pull requests up to date."); Ok(()) @@ -88,6 +89,7 @@ impl SubmitCmd { &self, ctx: &mut StContext<'_>, pulls: &mut PullRequestHandler<'_>, + issues: &mut IssueHandler<'_>, owner: &str, repo: &str, ) -> StResult<()> { @@ -152,7 +154,7 @@ impl SubmitCmd { ctx.repository.push_branch(branch, "origin", self.force)?; // Prompt the user for PR metadata. - let metadata = Self::prompt_pr_metadata(branch, parent)?; + let metadata = Self::prompt_pr_metadata(branch, parent, issues).await?; // Submit PR. let pr_info = pulls @@ -162,6 +164,17 @@ impl SubmitCmd { .send() .await?; + // Update labels and assignees, if declared. + if metadata.labels.is_some() || metadata.assignees.is_some() { + if let Some(ref labels) = metadata.labels { + issues.add_labels(pr_info.number, labels).await?; + } + if let Some(ref assignees) = metadata.assignees { + let assignees = assignees.iter().map(AsRef::as_ref).collect::>(); + issues.add_assignees(pr_info.number, &assignees).await?; + } + } + // Update the tracked branch with the remote information. tracked_branch.remote = Some(RemoteMetadata::new(pr_info.number)); @@ -230,7 +243,11 @@ impl SubmitCmd { } /// Prompts the user for metadata about the PR during the initial submission process. - fn prompt_pr_metadata(branch_name: &str, parent_name: &str) -> StResult { + async fn prompt_pr_metadata( + branch_name: &str, + parent_name: &str, + issues: &mut IssueHandler<'_>, + ) -> StResult { let title = inquire::Text::new( format!( "Title of pull request (`{}` -> `{}`):", @@ -247,10 +264,66 @@ impl SubmitCmd { .with_default(true) .prompt()?; + let set_labels = + inquire::Confirm::new("Would you like to set labels for the pull request?") + .with_default(false) + .prompt()?; + let labels = if set_labels { + let labels = issues.list_labels_for_repo().send().await?.take_items(); + let display_labels = labels + .iter() + .map(|label| { + let color_hex = u32::from_str_radix(&label.color, 16).map_err(|_| { + StError::DecodingError("Failed to decode label color".to_string()) + })?; + let (r, g, b) = ( + (color_hex >> 16 & 0xff) as u8, + (color_hex >> 8 & 0xff) as u8, + (color_hex & 0xff) as u8, + ); + let color = Color::Rgb(r, g, b); + Ok(SelectLabel { + name: label.name.clone(), + formatted: color.paint(label.name.as_str()).to_string(), + }) + }) + .collect::>>()?; + + let selected_labels = + inquire::MultiSelect::new("Select labels for the pull request:", display_labels) + .prompt()?; + + Some( + selected_labels + .into_iter() + .map(|label| label.name) + .collect(), + ) + } else { + None + }; + + let set_assignee = inquire::Confirm::new("Would you like to assign the pull request?") + .with_default(false) + .prompt()?; + let assignees = set_assignee + .then(|| { + let answer = inquire::Text::new("Assignees (comma-separated):") + .prompt()? + .replace(' ', "") + .split(',') + .map(ToString::to_string) + .collect(); + Ok::<_, StError>(answer) + }) + .transpose()?; + Ok(PRCreationMetadata { title, body, is_draft, + labels, + assignees, }) } @@ -290,6 +363,7 @@ impl SubmitCmd { } /// Metadata about pull request creation. +#[derive(Debug)] struct PRCreationMetadata { /// Title of the pull request. title: String, @@ -297,4 +371,23 @@ struct PRCreationMetadata { body: String, /// Whether or not the pull request is a draft. is_draft: bool, + /// Labels to apply to the pull request. + labels: Option>, + /// Assignees for the pull request. + assignees: Option>, +} + +/// A colored label for display in the terminal. +#[derive(Debug)] +struct SelectLabel { + /// The raw name of the label. + name: String, + /// The formatted name of the label. + formatted: String, +} + +impl Display for SelectLabel { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.formatted) + } } From 74c3173cf9eabcad4f886c25fd3d059f4297fcc7 Mon Sep 17 00:00:00 2001 From: clabby Date: Mon, 4 Nov 2024 12:09:24 -0500 Subject: [PATCH 2/3] :broom: --- src/subcommands/remote/submit.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/subcommands/remote/submit.rs b/src/subcommands/remote/submit.rs index 50f4a60..66bc1de 100644 --- a/src/subcommands/remote/submit.rs +++ b/src/subcommands/remote/submit.rs @@ -165,14 +165,12 @@ impl SubmitCmd { .await?; // Update labels and assignees, if declared. - if metadata.labels.is_some() || metadata.assignees.is_some() { - if let Some(ref labels) = metadata.labels { - issues.add_labels(pr_info.number, labels).await?; - } - if let Some(ref assignees) = metadata.assignees { - let assignees = assignees.iter().map(AsRef::as_ref).collect::>(); - issues.add_assignees(pr_info.number, &assignees).await?; - } + if let Some(ref labels) = metadata.labels { + issues.add_labels(pr_info.number, labels).await?; + } + if let Some(ref assignees) = metadata.assignees { + let assignees = assignees.iter().map(AsRef::as_ref).collect::>(); + issues.add_assignees(pr_info.number, &assignees).await?; } // Update the tracked branch with the remote information. From ef96fc0ccbd2c2783b571f80de5073501816ecf5 Mon Sep 17 00:00:00 2001 From: clabby Date: Mon, 4 Nov 2024 12:12:43 -0500 Subject: [PATCH 3/3] lint --- src/ctx/actions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ctx/actions.rs b/src/ctx/actions.rs index eb92930..0e67af4 100644 --- a/src/ctx/actions.rs +++ b/src/ctx/actions.rs @@ -9,7 +9,7 @@ use git2::BranchType; use nu_ansi_term::Color; use octocrab::{models::IssueState, pulls::PullRequestHandler}; -impl<'a> StContext<'a> { +impl StContext<'_> { /// Restacks the branch onto the parent branch passed. /// /// Returns `true` if the branch was restacked, `false` otherwise.