@@ -170,6 +170,276 @@ jobs:
170170 echo "<p>Stay up to date with the latest Armbian news, development highlights, and tips — delivered straight to your inbox.</p>"
171171 } > summary.md
172172
173+ - name : " Generate HTML digest table"
174+ shell : bash
175+ run : |
176+ cat > out/digest.html <<'HTMLEOF'
177+ <!DOCTYPE html>
178+ <html lang="en">
179+ <head>
180+ <meta charset="UTF-8">
181+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
182+ <title>${LABEL} - Armbian PR Digest</title>
183+ <style>
184+ :root {
185+ --bg-primary: #0d1117;
186+ --bg-secondary: #161b22;
187+ --bg-tertiary: #21262d;
188+ --border-color: #30363d;
189+ --text-primary: #c9d1d9;
190+ --text-secondary: #8b949e;
191+ --text-muted: #6e7681;
192+ --accent: #58a6ff;
193+ --accent-hover: #79c0ff;
194+ --success: #3fb950;
195+ --armbian-orange: #f88a29;
196+ --armbian-blue: #007bff;
197+ }
198+ * { margin: 0; padding: 0; box-sizing: border-box; }
199+ body {
200+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
201+ background: var(--bg-primary);
202+ color: var(--text-primary);
203+ line-height: 1.6;
204+ padding: 20px;
205+ }
206+ .container {
207+ max-width: 1200px;
208+ margin: 0 auto;
209+ }
210+ header {
211+ text-align: center;
212+ padding: 40px 20px;
213+ border-bottom: 1px solid var(--border-color);
214+ margin-bottom: 30px;
215+ }
216+ h1 {
217+ font-size: 2.5rem;
218+ margin-bottom: 10px;
219+ background: linear-gradient(135deg, var(--armbian-orange), var(--armbian-blue));
220+ -webkit-background-clip: text;
221+ -webkit-text-fill-color: transparent;
222+ background-clip: text;
223+ }
224+ .subtitle {
225+ color: var(--text-secondary);
226+ font-size: 1.1rem;
227+ }
228+ .meta {
229+ display: flex;
230+ justify-content: center;
231+ gap: 20px;
232+ flex-wrap: wrap;
233+ margin-bottom: 20px;
234+ }
235+ .meta-item {
236+ background: var(--bg-secondary);
237+ padding: 8px 16px;
238+ border-radius: 6px;
239+ font-size: 0.9rem;
240+ }
241+ .table-container {
242+ background: var(--bg-secondary);
243+ border-radius: 12px;
244+ overflow: hidden;
245+ border: 1px solid var(--border-color);
246+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
247+ }
248+ table {
249+ width: 100%;
250+ border-collapse: collapse;
251+ }
252+ thead {
253+ background: var(--bg-tertiary);
254+ }
255+ th {
256+ padding: 16px;
257+ text-align: left;
258+ font-weight: 600;
259+ color: var(--text-primary);
260+ border-bottom: 2px solid var(--border-color);
261+ font-size: 0.85rem;
262+ text-transform: uppercase;
263+ letter-spacing: 0.5px;
264+ }
265+ td {
266+ padding: 14px 16px;
267+ border-bottom: 1px solid var(--border-color);
268+ vertical-align: middle;
269+ }
270+ tr:last-child td {
271+ border-bottom: none;
272+ }
273+ tr:hover {
274+ background: var(--bg-tertiary);
275+ }
276+ .pr-title {
277+ font-weight: 500;
278+ color: var(--text-primary);
279+ margin-bottom: 6px;
280+ }
281+ .pr-meta {
282+ display: flex;
283+ gap: 8px;
284+ flex-wrap: wrap;
285+ align-items: center;
286+ }
287+ .badge {
288+ display: inline-block;
289+ padding: 3px 10px;
290+ border-radius: 12px;
291+ font-size: 0.75rem;
292+ font-weight: 500;
293+ }
294+ .badge-repo {
295+ background: rgba(88, 166, 255, 0.15);
296+ color: var(--accent);
297+ border: 1px solid rgba(88, 166, 255, 0.3);
298+ }
299+ .badge-author {
300+ background: rgba(248, 138, 41, 0.15);
301+ color: var(--armbian-orange);
302+ border: 1px solid rgba(248, 138, 41, 0.3);
303+ }
304+ .pr-link {
305+ color: var(--accent);
306+ text-decoration: none;
307+ font-size: 0.9rem;
308+ display: inline-flex;
309+ align-items: center;
310+ }
311+ .pr-link:hover {
312+ color: var(--accent-hover);
313+ text-decoration: underline;
314+ }
315+ .pr-link::before {
316+ content: "→";
317+ margin-right: 6px;
318+ }
319+ .no-prs {
320+ text-align: center;
321+ padding: 60px 20px;
322+ color: var(--text-muted);
323+ font-size: 1.1rem;
324+ }
325+ .no-prs-icon {
326+ font-size: 3rem;
327+ margin-bottom: 16px;
328+ opacity: 0.5;
329+ }
330+ footer {
331+ margin-top: 40px;
332+ text-align: center;
333+ padding: 30px 20px;
334+ border-top: 1px solid var(--border-color);
335+ color: var(--text-secondary);
336+ }
337+ .footer-link {
338+ color: var(--accent);
339+ text-decoration: none;
340+ font-weight: 500;
341+ }
342+ .footer-link:hover {
343+ text-decoration: underline;
344+ }
345+ .generated-time {
346+ margin-top: 10px;
347+ font-size: 0.85rem;
348+ color: var(--text-muted);
349+ }
350+ @media (max-width: 768px) {
351+ .meta {
352+ flex-direction: column;
353+ }
354+ .pr-meta {
355+ flex-direction: column;
356+ gap: 6px;
357+ }
358+ th, td {
359+ padding: 12px;
360+ }
361+ }
362+ </style>
363+ </head>
364+ <body>
365+ <div class="container">
366+ <header>
367+ <h1>${LABEL}</h1>
368+ <p class="subtitle">Armbian Pull Request Digest</p>
369+ <div class="meta">
370+ <div class="meta-item">📅 Period: ${PERIOD}</div>
371+ <div class="meta-item">📅 From: ${SINCE_UTC}</div>
372+ <div class="meta-item">📅 Until: ${UNTIL_UTC}</div>
373+ </div>
374+ </header>
375+ HTMLEOF
376+
377+ # Generate table rows
378+ if [[ ! -s out/pr-digest.tsv ]]; then
379+ cat >> out/digest.html <<'EOF'
380+ <div class="table-container">
381+ <div class="no-prs">
382+ <div class="no-prs-icon">📭</div>
383+ <p>No merged PRs in this period.</p>
384+ </div>
385+ </div>
386+ EOF
387+ else
388+ cat >> out/digest.html <<'EOF'
389+ <div class="table-container">
390+ <table>
391+ <thead>
392+ <tr>
393+ <th width="50%">Pull Request</th>
394+ <th>Author</th>
395+ <th>Repository</th>
396+ <th>Link</th>
397+ </tr>
398+ </thead>
399+ <tbody>
400+ EOF
401+
402+ while IFS=$'\t' read -r title author repo num pr_url; do
403+ repo_name="${repo##*/}"
404+ cat >> out/digest.html <<EOF
405+ <tr>
406+ <td>
407+ <div class="pr-title">${title}</div>
408+ <div class="pr-meta">
409+ <span class="badge badge-repo">${repo_name}</span>
410+ </div>
411+ </td>
412+ <td><span class="badge badge-author">@${author}</span></td>
413+ <td>${repo_name}</td>
414+ <td><a class="pr-link" href="${pr_url}" target="_blank">View PR #${num}</a></td>
415+ </tr>
416+ EOF
417+ done < out/pr-digest.tsv
418+
419+ cat >> out/digest.html <<'EOF'
420+ </tbody>
421+ </table>
422+ </div>
423+ EOF
424+ fi
425+
426+ cat >> out/digest.html <<'EOF'
427+ <footer>
428+ <a class="footer-link" href="https://blog.armbian.com/#/portal/signup" target="_blank">
429+ 📬 Subscribe to Armbian Blog
430+ </a>
431+ <p style="margin-top: 15px; font-size: 0.9rem; color: var(--text-muted);">
432+ Stay up to date with the latest Armbian news, development highlights, and tips.
433+ </p>
434+ <div class="generated-time">
435+ Generated: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
436+ </div>
437+ </footer>
438+ </div>
439+ </body>
440+ </html>
441+ HTMLEOF
442+
173443 - name : Upload raw data (artifacts)
174444 uses : actions/upload-artifact@v7
175445 with :
0 commit comments