Skip to content

Commit 2c5569b

Browse files
authored
Merge pull request #334 from casparvl/print_last_status_only
Add option to bot:status to print the status only for the last build
2 parents 5656a69 + 7b284ba commit 2c5569b

2 files changed

Lines changed: 65 additions & 5 deletions

File tree

eessi_bot_event_handler.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,55 @@ def handle_bot_command_status(self, event_info, bot_command):
592592
pr_number = event_info['raw_request_body']['issue']['number']
593593
status_table = request_bot_build_issue_comments(repo_name, pr_number)
594594

595+
if 'last_build' in bot_command.general_args:
596+
# If the bot command is something like 'bot:status =last_build', then only retain the last build for each
597+
# architecture in the status_table
598+
# To do this, we first insert a timestamp to facilitate sorting by time
599+
# Then, we obtain sorting indices that first sort by architecture, then by build time
600+
# Then, we reverse the sorting, so that the last build (highest timestamp) for each archictecture occurs
601+
# first.
602+
# Finally, we copy the table, but each time we encounter an entry for an architecture that we've already
603+
# copied, we ignore it, since - as a result of the sorting - the second entry is always older than the
604+
# first
605+
dates = status_table['date']
606+
timestamps = []
607+
for date in dates:
608+
date_object = datetime.strptime(date, "%b %d %X %Z %Y")
609+
timestamps.append(int(date_object.timestamp()))
610+
status_table['timestamp'] = timestamps
611+
612+
# Figure out the sorting indices, so that things are sorted first by the 'for arch', and then by 'date'
613+
sorted_indices = sorted(
614+
range(len(status_table['for arch'])),
615+
key=lambda x: (status_table['for arch'][x], status_table['timestamp'][x])
616+
)
617+
# Reverse, so that the newest builds are first
618+
sorted_indices.reverse()
619+
# Apply the sorted indices to get a sorted table
620+
sorted_table = {key: [status_table[key][i] for i in sorted_indices] for key in status_table}
621+
self.log(f"Sorted status table: {sorted_table}")
622+
623+
# Keep only the first entry for each 'for arch', as that is now the newest
624+
status_table_last = {
625+
'on arch': [], 'for arch': [], 'for repo': [], 'date': [], 'status': [], 'url': [], 'result': []
626+
}
627+
for x in range(0, len(sorted_table['date'])):
628+
if sorted_table['for arch'][x] not in status_table_last['for arch']:
629+
self.log(f"arch: {sorted_table['for arch'][x]} not yet in status_table_last")
630+
for key in status_table_last:
631+
self.log(f"Adding to '{key}' and the value {sorted_table[key][x]}")
632+
status_table_last[key].append(sorted_table[key][x])
633+
634+
# Re-sort, now only on 'for arch', for nicer viewing
635+
sorted_indices = sorted(
636+
range(len(status_table_last['for arch'])),
637+
key=lambda x: status_table_last['for arch'][x]
638+
)
639+
sorted_table_last = {key: [status_table_last[key][i] for i in sorted_indices] for key in status_table_last}
640+
641+
# overwrite the original status_table
642+
status_table = sorted_table_last
643+
595644
comment_status = ''
596645
comment_status += "\nThis is the status of all the `bot: build` commands:"
597646
comment_status += "\n|on|for|repo|result|date|status|url|"

tools/commands.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ def __init__(self, cmd_str):
8787
# TODO add function name to log messages
8888
cmd_as_list = cmd_str.split()
8989
self.command = cmd_as_list[0] # E.g. 'build' or 'help'
90+
self.general_args = []
91+
self.action_filters = None
9092
self.build_params = None
9193

9294
# TODO always init self.action_filters with empty EESSIBotActionFilter?
@@ -110,9 +112,14 @@ def __init__(self, cmd_str):
110112
# according to the expected argument format for 'for:'
111113
self.build_params = EESSIBotBuildParams(build_params)
112114
else:
113-
# Anything that is not 'on:' or 'for:' should just be passed on as normal
114-
# No further parsing of the value is needed
115-
other_filter_args.extend([arg])
115+
# Anything that is not 'on:' or 'for:'
116+
# Check if it's a filter argument, if so, pass it on to other_filter_args witout further parsing
117+
# If it's not a filter argument, it is a general argument - just store it so any other function
118+
# can read it
119+
if ':' in arg:
120+
other_filter_args.extend([arg])
121+
else:
122+
self.general_args.append(arg)
116123

117124
# If no 'on:' is found in the argument list, everything that follows the 'for:' argument
118125
# (until the next space) is considered the argument list for the action filters
@@ -140,6 +147,7 @@ def __init__(self, cmd_str):
140147
# so no special parsing needed there
141148
log(f"Extracted filter arguments related to hardware target: {normalized_filters}")
142149
log(f"Other extracted filter arguments: {other_filter_args}")
150+
log(f"Other general arguments: {self.general_args}")
143151
normalized_filters += other_filter_args
144152

145153
# Finally, change into a space-separated string, as expected by EESSIBotActionFilter
@@ -170,5 +178,8 @@ def to_string(self):
170178
Returns:
171179
string: the string representation created by the method
172180
"""
173-
action_filters_str = self.action_filters.to_string()
174-
return f"{' '.join([self.command, action_filters_str]).rstrip()}"
181+
if self.action_filters is None:
182+
return ""
183+
else:
184+
action_filters_str = self.action_filters.to_string()
185+
return f"{' '.join([self.command, action_filters_str]).rstrip()}"

0 commit comments

Comments
 (0)