Coverage for src/pytribeam/cicd/report_dashboard.py: 96%
24 statements
« prev ^ index » next coverage.py v7.5.1, created at 2026-07-23 14:51 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2026-07-23 14:51 +0000
1#!/usr/bin/env python3
2"""
3Generates the root index.html Project Dashboard for GitHub Pages.
4"""
6import argparse
7import os
9from pytribeam.cicd.utilities import (
10 ReportMetadata,
11 add_common_args,
12 extend_timestamp,
13 report_metadata_creation,
14)
17def generate_dashboard_html(metadata: ReportMetadata) -> str:
18 """
19 Generate the HTML content for the Project Dashboard using a two-column layout.
21 Args:
22 metadata: CI/CD metadata
24 Returns:
25 HTML string
26 """
27 timestamp_ext = extend_timestamp(metadata.timestamp)
29 # Pre-calculate GitHub URLs to stay under line length limits
30 github_url = f"https://github.com/{metadata.github_repo}"
31 run_url = f"{github_url}/actions/runs/{metadata.run_id}"
32 branch_url = f"{github_url}/tree/{metadata.ref_name}"
33 commit_url = f"{github_url}/commit/{metadata.github_sha}"
35 return f"""<!DOCTYPE html>
36<html lang="en">
37<head>
38 <meta charset="UTF-8">
39 <meta name="viewport" content="width=device-width, initial-scale=1.0">
40 <title>pyTriBeam | Project Dashboard</title>
41 <script src="https://cdn.tailwindcss.com"></script>
42 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap"
43 rel="stylesheet">
44 <style>
45 body {{ font-family: 'Inter', sans-serif; }}
46 .hover-card:hover {{ transform: translateY(-2px); transition: all 0.2s ease; }}
47 </style>
48 </head>
49 <body class="bg-[#DCDCDC] text-slate-800 antialiased min-h-screen">
50<nav class="bg-[#F5F5F5] border-b border-slate-200 sticky top-0 z-50">
51 <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
52 <div class="flex items-center gap-2">
53 <span class="text-xl font-bold tracking-tight text-blue-600">pyTriBeam</span>
54 </div>
56 <a href="{github_url}"
57 class="text-sm font-medium hover:text-blue-600 transition">GitHub Repository</a>
58 </div>
59 </nav>
61 <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
62 <header class="mb-12 text-center">
63 <h1 class="text-4xl font-extrabold tracking-tight text-slate-900 mb-4">
64 <b>Project Dashboard</b></h1>
65 <p class="text-lg text-slate-600 max-w-2xl mx-auto">
66 Documentation and quality reports for pyTriBeam.
67 </p>
68 </header>
70 <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
72 <section class="space-y-6">
73 <div class="flex items-center justify-between border-b-2 border-blue-200 pb-2">
74 <h2 class="text-2xl font-bold flex items-center gap-2">
75 🚀 Released
76 </h2>
77 <a href="{github_url}/tree/main"
78 class="text-xs font-semibold bg-blue-100 text-blue-700
79 px-2 py-1 rounded hover:bg-slate-300">main branch</a>
80 </div>
82 <div class="space-y-4">
83 <a href="main/docs/userguide/book/index.html"
84 class="hover-card block p-5 bg-[#F5F5F5] rounded-xl shadow-sm border
85 border-slate-200 hover:border-blue-600 group">
86 <div class="flex justify-between items-start">
87 <div>
88 <h3 class="font-bold text-lg group-hover:text-blue-600">
89 User's Manual</h3>
90 <p class="text-sm text-slate-500 mt-1">
91 Stable documentation for end-users.</p>
92 </div>
93 <span class="text-xs font-bold uppercase tracking-wider
94 bg-blue-100 text-blue-700 px-2 py-1 rounded">
95 Stable</span>
96 </div>
97 </a>
99 <a href="main/docs/api/index.html"
100 class="hover-card block p-5 bg-[#F5F5F5] rounded-xl shadow-sm border
101 border-slate-200 hover:border-blue-600 group">
102 <div class="flex justify-between items-start">
103 <div>
104 <h3 class="font-bold text-lg group-hover:text-blue-600">
105 API Reference</h3>
106 <p class="text-sm text-slate-500 mt-1">
107 Technical API documentation.</p>
108 </div>
109 <span class="text-xs font-bold uppercase tracking-wider
110 bg-blue-100 text-blue-700 px-2 py-1 rounded">
111 Stable</span>
112 </div>
113 </a>
115 <div class="grid grid-cols-2 gap-4">
116 <a href="main/reports/lint/index.html"
117 class="hover-card p-4 bg-[#F5F5F5] rounded-xl shadow-sm border
118 border-slate-200 hover:border-blue-600">
119 <span class="block text-xs font-bold text-slate-400
120 uppercase mb-2">Code Quality</span>
121 <img src="main/badges/lint.svg" alt="Lint Score" class="h-5">
122 </a>
123 <a href="main/reports/coverage/index.html"
124 class="hover-card p-4 bg-[#F5F5F5] rounded-xl shadow-sm border
125 border-slate-200 hover:border-blue-600">
126 <span class="block text-xs font-bold text-slate-400
127 uppercase mb-2">Test Coverage</span>
128 <img src="main/badges/coverage.svg" alt="Coverage" class="h-5">
129 </a>
130 </div>
131 </div>
132 </section>
134 <section class="space-y-6">
135 <div class="flex items-center justify-between border-b-2 border-orange-200 pb-2">
136 <h2 class="text-2xl font-bold flex items-center gap-2">
137 🛠️ Development
138 </h2>
139 <a href="{github_url}/tree/dev"
140 class="text-xs font-semibold bg-orange-100 text-orange-700
141 px-2 py-1 rounded hover:bg-orange-200">dev branch</a>
142 </div>
144 <div class="space-y-4">
145 <a href="dev/docs/userguide/book/index.html"
146 class="hover-card block p-5 bg-[#F5F5F5] rounded-xl shadow-sm border
147 border-slate-200 hover:border-orange-500 group">
148 <div class="flex justify-between items-start">
149 <div>
150 <h3 class="font-bold text-lg group-hover:text-orange-600">
151 User's Manual</h3>
152 <p class="text-sm text-slate-500 mt-1">
153 Development documentation.</p>
154 </div>
155 <span class="text-xs font-bold uppercase tracking-wider
156 bg-orange-100 text-orange-700 px-2 py-1 rounded">
157 Latest</span>
158 </div>
159 </a>
161 <a href="dev/docs/api/index.html"
162 class="hover-card block p-5 bg-[#F5F5F5] rounded-xl shadow-sm border
163 border-slate-200 hover:border-orange-500 group">
164 <div class="flex justify-between items-start">
165 <div>
166 <h3 class="font-bold text-lg group-hover:text-orange-600">
167 API Reference</h3>
168 <p class="text-sm text-slate-500 mt-1">
169 Technical API documentation.</p>
170 </div>
171 <span class="text-xs font-bold uppercase tracking-wider
172 bg-orange-100 text-orange-700 px-2 py-1 rounded">
173 Latest</span>
174 </div>
175 </a>
177 <div class="grid grid-cols-2 gap-4">
178 <a href="dev/reports/lint/index.html"
179 class="hover-card p-4 bg-[#F5F5F5] rounded-xl shadow-sm border
180 border-slate-200 hover:border-orange-500">
181 <span class="block text-xs font-bold text-slate-400
182 uppercase mb-2">Code Quality</span>
183 <img src="dev/badges/lint.svg" alt="Lint Score" class="h-5">
184 </a>
185 <a href="dev/reports/coverage/index.html"
186 class="hover-card p-4 bg-[#F5F5F5] rounded-xl shadow-sm border
187 border-slate-200 hover:border-orange-500">
188 <span class="block text-xs font-bold text-slate-400
189 uppercase mb-2">Test Coverage</span>
190 <img src="dev/badges/coverage.svg" alt="Coverage" class="h-5">
191 </a>
192 </div>
193 </div>
194 </section>
196 </div>
198 <section class="mt-16 bg-[#F5F5F5] p-8 rounded-xl shadow-sm border border-slate-200">
199 <h2 class="text-xl font-bold mb-4 border-b pb-2">Build Metadata</h2>
200 <div class="flex flex-col gap-0 text-sm leading-tight text-slate-600">
201 <div>
202 <span class="font-semibold">Generated:</span> {timestamp_ext}
203 </div>
204 <div>
205 <span class="font-semibold">Run ID:</span>
206 <a href="{run_url}" class="text-blue-600 hover:underline">{metadata.run_id}</a>
207 </div>
208 <div>
209 <span class="font-semibold">Branch:</span>
210 <a href="{branch_url}" class="text-blue-600 hover:underline">{metadata.ref_name}</a>
211 </div>
212 <div>
213 <span class="font-semibold">Commit:</span>
214 <a href="{commit_url}" class="text-blue-600 hover:underline">{metadata.github_sha[:7]}</a>
215 </div>
216 <div>
217 <span class="font-semibold">Repository:</span>
218 <a href="{github_url}" class="text-blue-600 hover:underline">{metadata.github_repo}</a>
219 </div>
220 </div>
221 </section>
222 </main>
224 <footer class="mt-20 py-10 border-t border-slate-200 bg-[#F5F5F5]">
225 <div class="max-w-7xl mx-auto px-4 text-center">
226 <p class="text-sm text-slate-400">
227 © 2026 Sandia National Laboratories | Released under <a href="{github_url}/blob/main/LICENSE" class="text-blue-600 hover:underline">MIT License</a>
228 </p>
229 </div>
230 </footer>
232</body>
233</html>"""
236def main():
237 """Main entry point."""
238 parser = argparse.ArgumentParser(
239 description="Generate Project Dashboard index.html"
240 )
241 parser.add_argument("--output_file", required=True, help="Output HTML file path")
243 add_common_args(parser)
245 args = parser.parse_args()
247 metadata = report_metadata_creation(args)
249 html = generate_dashboard_html(metadata)
251 output_dir = os.path.dirname(args.output_file)
252 if output_dir: 252 ↛ 255line 252 didn't jump to line 255, because the condition on line 252 was always true
253 os.makedirs(output_dir, exist_ok=True)
255 with open(args.output_file, "w", encoding="utf-8") as f:
256 f.write(html)
258 print(f"[OK] Project Dashboard generated: {args.output_file}")
261if __name__ == "__main__":
262 main()