""" Model for storing ansible-lint results per playbook. """ from datetime import datetime, timezone from typing import Optional from sqlalchemy import Column, DateTime, Integer, String, Text, JSON from sqlalchemy.orm import Mapped, mapped_column from .database import Base class PlaybookLintResult(Base): """Stores the latest ansible-lint result for each playbook.""" __tablename__ = "playbook_lint_results" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) # Playbook filename (unique constraint) filename: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True) # Quality score (0-100) quality_score: Mapped[int] = mapped_column(Integer, nullable=False, default=100) # Summary counts total_issues: Mapped[int] = mapped_column(Integer, nullable=False, default=0) errors_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0) warnings_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0) # Execution time in milliseconds execution_time_ms: Mapped[int] = mapped_column(Integer, nullable=False, default=0) # Full issues list as JSON issues_json: Mapped[Optional[str]] = mapped_column(Text, nullable=True) # Raw output from ansible-lint (for copy to clipboard) raw_output: Mapped[Optional[str]] = mapped_column(Text, nullable=True) # Timestamps created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc) ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc) ) def __repr__(self) -> str: return f"" def to_dict(self) -> dict: """Convert to dictionary for API response.""" import json issues = [] if self.issues_json: try: issues = json.loads(self.issues_json) except (json.JSONDecodeError, TypeError): issues = [] return { "id": self.id, "filename": self.filename, "quality_score": self.quality_score, "summary": { "total": self.total_issues, "errors": self.errors_count, "warnings": self.warnings_count, }, "issues": issues, "execution_time_ms": self.execution_time_ms, "created_at": self.created_at.isoformat() if self.created_at else None, "updated_at": self.updated_at.isoformat() if self.updated_at else None, }