Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions eessi_bot_event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,55 @@ def handle_bot_command_status(self, event_info, bot_command):
pr_number = event_info['raw_request_body']['issue']['number']
status_table = request_bot_build_issue_comments(repo_name, pr_number)

if 'last_build' in bot_command.general_args:
# If the bot command is something like 'bot:status =last_build', then only retain the last build for each
# architecture in the status_table
# To do this, we first insert a timestamp to facilitate sorting by time
# Then, we obtain sorting indices that first sort by architecture, then by build time
# Then, we reverse the sorting, so that the last build (highest timestamp) for each archictecture occurs
# first.
# Finally, we copy the table, but each time we encounter an entry for an architecture that we've already
# copied, we ignore it, since - as a result of the sorting - the second entry is always older than the
# first
dates = status_table['date']
timestamps = []
for date in dates:
date_object = datetime.strptime(date, "%b %d %X %Z %Y")
timestamps.append(int(date_object.timestamp()))
status_table['timestamp'] = timestamps

# Figure out the sorting indices, so that things are sorted first by the 'for arch', and then by 'date'
sorted_indices = sorted(
range(len(status_table['for arch'])),
key=lambda x: (status_table['for arch'][x], status_table['timestamp'][x])
)
# Reverse, so that the newest builds are first
sorted_indices.reverse()
# Apply the sorted indices to get a sorted table
sorted_table = {key: [status_table[key][i] for i in sorted_indices] for key in status_table}
self.log(f"Sorted status table: {sorted_table}")

# Keep only the first entry for each 'for arch', as that is now the newest
status_table_last = {
'on arch': [], 'for arch': [], 'for repo': [], 'date': [], 'status': [], 'url': [], 'result': []
}
for x in range(0, len(sorted_table['date'])):
if sorted_table['for arch'][x] not in status_table_last['for arch']:
self.log(f"arch: {sorted_table['for arch'][x]} not yet in status_table_last")
for key in status_table_last:
self.log(f"Adding to '{key}' and the value {sorted_table[key][x]}")
status_table_last[key].append(sorted_table[key][x])

# Re-sort, now only on 'for arch', for nicer viewing
sorted_indices = sorted(
range(len(status_table_last['for arch'])),
key=lambda x: status_table_last['for arch'][x]
)
sorted_table_last = {key: [status_table_last[key][i] for i in sorted_indices] for key in status_table_last}

# overwrite the original status_table
status_table = sorted_table_last

comment_status = ''
comment_status += "\nThis is the status of all the `bot: build` commands:"
comment_status += "\n|on|for|repo|result|date|status|url|"
Expand Down
21 changes: 16 additions & 5 deletions tools/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def __init__(self, cmd_str):
# TODO add function name to log messages
cmd_as_list = cmd_str.split()
self.command = cmd_as_list[0] # E.g. 'build' or 'help'
self.general_args = []
self.action_filters = None
self.build_params = None

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

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

# Finally, change into a space-separated string, as expected by EESSIBotActionFilter
Expand Down Expand Up @@ -170,5 +178,8 @@ def to_string(self):
Returns:
string: the string representation created by the method
"""
action_filters_str = self.action_filters.to_string()
return f"{' '.join([self.command, action_filters_str]).rstrip()}"
if self.action_filters is None:
return ""
else:
action_filters_str = self.action_filters.to_string()
return f"{' '.join([self.command, action_filters_str]).rstrip()}"