diff --git a/.github/actions/workflow-results/parse-job-times.py b/.github/actions/workflow-results/parse-job-times.py index e30e213de34..79723bf3089 100755 --- a/.github/actions/workflow-results/parse-job-times.py +++ b/.github/actions/workflow-results/parse-job-times.py @@ -76,9 +76,11 @@ def main(): # Job times are 2024-05-09T06:52:20Z started_at = job['started_at'] started_time = datetime.datetime.strptime(started_at, "%Y-%m-%dT%H:%M:%SZ") + started_time_epoch_secs = started_time.timestamp() completed_at = job['completed_at'] completed_time = datetime.datetime.strptime(completed_at, "%Y-%m-%dT%H:%M:%SZ") + completed_time_epoch_secs = completed_time.timestamp() job_seconds = (completed_time - started_time).total_seconds() job_duration = str(datetime.timedelta(seconds=job_seconds)) @@ -87,6 +89,8 @@ def main(): result[id]['name'] = name result[id]['started_at'] = started_at result[id]['completed_at'] = completed_at + result[id]['started_epoch_secs'] = started_time_epoch_secs + result[id]['completed_epoch_secs'] = completed_time_epoch_secs result[id]['job_duration'] = job_duration result[id]['job_seconds'] = job_seconds diff --git a/.github/actions/workflow-results/prepare-execution-summary.py b/.github/actions/workflow-results/prepare-execution-summary.py index 61cfc43f449..07dbdde8df3 100755 --- a/.github/actions/workflow-results/prepare-execution-summary.py +++ b/.github/actions/workflow-results/prepare-execution-summary.py @@ -70,11 +70,14 @@ def update_summary_entry(entry, job, job_times=None): if not 'job_time' in entry: entry['job_time'] = 0 - if not 'step_time' in entry: - entry['step_time'] = 0 + if not 'command_time' in entry: + entry['command_time'] = 0 + if not 'max_job_time' in entry: + entry['max_job_time'] = 0 entry['job_time'] += job_time - entry['step_time'] += command_time + entry['command_time'] += command_time + entry['max_job_time'] = max(entry['max_job_time'], job_time) sccache_stats = get_sccache_stats(job["id"]) if sccache_stats: @@ -159,6 +162,20 @@ def rank_tag(tag_summary): return summary +def get_walltime(job_times): + "Return the walltime for all jobs in seconds." + start = None + end = None + for job_id, job_time in job_times.items(): + job_start_timestamp = job_time['started_epoch_secs'] + job_end_timestamp = job_time['completed_epoch_secs'] + if not start or job_start_timestamp < start: + start = job_start_timestamp + if not end or job_end_timestamp > end: + end = job_end_timestamp + return end - start + + def format_seconds(seconds): days, remainder = divmod(seconds, 86400) hours, remainder = divmod(remainder, 3600) @@ -187,9 +204,11 @@ def get_summary_stats(summary): if 'job_time' in summary and total > 0 and summary['job_time'] > 0: job_time = summary['job_time'] + max_job_time = summary['max_job_time'] total_job_duration = format_seconds(job_time) avg_job_duration = format_seconds(job_time / total) - stats += f' | Total Time: {total_job_duration:>7} | Avg Time: {avg_job_duration:>7}' + max_job_duration = format_seconds(max_job_time) + stats += f' | Total: {total_job_duration:>7} | Avg: {avg_job_duration:>7} | Max: {max_job_duration:>7}' if 'sccache' in summary: sccache = summary['sccache'] @@ -202,7 +221,7 @@ def get_summary_stats(summary): return stats -def get_summary_heading(summary): +def get_summary_heading(summary, walltime): passed = summary['passed'] failed = summary['failed'] @@ -213,7 +232,7 @@ def get_summary_heading(summary): else: flag = '🟩' - return f'{flag} CI Results: {get_summary_stats(summary)}' + return f'{flag} CI finished in {walltime}: {get_summary_stats(summary)}' def get_project_heading(project, project_summary): @@ -308,10 +327,11 @@ def write_project_summary(idx, project, project_summary): def write_workflow_summary(workflow, job_times=None): summary = build_summary(extract_jobs(workflow), job_times) + walltime = format_seconds(get_walltime(job_times)) if job_times else '[unknown]' os.makedirs('execution/projects', exist_ok=True) - write_text('execution/heading.txt', get_summary_heading(summary)) + write_text('execution/heading.txt', get_summary_heading(summary, walltime)) # Sort summary projects so that projects with failures come first, and ties # are broken by the total number of jobs: