feat(sofiia-console): add auto-evidence and post-review generation from runbook runs
- adds runbook_artifacts.py: server-side render of release_evidence.md and
post_review.md from DB step results (no shell); saves to
SOFIIA_DATA_DIR/release_artifacts/<run_id>/
- evidence: auto-fills preflight/smoke/script outcomes, step table, timestamps
- post_review: auto-fills metadata, smoke results, incidents from step statuses;
leaves [TODO] markers for manual observation sections
- adds POST /api/runbooks/runs/{run_id}/evidence and /post_review endpoints
- updates runbook_runs.evidence_path in DB after render
- adds 11 tests covering file creation, key sections, TODO markers, 404s, API
Made-with: Cursor
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
Runbook runs API — create run, get run, next step, complete step, abort (PR2).
|
||||
Evidence + post-review generation (PR4).
|
||||
All under require_auth.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
@@ -10,6 +11,7 @@ from fastapi import APIRouter, Depends, HTTPException, Body
|
||||
|
||||
from .auth import require_auth
|
||||
from . import runbook_runner as runner
|
||||
from . import runbook_artifacts as artifacts
|
||||
|
||||
runbook_runs_router = APIRouter(prefix="/api/runbooks/runs", tags=["runbook-runs"])
|
||||
|
||||
@@ -80,6 +82,32 @@ async def complete_step(
|
||||
return {"ok": True, "run_id": run_id, "step_index": step_index, "next_step": step_index + 1}
|
||||
|
||||
|
||||
@runbook_runs_router.post("/{run_id}/evidence")
|
||||
async def generate_evidence(
|
||||
run_id: str,
|
||||
_auth: str = Depends(require_auth),
|
||||
):
|
||||
"""Generate release evidence markdown from run step results. Returns {evidence_path, bytes, created_at}."""
|
||||
try:
|
||||
out = await artifacts.render_release_evidence(run_id)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return out
|
||||
|
||||
|
||||
@runbook_runs_router.post("/{run_id}/post_review")
|
||||
async def generate_post_review(
|
||||
run_id: str,
|
||||
_auth: str = Depends(require_auth),
|
||||
):
|
||||
"""Generate post-release review markdown. Returns {path, bytes, created_at}."""
|
||||
try:
|
||||
out = await artifacts.render_post_review(run_id)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return out
|
||||
|
||||
|
||||
@runbook_runs_router.post("/{run_id}/abort")
|
||||
async def abort_run(
|
||||
run_id: str,
|
||||
|
||||
Reference in New Issue
Block a user