|
@@ -1,16 +1,17 @@
|
|
|
use crate::{
|
|
|
config::MajorChangeConfig,
|
|
|
- github::{Event, Issue, IssuesAction, IssuesEvent, Label},
|
|
|
+ github::{Event, Issue, IssuesAction, IssuesEvent, Label, ZulipGitHubReference},
|
|
|
handlers::Context,
|
|
|
interactions::ErrorComment,
|
|
|
};
|
|
|
use anyhow::Context as _;
|
|
|
use parser::command::second::SecondCommand;
|
|
|
|
|
|
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
+#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
pub enum Invocation {
|
|
|
NewProposal,
|
|
|
AcceptedProposal,
|
|
|
+ Rename { prev_issue: ZulipGitHubReference },
|
|
|
}
|
|
|
|
|
|
pub(super) fn parse_input(
|
|
@@ -18,6 +19,19 @@ pub(super) fn parse_input(
|
|
|
event: &IssuesEvent,
|
|
|
_config: Option<&MajorChangeConfig>,
|
|
|
) -> Result<Option<Invocation>, String> {
|
|
|
+ if event.action == IssuesAction::Edited {
|
|
|
+ if let Some(changes) = &event.changes {
|
|
|
+ let prev_issue = ZulipGitHubReference {
|
|
|
+ number: event.issue.number,
|
|
|
+ title: changes.title.from.clone(),
|
|
|
+ repository: event.issue.repository().clone(),
|
|
|
+ };
|
|
|
+ return Ok(Some(Invocation::Rename { prev_issue }));
|
|
|
+ } else {
|
|
|
+ return Err(format!("no changes property in edited event"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// If we were labeled with accepted, then issue that event
|
|
|
if event.action == IssuesAction::Labeled
|
|
|
&& event
|
|
@@ -32,7 +46,7 @@ pub(super) fn parse_input(
|
|
|
// "Opened" and "Labeled" events.
|
|
|
//
|
|
|
// We want to treat reopened issues as new proposals but if the
|
|
|
- // issues is freshly opened, we only want to trigger once;
|
|
|
+ // issue is freshly opened, we only want to trigger once;
|
|
|
// currently we do so on the label event.
|
|
|
if (event.action == IssuesAction::Reopened
|
|
|
&& event
|
|
@@ -85,6 +99,40 @@ pub(super) async fn handle_input(
|
|
|
"This proposal has been accepted: [#{}]({}).",
|
|
|
event.issue.number, event.issue.html_url,
|
|
|
),
|
|
|
+ Invocation::Rename { prev_issue } => {
|
|
|
+ let issue = &event.issue;
|
|
|
+
|
|
|
+ let prev_topic = zulip_topic_from_issue(&prev_issue);
|
|
|
+ let partial_issue = issue.to_zulip_github_reference();
|
|
|
+ let new_topic = zulip_topic_from_issue(&partial_issue);
|
|
|
+
|
|
|
+ let zulip_send_req = crate::zulip::MessageApiRequest {
|
|
|
+ recipient: crate::zulip::Recipient::Stream {
|
|
|
+ id: config.zulip_stream,
|
|
|
+ topic: &prev_topic,
|
|
|
+ },
|
|
|
+ content: "The associated GitHub issue has been renamed. Renaming this Zulip topic.",
|
|
|
+ };
|
|
|
+ let zulip_send_res = zulip_send_req
|
|
|
+ .send(&ctx.github.raw())
|
|
|
+ .await
|
|
|
+ .context("zulip post failed")?;
|
|
|
+
|
|
|
+ let zulip_send_res: crate::zulip::MessageApiResponse = zulip_send_res.json().await?;
|
|
|
+
|
|
|
+ let zulip_update_req = crate::zulip::UpdateMessageApiRequest {
|
|
|
+ message_id: zulip_send_res.message_id,
|
|
|
+ topic: Some(&new_topic),
|
|
|
+ propagate_mode: None,
|
|
|
+ content: None,
|
|
|
+ };
|
|
|
+ zulip_update_req
|
|
|
+ .send(&ctx.github.raw())
|
|
|
+ .await
|
|
|
+ .context("zulip message update failed")?;
|
|
|
+
|
|
|
+ return Ok(());
|
|
|
+ }
|
|
|
};
|
|
|
handle(
|
|
|
ctx,
|
|
@@ -157,21 +205,8 @@ async fn handle(
|
|
|
labels.push(Label { name: label_to_add });
|
|
|
let github_req = issue.set_labels(&ctx.github, labels);
|
|
|
|
|
|
- // Concatenate the issue title and the topic reference, truncating such that
|
|
|
- // the overall length does not exceed 60 characters (a Zulip limitation).
|
|
|
- let topic_ref = issue.zulip_topic_reference();
|
|
|
- // Skip chars until the last characters that can be written:
|
|
|
- // Maximum 60, minus the reference, minus the elipsis and the space
|
|
|
- let mut chars = issue
|
|
|
- .title
|
|
|
- .char_indices()
|
|
|
- .skip(60 - topic_ref.chars().count() - 2);
|
|
|
- let zulip_topic = match chars.next() {
|
|
|
- Some((len, _)) if chars.next().is_some() => {
|
|
|
- format!("{}… {}", &issue.title[..len], topic_ref)
|
|
|
- }
|
|
|
- _ => format!("{} {}", issue.title, topic_ref),
|
|
|
- };
|
|
|
+ let partial_issue = issue.to_zulip_github_reference();
|
|
|
+ let zulip_topic = zulip_topic_from_issue(&partial_issue);
|
|
|
|
|
|
let zulip_req = crate::zulip::MessageApiRequest {
|
|
|
recipient: crate::zulip::Recipient::Stream {
|
|
@@ -207,3 +242,21 @@ async fn handle(
|
|
|
gh_res.context("label setting failed")?;
|
|
|
Ok(())
|
|
|
}
|
|
|
+
|
|
|
+fn zulip_topic_from_issue(issue: &ZulipGitHubReference) -> String {
|
|
|
+ // Concatenate the issue title and the topic reference, truncating such that
|
|
|
+ // the overall length does not exceed 60 characters (a Zulip limitation).
|
|
|
+ let topic_ref = issue.zulip_topic_reference();
|
|
|
+ // Skip chars until the last characters that can be written:
|
|
|
+ // Maximum 60, minus the reference, minus the elipsis and the space
|
|
|
+ let mut chars = issue
|
|
|
+ .title
|
|
|
+ .char_indices()
|
|
|
+ .skip(60 - topic_ref.chars().count() - 2);
|
|
|
+ match chars.next() {
|
|
|
+ Some((len, _)) if chars.next().is_some() => {
|
|
|
+ format!("{}… {}", &issue.title[..len], topic_ref)
|
|
|
+ }
|
|
|
+ _ => format!("{} {}", issue.title, topic_ref),
|
|
|
+ }
|
|
|
+}
|