11use crate :: db:: jobs:: * ;
2+ use crate :: github;
23use crate :: {
34 config:: DecisionConfig , db:: issue_decision_state:: * , github:: Event , handlers:: Context ,
45 interactions:: ErrorComment ,
56} ;
7+ use anyhow:: bail;
68use anyhow:: Context as Ctx ;
79use chrono:: { DateTime , Duration , Utc } ;
810use parser:: command:: decision:: Resolution :: { Hold , Merge } ;
@@ -93,16 +95,26 @@ pub(super) async fn handle_command(
9395 let end_date: DateTime < Utc > =
9496 start_date. checked_add_signed ( Duration :: days ( 10 ) ) . unwrap ( ) ;
9597
96- let mut current: BTreeMap < String , UserStatus > = BTreeMap :: new ( ) ;
98+ //TODO: change this to be configurable in toml / ask user to provide the team name
99+ // it should match the same team that we check for above when determining if the user is a member
100+ let team = github:: get_team ( & ctx. github , & "T-lang" ) . await ?. unwrap ( ) ;
101+
102+ let mut current: BTreeMap < String , Option < UserStatus > > = BTreeMap :: new ( ) ;
103+
104+ for member in team. members {
105+ current. insert ( member. name , None ) ;
106+ }
107+
97108 current. insert (
98- "mcass19" . to_string ( ) ,
99- UserStatus {
109+ user . login . clone ( ) ,
110+ Some ( UserStatus {
100111 comment_id : "comment_id" . to_string ( ) ,
101112 text : "something" . to_string ( ) ,
102113 reversibility : Reversibility :: Reversible ,
103114 resolution : Merge ,
104- } ,
115+ } ) ,
105116 ) ;
117+
106118 let history: BTreeMap < String , Vec < UserStatus > > = BTreeMap :: new ( ) ;
107119
108120 insert_issue_decision_state (
@@ -120,7 +132,11 @@ pub(super) async fn handle_command(
120132
121133 let metadata = serde_json:: value:: to_value ( DecisionProcessActionMetadata {
122134 message : "some message" . to_string ( ) ,
123- get_issue_url : format ! ( "{}/issues/{}" , issue. repository( ) . url( ) , issue. number) ,
135+ get_issue_url : format ! (
136+ "{}/issues/{}" ,
137+ issue. repository( ) . url( ) ,
138+ issue. number
139+ ) ,
124140 status : Merge ,
125141 } )
126142 . unwrap ( ) ;
@@ -133,12 +149,7 @@ pub(super) async fn handle_command(
133149 )
134150 . await ?;
135151
136- // let team = github::get_team(&ctx.github, &"T-lang"); // change this to be configurable in toml?
137-
138- let comment = format ! (
139- "Wow, it looks like you want to merge this, {}.\n | Team member | State |\n |-------------|-------|\n | julmontesdeoca | merge |\n | mcass19 | |" ,
140- user. login
141- ) ;
152+ let comment = build_status_comment ( & history, & current) ?;
142153
143154 issue
144155 . post_comment ( & ctx. github , & comment)
@@ -152,6 +163,164 @@ pub(super) async fn handle_command(
152163 }
153164}
154165
166+ fn build_status_comment (
167+ history : & BTreeMap < String , Vec < UserStatus > > ,
168+ current : & BTreeMap < String , Option < UserStatus > > ,
169+ ) -> anyhow:: Result < String > {
170+ let mut comment = "| Team member | State |\n |-------------|-------|" . to_owned ( ) ;
171+ for ( user, statuses) in history {
172+ let mut user_statuses = format ! ( "\n | {} |" , user) ;
173+
174+ // previous stasuses
175+ for status in statuses {
176+ let status_item = format ! ( " ~~{}~~ " , status. resolution) ;
177+ user_statuses. push_str ( & status_item) ;
178+ }
179+
180+ // current status
181+ let user_resolution = match current. get ( user) {
182+ Some ( current_status) => {
183+ if let Some ( status) = current_status {
184+ format ! ( "**{}**" , status. resolution)
185+ } else {
186+ "" . to_string ( )
187+ }
188+ }
189+ None => bail ! ( "user {} not present in current statuses list" , user) ,
190+ } ;
191+
192+ let status_item = format ! ( " {} |" , user_resolution) ;
193+ user_statuses. push_str ( & status_item) ;
194+
195+ comment. push_str ( & user_statuses) ;
196+ }
197+
198+ Ok ( comment)
199+ }
200+
201+ #[ cfg( test) ]
202+ mod tests {
203+ use super :: * ;
204+ use factori:: { create, factori} ;
205+
206+ factori ! ( UserStatus , {
207+ default {
208+ comment_id = "the-comment-id" . to_string( ) ,
209+ text = "this is my argument for making this decision" . to_string( ) ,
210+ reversibility = Reversibility :: Reversible ,
211+ resolution = Resolution :: Merge
212+ }
213+
214+ mixin hold {
215+ resolution = Resolution :: Hold
216+ }
217+ } ) ;
218+
219+ #[ test]
220+ fn test_successfuly_build_comment ( ) {
221+ let mut history: BTreeMap < String , Vec < UserStatus > > = BTreeMap :: new ( ) ;
222+ let mut current_statuses: BTreeMap < String , Option < UserStatus > > = BTreeMap :: new ( ) ;
223+
224+ // user 1
225+ let mut user_1_statuses: Vec < UserStatus > = Vec :: new ( ) ;
226+ user_1_statuses. push ( create ! ( UserStatus ) ) ;
227+ user_1_statuses. push ( create ! ( UserStatus , : hold) ) ;
228+
229+ history. insert ( "Niklaus" . to_string ( ) , user_1_statuses) ;
230+
231+ current_statuses. insert ( "Niklaus" . to_string ( ) , Some ( create ! ( UserStatus ) ) ) ;
232+
233+ // user 2
234+ let mut user_2_statuses: Vec < UserStatus > = Vec :: new ( ) ;
235+ user_2_statuses. push ( create ! ( UserStatus , : hold) ) ;
236+ user_2_statuses. push ( create ! ( UserStatus ) ) ;
237+
238+ history. insert ( "Barbara" . to_string ( ) , user_2_statuses) ;
239+
240+ current_statuses. insert ( "Barbara" . to_string ( ) , Some ( create ! ( UserStatus ) ) ) ;
241+
242+ let build_result = build_status_comment ( & history, & current_statuses)
243+ . expect ( "it shouldn't fail building the message" ) ;
244+ let expected_comment = "| Team member | State |\n \
245+ |-------------|-------|\n \
246+ | Barbara | ~~hold~~ ~~merge~~ **merge** |\n \
247+ | Niklaus | ~~merge~~ ~~hold~~ **merge** |"
248+ . to_string ( ) ;
249+
250+ assert_eq ! ( build_result, expected_comment) ;
251+ }
252+
253+ #[ test]
254+ fn test_successfuly_build_comment_user_no_votes ( ) {
255+ let mut history: BTreeMap < String , Vec < UserStatus > > = BTreeMap :: new ( ) ;
256+ let mut current_statuses: BTreeMap < String , Option < UserStatus > > = BTreeMap :: new ( ) ;
257+
258+ // user 1
259+ let mut user_1_statuses: Vec < UserStatus > = Vec :: new ( ) ;
260+ user_1_statuses. push ( create ! ( UserStatus ) ) ;
261+ user_1_statuses. push ( create ! ( UserStatus , : hold) ) ;
262+
263+ history. insert ( "Niklaus" . to_string ( ) , user_1_statuses) ;
264+
265+ current_statuses. insert ( "Niklaus" . to_string ( ) , Some ( create ! ( UserStatus ) ) ) ;
266+
267+ // user 2
268+ let mut user_2_statuses: Vec < UserStatus > = Vec :: new ( ) ;
269+ user_2_statuses. push ( create ! ( UserStatus , : hold) ) ;
270+ user_2_statuses. push ( create ! ( UserStatus ) ) ;
271+
272+ history. insert ( "Barbara" . to_string ( ) , user_2_statuses) ;
273+
274+ current_statuses. insert ( "Barbara" . to_string ( ) , Some ( create ! ( UserStatus ) ) ) ;
275+
276+ // user 3
277+ history. insert ( "Tom" . to_string ( ) , Vec :: new ( ) ) ;
278+
279+ current_statuses. insert ( "Tom" . to_string ( ) , None ) ;
280+
281+ let build_result = build_status_comment ( & history, & current_statuses)
282+ . expect ( "it shouldn't fail building the message" ) ;
283+ let expected_comment = "| Team member | State |\n \
284+ |-------------|-------|\n \
285+ | Barbara | ~~hold~~ ~~merge~~ **merge** |\n \
286+ | Niklaus | ~~merge~~ ~~hold~~ **merge** |\n \
287+ | Tom | |"
288+ . to_string ( ) ;
289+
290+ assert_eq ! ( build_result, expected_comment) ;
291+ }
292+
293+ #[ test]
294+ fn test_build_comment_inconsistent_users ( ) {
295+ let mut history: BTreeMap < String , Vec < UserStatus > > = BTreeMap :: new ( ) ;
296+ let mut current_statuses: BTreeMap < String , Option < UserStatus > > = BTreeMap :: new ( ) ;
297+
298+ // user 1
299+ let mut user_1_statuses: Vec < UserStatus > = Vec :: new ( ) ;
300+ user_1_statuses. push ( create ! ( UserStatus ) ) ;
301+ user_1_statuses. push ( create ! ( UserStatus , : hold) ) ;
302+
303+ history. insert ( "Niklaus" . to_string ( ) , user_1_statuses) ;
304+
305+ current_statuses. insert ( "Niklaus" . to_string ( ) , Some ( create ! ( UserStatus ) ) ) ;
306+
307+ // user 2
308+ let mut user_2_statuses: Vec < UserStatus > = Vec :: new ( ) ;
309+ user_2_statuses. push ( create ! ( UserStatus , : hold) ) ;
310+ user_2_statuses. push ( create ! ( UserStatus ) ) ;
311+
312+ history. insert ( "Barbara" . to_string ( ) , user_2_statuses) ;
313+
314+ current_statuses. insert ( "Martin" . to_string ( ) , Some ( create ! ( UserStatus ) ) ) ;
315+
316+ let build_result = build_status_comment ( & history, & current_statuses) ;
317+ assert_eq ! (
318+ format!( "{}" , build_result. unwrap_err( ) ) ,
319+ "user Barbara not present in current statuses list"
320+ ) ;
321+ }
322+ }
323+
155324// #[cfg(test)]
156325// mod tests {
157326// use chrono::{Duration, Utc};
0 commit comments