Finalized dependency aware scope prop

This commit is contained in:
2026-05-03 14:45:56 +02:00
parent 58f53e18de
commit 256dd497a0
4 changed files with 84 additions and 3 deletions

View File

@@ -1619,6 +1619,11 @@ def analysis_run_diff_detail(
base_analysis_run_id,
target_analysis_run_id,
)
impact = service.analyze_dependency_impact(
repository_id,
base_analysis_run_id,
target_analysis_run_id,
)
except NotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
display_name = repository_display_name(diff.repository)
@@ -1639,6 +1644,13 @@ def analysis_run_diff_detail(
</form>
</div>
</section>
<section class="panel" style="margin-top:18px">
<div class="actions">
<h2 style="margin-right:auto">Dependency Impact</h2>
<a class="button secondary" href="/ui/repos/{repository_id}/dependency-graph?base_analysis_run_id={base_analysis_run_id}&target_analysis_run_id={target_analysis_run_id}">Open Graph</a>
</div>
{render_dependency_impact_summary(asdict(impact))}
</section>
<div class="grid" style="margin-top:18px">
<section class="panel">
<h2>Approved Registry Impact</h2>
@@ -2403,6 +2415,65 @@ def render_diff_section(section: dict) -> str:
return rendered or '<p class="muted">No differences.</p>'
def render_dependency_impact_summary(impact: dict) -> str:
impacts = impact.get("impacts", [])
metric_row = (
f'<span class="pill">{escape(str(impact.get("propagation_breadth", 0)))} impacted</span>'
f'<span class="pill">depth {escape(str(impact.get("max_depth", 0)))}</span>'
+ (
'<span class="pill">scope impacted</span>'
if impact.get("scope_impacted")
else '<span class="pill">scope current</span>'
)
)
changed_facts = impact.get("changed_fact_keys", [])
changed_fact_rows = "".join(
f'<li class="source">{escape(str(fact_key))}</li>'
for fact_key in changed_facts[:8]
)
changed_fact_note = (
f"<ul>{changed_fact_rows}</ul>"
if changed_fact_rows
else '<p class="muted">No changed facts reached approved characteristics.</p>'
)
rows = "\n".join(
f"""
<tr>
<td><span class="pill">{escape(str(item.get('item_kind', '')))}</span></td>
<td>{escape(str(item.get('name', '')))}</td>
<td><span class="pill">{escape(str(item.get('freshness_state', '')))}</span></td>
<td>{escape(str(item.get('recommended_action', '')))}</td>
<td>{escape(str(item.get('impact_depth', '')))}</td>
<td>{render_impact_reasons(item.get('reasons', []))}</td>
</tr>
"""
for item in impacts
)
table = (
f"""
<table>
<thead><tr><th>Kind</th><th>Name</th><th>Freshness</th><th>Action</th><th>Depth</th><th>Why</th></tr></thead>
<tbody>{rows}</tbody>
</table>
"""
if rows
else '<p class="muted">No approved downstream items were marked stale.</p>'
)
return f"""
<div class="actions">{metric_row}</div>
<h3>Changed Facts</h3>
{changed_fact_note}
<h3>Impacted Items</h3>
{table}
"""
def render_impact_reasons(reasons: list[str]) -> str:
if not reasons:
return '<span class="muted">No reason recorded.</span>'
return "<br>".join(escape(str(reason)) for reason in reasons[:3])
def render_diff_group(items: list[dict], title: str) -> str:
if not items:
return ""