feat(recipe-report): link recipe names in the lead to their mirror repos; 3-para concise lead
render() auto-links whole-word recipe mentions in the editorial lead to git.autonomic.zone/recipe-maintainers/<recipe> (single regex pass, longest-name-first, no href corruption). Skill: lead is ~3 short paragraphs (~150-180 words) incl. an 'anything strange worth looking into' paragraph. example-spec.json lead updated to the concise target. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -29,11 +29,14 @@ Helper: `python3 /srv/cc-ci/cc-ci-plan/recipe-report.py {survey|render|publish}`
|
||||
of the version bumps) for upgrades that fix **CVEs / security issues**. Anything **critical/high**
|
||||
leads the page → the `security` bulletin (recipe · CVE id(s) + severity · what it fixes · PR link).
|
||||
This is the most important section; be specific about severity and what's exposed if not merged.
|
||||
- **Lead / editorial.** Write the `lead`: the **overall state of the recipe fleet** this week (how
|
||||
healthy, what moved, any worrying trend) and **specific, opinionated suggestions of what to focus
|
||||
on** — opus's voice, useful and concrete. **Keep it TIGHT: 2 short paragraphs, ~120 words total** —
|
||||
lead with the single most important thing, then security/focus in a sentence or two. (Trim hard;
|
||||
the rest of the page carries the detail.)
|
||||
- **Lead / editorial.** Write the `lead` in opus's voice — useful, concrete, opinionated. **~3 short
|
||||
paragraphs, ~150–180 words:**
|
||||
1. **Fleet state** in a line or two — how healthy, what moved, any trend.
|
||||
2. **What to focus on** — security/critical merges first, then the key failures.
|
||||
3. **Anything strange worth looking into** — odd or unexpected failures, parser snags, PR-state
|
||||
oddities (e.g. a recipe carrying two open PRs to reconcile), drift from the summary, leftover
|
||||
artifacts. This is the "editor's eye" paragraph; flag what a careful maintainer would want to notice.
|
||||
Lead with the single most important thing; the rest of the page carries the detail.
|
||||
- **Needs attention** — GREEN PRs ready to merge + errors/failures to investigate (RED `!testme`,
|
||||
recipe bugs). Short, specific prose + links. Flag cross-cutting issues (e.g. two open PRs to reconcile).
|
||||
- **Routine** — minor/clean bumps, stale-test PRs (need operator `--with-tests`), up-to-date / skipped.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -21,7 +21,7 @@ SPEC SHAPE (the agent writes this JSON):
|
||||
"pr":"#4","pr_url":"…","notes":"…"}]}
|
||||
PUBLIC PAGE — include only public-safe data (no secrets/tokens/raw logs).
|
||||
"""
|
||||
import base64, html, json, os, subprocess, sys, urllib.request
|
||||
import base64, html, json, os, re, subprocess, sys, urllib.request
|
||||
from datetime import datetime, timezone
|
||||
|
||||
LOGDIR = "/srv/cc-ci/.cc-ci-logs"
|
||||
@ -121,6 +121,17 @@ def _esc(s):
|
||||
return html.escape(str(s or ""))
|
||||
|
||||
|
||||
def _linkify_recipes(text, repo_url):
|
||||
"""Linkify whole-word recipe-name mentions to their mirror repo. ONE pass over the (already
|
||||
HTML-escaped) text, longest names first so 'custom-html-tiny' wins over 'custom-html'; re.sub does
|
||||
not re-scan inserted hrefs, so URLs that end in a recipe name aren't double-linked."""
|
||||
if not repo_url:
|
||||
return text
|
||||
names = sorted(repo_url, key=len, reverse=True)
|
||||
pat = re.compile(r"(?<![\w-])(" + "|".join(re.escape(n) for n in names) + r")(?![\w-])")
|
||||
return pat.sub(lambda m: f'<a href="{repo_url[m.group(1)]}">{m.group(1)}</a>', text)
|
||||
|
||||
|
||||
def _links(links):
|
||||
if not links:
|
||||
return ""
|
||||
@ -172,8 +183,13 @@ def render(spec_path, out_path):
|
||||
gen = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
||||
sub = s.get("subtitle", "Week of " + s["date"])
|
||||
lead = s.get("lead", "") or ""
|
||||
# Auto-link recipe-name mentions in the lead to their mirror repos.
|
||||
gitea = _env().get("GITEA_URL", "git.autonomic.zone")
|
||||
repo_url = {r["recipe"]: f"https://{gitea}/recipe-maintainers/{r['recipe']}"
|
||||
for r in (s.get("table") or []) if r.get("recipe")}
|
||||
if lead and "<p>" not in lead:
|
||||
lead = "".join(f"<p>{_esc(p.strip())}</p>" for p in lead.split("\n\n") if p.strip())
|
||||
lead = "".join(f"<p>{_linkify_recipes(_esc(p.strip()), repo_url)}</p>"
|
||||
for p in lead.split("\n\n") if p.strip())
|
||||
body = (_mast() +
|
||||
f'<div class="dateline"><span>{_esc(sub)}</span>'
|
||||
f'<span>report.ci.commoninternet.net</span><span>{gen}</span></div>'
|
||||
|
||||
Reference in New Issue
Block a user