소스 검색

implement the ready & author shortcuts to swap waiting-on labels

Llandy Riveron Del Risco 3 년 전
부모
커밋
89daaa7840
2개의 변경된 파일118개의 추가작업 그리고 0개의 파일을 삭제
  1. 2 0
      src/handlers.rs
  2. 116 0
      src/handlers/shortcut.rs

+ 2 - 0
src/handlers.rs

@@ -38,6 +38,7 @@ mod prioritize;
 mod relabel;
 mod review_submitted;
 mod rustc_commits;
+mod shortcut;
 
 pub async fn handle(ctx: &Context, event: &Event) -> Vec<HandlerError> {
     let config = config::get(&ctx.github, event.repo_name()).await;
@@ -240,6 +241,7 @@ command_handlers! {
     prioritize: Prioritize,
     relabel: Relabel,
     major_change: Second,
+    shortcut: Shortcut,
     close: Close,
 }
 

+ 116 - 0
src/handlers/shortcut.rs

@@ -0,0 +1,116 @@
+//! Purpose: Allow the use of single words shortcut to do specific actions on GitHub via comments.
+//!
+//! Parsing is done in the `parser::command::shortcut` module.
+
+use crate::{
+    config::ShortcutConfig,
+    github::{Event, Label},
+    handlers::Context,
+    interactions::ErrorComment,
+};
+use parser::command::shortcut::ShortcutCommand;
+
+pub(super) async fn handle_command(
+    ctx: &Context,
+    _config: &ShortcutConfig,
+    event: &Event,
+    input: ShortcutCommand,
+) -> anyhow::Result<()> {
+    let issue = event.issue().unwrap();
+    // NOTE: if shortcuts available to issues are created, they need to be allowed here
+    if !issue.is_pr() {
+        let msg = format!("The \"{:?}\" shortcut only works on pull requests.", input);
+        let cmnt = ErrorComment::new(&issue, msg);
+        cmnt.post(&ctx.github).await?;
+        return Ok(());
+    }
+
+    let mut issue_labels = issue.labels().to_owned();
+    let waiting_on_review = "S-waiting-on-review";
+    let waiting_on_author = "S-waiting-on-author";
+
+    match input {
+        ShortcutCommand::Ready => {
+            if assign_and_remove_label(&mut issue_labels, waiting_on_review, waiting_on_author)
+                .is_some()
+            {
+                return Ok(());
+            }
+            issue.set_labels(&ctx.github, issue_labels).await?;
+        }
+        ShortcutCommand::Author => {
+            if assign_and_remove_label(&mut issue_labels, waiting_on_author, waiting_on_review)
+                .is_some()
+            {
+                return Ok(());
+            }
+            issue.set_labels(&ctx.github, issue_labels).await?;
+        }
+    }
+
+    Ok(())
+}
+
+fn assign_and_remove_label(
+    issue_labels: &mut Vec<Label>,
+    assign: &str,
+    remove: &str,
+) -> Option<()> {
+    if issue_labels.iter().any(|label| label.name == assign) {
+        return Some(());
+    }
+
+    if let Some(index) = issue_labels.iter().position(|label| label.name == remove) {
+        issue_labels.swap_remove(index);
+    }
+
+    issue_labels.push(Label {
+        name: assign.into(),
+    });
+
+    None
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::{assign_and_remove_label, Label};
+    fn create_labels(names: Vec<&str>) -> Vec<Label> {
+        names
+            .into_iter()
+            .map(|name| Label { name: name.into() })
+            .collect()
+    }
+
+    #[test]
+    fn test_adds_without_labels() {
+        let expected = create_labels(vec!["assign"]);
+        let mut labels = vec![];
+        assert!(assign_and_remove_label(&mut labels, "assign", "remove").is_none());
+        assert_eq!(labels, expected);
+    }
+
+    #[test]
+    fn test_do_nothing_with_label_already_set() {
+        let expected = create_labels(vec!["assign"]);
+        let mut labels = create_labels(vec!["assign"]);
+        assert!(assign_and_remove_label(&mut labels, "assign", "remove").is_some());
+        assert_eq!(labels, expected);
+    }
+
+    #[test]
+    fn test_other_labels_untouched() {
+        let expected = create_labels(vec!["bug", "documentation", "assign"]);
+        let mut labels = create_labels(vec!["bug", "documentation"]);
+        assert!(assign_and_remove_label(&mut labels, "assign", "remove").is_none());
+        assert_eq!(labels, expected);
+    }
+
+    #[test]
+    fn test_correctly_remove_label() {
+        let expected = create_labels(vec!["bug", "documentation", "assign"]);
+        let mut labels = create_labels(vec!["bug", "documentation", "remove"]);
+        assert!(assign_and_remove_label(&mut labels, "assign", "remove").is_none());
+        assert_eq!(labels, expected);
+    }
+}