Skip to content

Commit 06c3852

Browse files
committed
action, github: support edited comments update + add tests
1 parent 81b7363 commit 06c3852

10 files changed

+275
-116
lines changed

lib/action.ml

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
5858

5959
let partition_pr_review_comment cfg (n : pr_review_comment_notification) =
6060
match n.action with
61-
| Created -> partition_label cfg n.pull_request.labels
61+
| Created | Edited -> partition_label cfg n.pull_request.labels
6262
| _ -> []
6363

6464
let partition_issue_comment cfg (n : issue_comment_notification) =
6565
match n.action with
66-
| Created -> partition_label cfg n.issue.labels
66+
| Created | Edited -> partition_label cfg n.issue.labels
6767
| _ -> []
6868

6969
let partition_pr_review cfg (n : pr_review_notification) =
@@ -186,26 +186,41 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
186186
| Pull_request n -> partition_pr cfg n |> List.map ~f:(generate_pull_request_notification n) |> Lwt.return
187187
| PR_review n -> partition_pr_review cfg n |> List.map ~f:(generate_pr_review_notification n) |> Lwt.return
188188
| PR_review_comment n ->
189-
partition_pr_review_comment cfg n |> List.map ~f:(generate_pr_review_comment_notification n) |> Lwt.return
189+
partition_pr_review_comment cfg n |> List.map ~f:(generate_pr_review_comment_notification ctx n) |> Lwt.return
190190
| Issue n -> partition_issue cfg n |> List.map ~f:(generate_issue_notification n) |> Lwt.return
191191
| Issue_comment n ->
192-
partition_issue_comment cfg n |> List.map ~f:(generate_issue_comment_notification n) |> Lwt.return
192+
partition_issue_comment cfg n |> List.map ~f:(generate_issue_comment_notification ctx n) |> Lwt.return
193193
| Commit_comment n ->
194194
let%lwt channels, api_commit = partition_commit_comment ctx n in
195-
let notifs = List.map ~f:(generate_commit_comment_notification api_commit n) channels in
195+
let notifs = List.map ~f:(generate_commit_comment_notification ctx api_commit n) channels in
196196
Lwt.return notifs
197197
| Status n ->
198198
let%lwt channels = partition_status ctx n in
199199
let notifs = List.map ~f:(generate_status_notification cfg n) channels in
200200
Lwt.return notifs
201201
| _ -> Lwt.return []
202202

203-
let send_notifications (ctx : Context.t) notifications =
204-
let notify (msg : Slack_t.post_message_req) =
205-
match%lwt Slack_api.send_notification ~ctx ~msg with
206-
| Ok () -> Lwt.return_unit
207-
| Error e -> action_error e
203+
let send_notifications (ctx : Context.t) (req : Github.t) notifications =
204+
let update_comment_mapping message =
205+
match req with
206+
| Github.PR_review_comment n -> State.add_comment_map ctx.state n.repository.url n.comment.id message
207+
| Issue_comment n -> State.add_comment_map ctx.state n.repository.url n.comment.id message
208+
| Commit_comment n -> State.add_comment_map ctx.state n.repository.url n.comment.id message
209+
| _ -> Lwt.return_unit
208210
in
211+
let notify = function
212+
| New_message (msg : Slack_t.post_message_req) ->
213+
( match%lwt Slack_api.send_notification ~ctx ~msg with
214+
| Ok res -> update_comment_mapping res
215+
| Error e -> action_error e
216+
)
217+
| Update_message msg ->
218+
( match%lwt Slack_api.update_notification ~ctx ~msg with
219+
| Ok () -> Lwt.return_unit
220+
| Error e -> action_error e
221+
)
222+
in
223+
209224
Lwt_list.iter_s notify notifications
210225

211226
(** [refresh_repo_config ctx n] fetches the latest repo config if it's
@@ -278,7 +293,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
278293
| Error e -> action_error e
279294
| Ok () ->
280295
let%lwt notifications = generate_notifications ctx payload in
281-
let%lwt () = Lwt.join [ send_notifications ctx notifications; do_github_tasks ctx repo payload ] in
296+
let%lwt () = Lwt.join [ send_notifications ctx payload notifications; do_github_tasks ctx repo payload ] in
282297
( match ctx.state_filepath with
283298
| None -> Lwt.return_unit
284299
| Some path ->

lib/github.atd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ type api_commit = {
287287
}
288288

289289
type commit_comment_notification = {
290-
action: string;
290+
action: comment_action;
291291
repository: repository;
292292
comment: comment;
293293
sender: github_user;

lib/slack.ml

Lines changed: 125 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ open Mrkdwn
55
open Github_j
66
open Slack_j
77

8+
type notify =
9+
| New_message of Slack_t.post_message_req
10+
| Update_message of Slack_t.update_message_req
11+
812
let empty_attachments =
913
{
1014
mrkdwn_in = None;
@@ -55,21 +59,22 @@ let generate_pull_request_notification notification channel =
5559
sprintf "<%s|[%s]> Pull request #%d %s %s by *%s*" repository.url repository.full_name number
5660
(pp_link ~url:html_url title) action sender.login
5761
in
58-
{
59-
channel;
60-
text = Some summary;
61-
attachments =
62-
Some
63-
[
64-
{
65-
empty_attachments with
66-
mrkdwn_in = Some [ "text" ];
67-
color = Some "#ccc";
68-
text = mrkdwn_of_markdown_opt body;
69-
};
70-
];
71-
blocks = None;
72-
}
62+
New_message
63+
{
64+
channel;
65+
text = Some summary;
66+
attachments =
67+
Some
68+
[
69+
{
70+
empty_attachments with
71+
mrkdwn_in = Some [ "text" ];
72+
color = Some "#ccc";
73+
text = mrkdwn_of_markdown_opt body;
74+
};
75+
];
76+
blocks = None;
77+
}
7378

7479
let generate_pr_review_notification notification channel =
7580
let { action; sender; pull_request; review; repository } = notification in
@@ -93,28 +98,29 @@ let generate_pr_review_notification notification channel =
9398
sprintf "<%s|[%s]> *%s* <%s|%s> #%d %s" repository.url repository.full_name sender.login review.html_url action_str
9499
number (pp_link ~url:html_url title)
95100
in
96-
{
97-
channel;
98-
text = Some summary;
99-
attachments =
100-
Some
101-
[
102-
{
103-
empty_attachments with
104-
mrkdwn_in = Some [ "text" ];
105-
color = Some "#ccc";
106-
text = mrkdwn_of_markdown_opt review.body;
107-
};
108-
];
109-
blocks = None;
110-
}
101+
New_message
102+
{
103+
channel;
104+
text = Some summary;
105+
attachments =
106+
Some
107+
[
108+
{
109+
empty_attachments with
110+
mrkdwn_in = Some [ "text" ];
111+
color = Some "#ccc";
112+
text = mrkdwn_of_markdown_opt review.body;
113+
};
114+
];
115+
blocks = None;
116+
}
111117

112-
let generate_pr_review_comment_notification notification channel =
118+
let generate_pr_review_comment_notification (ctx : Context.t) notification channel =
113119
let { action; pull_request; sender; comment; repository } = notification in
114120
let ({ number; title; html_url; _ } : pull_request) = pull_request in
115121
let action_str =
116122
match action with
117-
| Created -> "commented"
123+
| Created | Edited -> "commented"
118124
| _ ->
119125
invalid_arg
120126
(sprintf "Monorobot doesn't know how to generate notification for the unexpected event %s"
@@ -130,22 +136,27 @@ let generate_pr_review_comment_notification notification channel =
130136
| None -> None
131137
| Some a -> Some (sprintf "New comment by %s in <%s|%s>" sender.login comment.html_url a)
132138
in
133-
{
134-
channel;
135-
text = Some summary;
136-
attachments =
137-
Some
138-
[
139-
{
140-
empty_attachments with
141-
mrkdwn_in = Some [ "text" ];
142-
color = Some "#ccc";
143-
footer = file;
144-
text = Some (mrkdwn_of_markdown comment.body);
145-
};
146-
];
147-
blocks = None;
148-
}
139+
let attachments =
140+
Some
141+
[
142+
{
143+
empty_attachments with
144+
mrkdwn_in = Some [ "text" ];
145+
color = Some "#ccc";
146+
footer = file;
147+
text = Some (mrkdwn_of_markdown comment.body);
148+
};
149+
]
150+
in
151+
match action with
152+
| Created -> New_message { channel; text = Some summary; attachments; blocks = None }
153+
| Edited ->
154+
( match State.get_comment_map ctx.state repository.url comment.id with
155+
| Some ({ channel; ts } : post_message_res) ->
156+
Update_message { channel; ts; text = Some summary; attachments; blocks = None }
157+
| None -> invalid_arg (sprintf "could not find comment %d in %s" comment.id repository.url)
158+
)
159+
| _ -> invalid_arg "impossible"
149160

150161
let generate_issue_notification notification channel =
151162
let ({ action; sender; issue; repository } : issue_notification) = notification in
@@ -166,28 +177,29 @@ let generate_issue_notification notification channel =
166177
sprintf "<%s|[%s]> Issue #%d %s %s by *%s*" repository.url repository.full_name number (pp_link ~url:html_url title)
167178
action sender.login
168179
in
169-
{
170-
channel;
171-
text = Some summary;
172-
attachments =
173-
Some
174-
[
175-
{
176-
empty_attachments with
177-
mrkdwn_in = Some [ "text" ];
178-
color = Some "#ccc";
179-
text = mrkdwn_of_markdown_opt body;
180-
};
181-
];
182-
blocks = None;
183-
}
180+
New_message
181+
{
182+
channel;
183+
text = Some summary;
184+
attachments =
185+
Some
186+
[
187+
{
188+
empty_attachments with
189+
mrkdwn_in = Some [ "text" ];
190+
color = Some "#ccc";
191+
text = mrkdwn_of_markdown_opt body;
192+
};
193+
];
194+
blocks = None;
195+
}
184196

185-
let generate_issue_comment_notification notification channel =
197+
let generate_issue_comment_notification (ctx : Context.t) notification channel =
186198
let { action; issue; sender; comment; repository } = notification in
187199
let { number; title; _ } = issue in
188200
let action_str =
189201
match action with
190-
| Created -> "commented"
202+
| Created | Edited -> "commented"
191203
| _ ->
192204
invalid_arg
193205
(sprintf
@@ -199,21 +211,26 @@ let generate_issue_comment_notification notification channel =
199211
sprintf "<%s|[%s]> *%s* <%s|%s> on #%d %s" repository.url repository.full_name sender.login comment.html_url
200212
action_str number (pp_link ~url:issue.html_url title)
201213
in
202-
{
203-
channel;
204-
text = Some summary;
205-
attachments =
206-
Some
207-
[
208-
{
209-
empty_attachments with
210-
mrkdwn_in = Some [ "text" ];
211-
color = Some "#ccc";
212-
text = Some (mrkdwn_of_markdown comment.body);
213-
};
214-
];
215-
blocks = None;
216-
}
214+
let attachments =
215+
Some
216+
[
217+
{
218+
empty_attachments with
219+
mrkdwn_in = Some [ "text" ];
220+
color = Some "#ccc";
221+
text = Some (mrkdwn_of_markdown comment.body);
222+
};
223+
]
224+
in
225+
match action with
226+
| Created -> New_message { channel; text = Some summary; attachments; blocks = None }
227+
| Edited ->
228+
( match State.get_comment_map ctx.state repository.url comment.id with
229+
| Some ({ channel; ts } : post_message_res) ->
230+
Update_message { channel; ts; text = Some summary; attachments; blocks = None }
231+
| None -> invalid_arg (sprintf "could not find comment %d in %s" comment.id repository.url)
232+
)
233+
| _ -> invalid_arg "impossible"
217234

218235
let git_short_sha_hash hash = String.sub ~pos:0 ~len:8 hash
219236

@@ -271,21 +288,22 @@ let generate_push_notification notification channel =
271288
sender.login
272289
in
273290
let commits = pp_list_with_previews ~pp_item:pp_commit commits in
274-
{
275-
channel;
276-
text = Some title;
277-
attachments =
278-
Some
279-
[
280-
{
281-
empty_attachments with
282-
mrkdwn_in = Some [ "fields" ];
283-
color = Some "#ccc";
284-
fields = Some [ { value = String.concat ~sep:"\n" commits; title = None; short = false } ];
285-
};
286-
];
287-
blocks = None;
288-
}
291+
New_message
292+
{
293+
channel;
294+
text = Some title;
295+
attachments =
296+
Some
297+
[
298+
{
299+
empty_attachments with
300+
mrkdwn_in = Some [ "fields" ];
301+
color = Some "#ccc";
302+
fields = Some [ { value = String.concat ~sep:"\n" commits; title = None; short = false } ];
303+
};
304+
];
305+
blocks = None;
306+
}
289307

290308
let generate_status_notification (cfg : Config_t.config) (notification : status_notification) channel =
291309
let { commit; state; description; target_url; context; repository; _ } = notification in
@@ -347,11 +365,11 @@ let generate_status_notification (cfg : Config_t.config) (notification : status_
347365
fields = Some [ { title = None; value = msg; short = false } ];
348366
}
349367
in
350-
{ channel; text = Some summary; attachments = Some [ attachment ]; blocks = None }
368+
New_message { channel; text = Some summary; attachments = Some [ attachment ]; blocks = None }
351369

352-
let generate_commit_comment_notification api_commit notification channel =
370+
let generate_commit_comment_notification (ctx : Context.t) api_commit notification channel =
353371
let { commit; _ } = api_commit in
354-
let { sender; comment; repository; _ } = notification in
372+
let { sender; comment; repository; action; _ } = notification in
355373
let commit_id =
356374
match comment.commit_id with
357375
| None -> invalid_arg "commit id not found"
@@ -376,7 +394,15 @@ let generate_commit_comment_notification api_commit notification channel =
376394
text = Some (mrkdwn_of_markdown comment.body);
377395
}
378396
in
379-
{ channel; text = Some summary; attachments = Some [ attachment ]; blocks = None }
397+
match action with
398+
| Created -> New_message { channel; text = Some summary; attachments = Some [ attachment ]; blocks = None }
399+
| Edited ->
400+
( match State.get_comment_map ctx.state repository.url comment.id with
401+
| Some ({ channel; ts } : post_message_res) ->
402+
Update_message { channel; ts; text = Some summary; attachments = Some [ attachment ]; blocks = None }
403+
| None -> invalid_arg (sprintf "could not find comment %d in %s" comment.id repository.url)
404+
)
405+
| _ -> invalid_arg "impossible"
380406

381407
let validate_signature ?(version = "v0") ?signing_key ~headers body =
382408
match signing_key with

0 commit comments

Comments
 (0)