- Configure Alembic for async migrations with SQLAlchemy 2.0 - Create Build model with UUID primary key, config_hash, status enum - Add indexes on status (queue queries) and config_hash (cache lookups) - Generate and apply initial migration creating builds table Build model fields: id, config_hash, status, iso_path, error_message, build_log, started_at, completed_at, created_at, updated_at.
113 lines
3 KiB
Python
113 lines
3 KiB
Python
"""Build tracking model for ISO generation."""
|
|
|
|
import enum
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import DateTime, Enum, Index, String, Text, func
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from backend.app.db.base import Base
|
|
|
|
|
|
class BuildStatus(enum.Enum):
|
|
"""Status values for build tracking."""
|
|
|
|
PENDING = "pending"
|
|
BUILDING = "building"
|
|
COMPLETED = "completed"
|
|
FAILED = "failed"
|
|
CACHED = "cached"
|
|
|
|
|
|
class Build(Base):
|
|
"""Model for tracking ISO build jobs.
|
|
|
|
Attributes:
|
|
id: Unique identifier for the build (UUID)
|
|
config_hash: SHA-256 hash of the build configuration (64 chars)
|
|
status: Current build status
|
|
iso_path: Path to generated ISO file (if completed)
|
|
error_message: Error message if build failed
|
|
build_log: Full build output log
|
|
started_at: Timestamp when build started
|
|
completed_at: Timestamp when build completed
|
|
created_at: Timestamp when build was created
|
|
updated_at: Timestamp of last update
|
|
|
|
The config_hash enables caching - identical configurations can
|
|
return existing ISOs without rebuilding.
|
|
"""
|
|
|
|
__tablename__ = "builds"
|
|
|
|
# Primary key
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
primary_key=True,
|
|
default=uuid.uuid4,
|
|
)
|
|
|
|
# Configuration hash for caching (SHA-256 = 64 hex chars)
|
|
config_hash: Mapped[str] = mapped_column(
|
|
String(64),
|
|
unique=True,
|
|
index=True,
|
|
nullable=False,
|
|
)
|
|
|
|
# Build status
|
|
status: Mapped[BuildStatus] = mapped_column(
|
|
Enum(BuildStatus),
|
|
default=BuildStatus.PENDING,
|
|
nullable=False,
|
|
)
|
|
|
|
# Build results
|
|
iso_path: Mapped[str | None] = mapped_column(
|
|
String(512),
|
|
nullable=True,
|
|
)
|
|
error_message: Mapped[str | None] = mapped_column(
|
|
Text,
|
|
nullable=True,
|
|
)
|
|
build_log: Mapped[str | None] = mapped_column(
|
|
Text,
|
|
nullable=True,
|
|
)
|
|
|
|
# Timing
|
|
started_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True),
|
|
nullable=True,
|
|
)
|
|
completed_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True),
|
|
nullable=True,
|
|
)
|
|
|
|
# Audit timestamps
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
nullable=False,
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
nullable=False,
|
|
)
|
|
|
|
# Indexes for common queries
|
|
__table_args__ = (
|
|
# Index on status for queue queries (find pending builds)
|
|
Index("ix_builds_status", "status"),
|
|
# Index on config_hash already created via column definition
|
|
)
|
|
|
|
def __repr__(self) -> str:
|
|
"""String representation of Build."""
|
|
return f"<Build {self.id} status={self.status.value}>"
|