Conversation
These are needed on main branch to trigger on workflow_run events. Tag: agy Conv: 5dcc52a8-9b21-44ce-bdad-7d0105d07dc9
🤖 Gemini Suggested Commit Message💡 Pro Tips for a Better Commit Message:
|
There was a problem hiding this comment.
Code Review
This pull request introduces two new Python scripts, collate_ci_reports.py and format_ci_report.py, to aggregate and format GitHub Actions CI workflow reports into a unified Markdown table. The review feedback highlights several robust improvements: handling potential command failures when downloading artifacts to prevent script crashes, clearing the temporary fragments directory to avoid stale data, defensively accessing dictionary keys to prevent KeyError exceptions, and providing fallback defaults for missing report fields to ensure clean Markdown output.
| run_cmd([ | ||
| 'gh', | ||
| 'run', | ||
| 'download', | ||
| run_id, | ||
| '--pattern', | ||
| 'validation-report-*', | ||
| '--dir', | ||
| 'fragments', | ||
| ]) |
There was a problem hiding this comment.
If a workflow run fails before generating any artifacts (e.g., due to a compilation or setup failure), gh run download will fail with a non-zero exit code. Since run_cmd uses check=True, this will raise a CalledProcessError and crash the entire collation script, preventing other workflows from being reported. Wrapping this in a try-except block allows the script to handle failures gracefully and record the error.
try:
run_cmd([
'gh',
'run',
'download',
run_id,
'--pattern',
'validation-report-*',
'--dir',
'fragments',
])
except subprocess.CalledProcessError:
if conclusion != 'success':
report_data.append({
'workflow': wf_name,
'status': 'completed',
'error': f'Workflow failed ({conclusion})'
})
else:
report_data.append({
'workflow': wf_name,
'status': 'completed',
'error': 'Failed to download validation report'
})| ci_runs.append(r) | ||
| seen_workflows.add(wf_name) | ||
|
|
||
| os.makedirs('fragments', exist_ok=True) |
There was a problem hiding this comment.
If this script is run multiple times in a persistent environment or locally, stale JSON files in the fragments directory from previous runs will be read and merged into the new report. It is safer to clear the directory before downloading new fragments.
| os.makedirs('fragments', exist_ok=True) | |
| import shutil | |
| shutil.rmtree('fragments', ignore_errors=True) | |
| os.makedirs('fragments', exist_ok=True) |
| f" ({entry['error']}) |") | ||
| else: | ||
| d = entry['data'] | ||
| status_icon = '❌ FAIL' if d['failed'] else '✅ PASS' |
There was a problem hiding this comment.
Accessing d['failed'] directly can raise a KeyError if the key is missing from the JSON fragment. Using .get('failed') is safer and aligns with defensive programming practices.
| status_icon = '❌ FAIL' if d['failed'] else '✅ PASS' | |
| status_icon = '❌ FAIL' if d.get('failed') else '✅ PASS' |
| markdown_lines.append( | ||
| f"| {d.get('platform')} | {d.get('build_result')} |" | ||
| f" {d.get('on_host_test_result')} |" | ||
| f" {d.get('on_device_test_result')} | {test_summary} |" | ||
| f' {status_icon} |') |
There was a problem hiding this comment.
If any of the expected keys (like platform, build_result, etc.) are missing from the JSON fragment, d.get(...) will return None, which will print as the string 'None' in the Markdown table. Providing fallback defaults (like 'Unknown' or '-') improves the visual presentation of the report.
| markdown_lines.append( | |
| f"| {d.get('platform')} | {d.get('build_result')} |" | |
| f" {d.get('on_host_test_result')} |" | |
| f" {d.get('on_device_test_result')} | {test_summary} |" | |
| f' {status_icon} |') | |
| markdown_lines.append( | |
| f"| {d.get('platform', 'Unknown')} | {d.get('build_result', '-')} |" | |
| f" {d.get('on_host_test_result', '-')} |" | |
| f" {d.get('on_device_test_result', '-')} | {test_summary} |" | |
| f' {status_icon} |') |
| - completed | ||
|
|
||
| permissions: | ||
| statuses: write |
| generate-report: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout |
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 |
|
|
||
| - name: Comment on PR | ||
| if: always() && github.event.workflow_run.event == 'pull_request' && steps.collate.outputs.status != 'PENDING' && steps.collate.outputs.status != 'SKIPPED' && hashFiles('combined_report.md') != '' | ||
| uses: marocchino/sticky-pull-request-comment@v2 |
Merge ci_shepherd.yml and script files to main branch for collation testing.