Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
"""
|
|
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"<PlaybookLintResult(filename={self.filename}, score={self.quality_score})>"
|
|
|
|
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,
|
|
}
|