Skip to content

Commit b4083a1

Browse files
committed
define slack message generation logic for PRs and issues
1 parent f287135 commit b4083a1

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

lib/github.atd

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,23 @@ type github_user = {
2929
avatar_url: string;
3030
}
3131

32+
type github_team = {
33+
id: int;
34+
name: string;
35+
slug: string;
36+
url: string;
37+
html_url: string;
38+
~description <ocaml default="\"\"">: string;
39+
}
40+
3241
type repository = {
3342
name: string;
3443
full_name: string;
3544
html_url <ocaml name="url"> : string;
3645
commits_url: string;
3746
contents_url: string;
47+
pulls_url: string;
48+
issues_url: string;
3849
}
3950

4051
type commit_pushed_notification = {
@@ -55,13 +66,25 @@ type label = {
5566
name: string;
5667
}
5768

69+
type abstract_issue_state = [
70+
| Open <json name="open">
71+
| Closed <json name="closed">
72+
] <ocaml repr="classic">
73+
5874
type pull_request = {
5975
user: github_user;
6076
number: int;
6177
body: string;
6278
title: string;
6379
html_url: string;
6480
labels: label list;
81+
state: abstract_issue_state;
82+
~requested_reviewers <ocaml default="[]">: github_user list;
83+
~requested_teams <ocaml default="[]">: github_team list;
84+
~assignees <ocaml default="[]">: github_user list;
85+
~merged <ocaml default="false">: bool;
86+
~draft <ocaml default="false">: bool;
87+
~comments <ocaml default="0">: int;
6588
}
6689

6790
type issue = {
@@ -72,6 +95,9 @@ type issue = {
7295
html_url: string;
7396
labels: label list;
7497
?pull_request: basic_json nullable;
98+
state: abstract_issue_state;
99+
~assignees <ocaml default="[]">: github_user list;
100+
~comments <ocaml default="0">: int;
75101
}
76102

77103
type pr_action = [

lib/github.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ let gh_link_of_string url_str =
124124
url = html_base;
125125
commits_url = sprintf "%s/commits{/sha}" api_base;
126126
contents_url = sprintf "%s/contents/{+path}" api_base;
127+
pulls_url = sprintf "%s/pulls{/number}" api_base;
128+
issues_url = sprintf "%s/issues{/number}" api_base;
127129
}
128130
in
129131
begin

lib/slack_message.ml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ open Slack_t
55
open Common
66
open Mrkdwn
77

8+
let color_of_state ?(draft = false) ?(merged = false) state =
9+
match draft with
10+
| true -> Colors.gray
11+
| false ->
12+
match merged with
13+
| true -> Colors.purple
14+
| false ->
15+
match state with
16+
| Open -> Colors.green
17+
| Closed -> Colors.red
18+
19+
let gh_name_of_string = sprintf "@%s"
20+
821
let empty_attachment =
922
{
1023
mrkdwn_in = None;
@@ -27,6 +40,87 @@ let empty_attachment =
2740
let base_attachment (repository : repository) =
2841
{ empty_attachment with footer = Some (sprintf "<%s|%s>" repository.url (escape_mrkdwn repository.full_name)) }
2942

43+
let pp_label (label : label) = label.name
44+
45+
let pp_github_user (user : github_user) = gh_name_of_string user.login
46+
47+
let pp_github_team (team : github_team) = gh_name_of_string team.slug
48+
49+
let populate_pull_request repository (pull_request : pull_request) =
50+
let ({
51+
body;
52+
title;
53+
number;
54+
html_url;
55+
user;
56+
assignees;
57+
comments;
58+
labels;
59+
requested_reviewers;
60+
requested_teams;
61+
state;
62+
draft;
63+
merged;
64+
_;
65+
}
66+
: pull_request)
67+
=
68+
pull_request
69+
in
70+
let get_reviewers () =
71+
List.concat [ List.map requested_reviewers ~f:pp_github_user; List.map requested_teams ~f:pp_github_team ]
72+
in
73+
let fields =
74+
[
75+
"Assignees", List.map assignees ~f:pp_github_user;
76+
"Labels", List.map labels ~f:pp_label;
77+
"Comments", [ Int.to_string comments ];
78+
"Reviewers", get_reviewers ();
79+
]
80+
|> List.filter_map ~f:(fun (t, v) -> if List.is_empty v then None else Some (t, String.concat v ~sep:","))
81+
|> List.map ~f:(fun (t, v) -> { title = Some t; value = v })
82+
in
83+
let get_title () = sprintf "#%d %s" number (Mrkdwn.escape_mrkdwn title) in
84+
{
85+
(base_attachment repository) with
86+
author_name = Some user.login;
87+
author_link = Some user.html_url;
88+
author_icon = Some user.avatar_url;
89+
color = Some (color_of_state ~draft ~merged state);
90+
fields = Some fields;
91+
mrkdwn_in = Some [ "text" ];
92+
title = Some (get_title ());
93+
title_link = Some html_url;
94+
fallback = Some (sprintf "[%s] %s" repository.full_name title);
95+
text = Some (Mrkdwn.mrkdwn_of_markdown body);
96+
}
97+
98+
let populate_issue repository (issue : issue) =
99+
let ({ body; title; number; html_url; user; assignees; comments; labels; state; _ } : issue) = issue in
100+
let fields =
101+
[
102+
"Assignees", List.map assignees ~f:pp_github_user;
103+
"Labels", List.map labels ~f:pp_label;
104+
"Comments", [ Int.to_string comments ];
105+
]
106+
|> List.filter_map ~f:(fun (t, v) -> if List.is_empty v then None else Some (t, String.concat v ~sep:","))
107+
|> List.map ~f:(fun (t, v) -> { title = Some t; value = v })
108+
in
109+
let get_title () = sprintf "#%d %s" number (Mrkdwn.escape_mrkdwn title) in
110+
{
111+
(base_attachment repository) with
112+
author_name = Some user.login;
113+
author_link = Some user.html_url;
114+
author_icon = Some user.avatar_url;
115+
color = Some (color_of_state state);
116+
fields = Some fields;
117+
mrkdwn_in = Some [ "text" ];
118+
title = Some (get_title ());
119+
title_link = Some html_url;
120+
fallback = Some (sprintf "[%s] %s" repository.full_name title);
121+
text = Some (Mrkdwn.mrkdwn_of_markdown body);
122+
}
123+
30124
let populate_commit repository (commit : api_commit) =
31125
let ({ sha; commit; url; author; files; _ } : api_commit) = commit in
32126
let title =

0 commit comments

Comments
 (0)