175 lines
10 KiB
Python
175 lines
10 KiB
Python
"""finalize v1 productization
|
|
|
|
Revision ID: 20260421_finalize_v1_productization
|
|
Revises: 20260421_add_ai_project_control_tables
|
|
Create Date: 2026-04-21
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
try:
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
except Exception: # pragma: no cover
|
|
JSONB = sa.JSON
|
|
|
|
|
|
revision = "20260421_finalize_v1_productization"
|
|
down_revision = "20260421_add_ai_project_control_tables"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def _json_type(bind):
|
|
return JSONB() if bind.dialect.name == "postgresql" else sa.JSON()
|
|
|
|
|
|
def _table_exists(bind, table_name: str) -> bool:
|
|
return sa.inspect(bind).has_table(table_name)
|
|
|
|
|
|
def _column_exists(bind, table_name: str, column_name: str) -> bool:
|
|
if not _table_exists(bind, table_name):
|
|
return False
|
|
return any(column.get("name") == column_name for column in sa.inspect(bind).get_columns(table_name))
|
|
|
|
|
|
def upgrade() -> None:
|
|
bind = op.get_bind()
|
|
json_type = _json_type(bind)
|
|
|
|
if _table_exists(bind, "users") and _column_exists(bind, "users", "role"):
|
|
op.execute("UPDATE users SET role = 'OWNER' WHERE UPPER(role) = 'BOSS'")
|
|
op.execute("UPDATE users SET role = 'REVIEWER' WHERE UPPER(role) = 'ADMIN'")
|
|
op.execute("UPDATE users SET role = 'BUILDER' WHERE UPPER(role) IN ('AI', 'FE', 'BE')")
|
|
|
|
if _table_exists(bind, "revenue_events") and not _column_exists(bind, "revenue_events", "category"):
|
|
op.add_column(
|
|
"revenue_events",
|
|
sa.Column("category", sa.String(length=32), nullable=False, server_default="other"),
|
|
)
|
|
op.create_index("ix_revenue_events_category", "revenue_events", ["category"], unique=False)
|
|
|
|
if _table_exists(bind, "repo_bindings") and not _column_exists(bind, "repo_bindings", "installation_account_login"):
|
|
op.add_column(
|
|
"repo_bindings",
|
|
sa.Column("installation_account_login", sa.String(length=255), nullable=True),
|
|
)
|
|
|
|
if _table_exists(bind, "progress_events") and not _column_exists(bind, "progress_events", "delivery_id"):
|
|
op.add_column("progress_events", sa.Column("delivery_id", sa.String(length=255), nullable=True))
|
|
op.create_index("ix_progress_events_delivery_id", "progress_events", ["delivery_id"], unique=False)
|
|
if _table_exists(bind, "progress_events") and not _column_exists(bind, "progress_events", "event_source_id"):
|
|
op.add_column("progress_events", sa.Column("event_source_id", sa.String(length=255), nullable=True))
|
|
op.create_index("ix_progress_events_event_source_id", "progress_events", ["event_source_id"], unique=False)
|
|
|
|
if not _table_exists(bind, "github_app_installations"):
|
|
op.create_table(
|
|
"github_app_installations",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("tenant_id", sa.BigInteger(), nullable=False),
|
|
sa.Column("created_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False),
|
|
sa.Column("updated_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False),
|
|
sa.Column("installation_id", sa.String(length=255), nullable=False),
|
|
sa.Column("account_login", sa.String(length=255), nullable=False),
|
|
sa.Column("account_type", sa.String(length=64), nullable=True),
|
|
sa.Column("app_slug", sa.String(length=255), nullable=True),
|
|
sa.Column("target_type", sa.String(length=64), nullable=True),
|
|
sa.Column("status", sa.String(length=32), nullable=False, server_default="active"),
|
|
sa.Column("permissions", json_type, nullable=False),
|
|
sa.Column("events", json_type, nullable=False),
|
|
sa.Column("metadata", json_type, nullable=False),
|
|
sa.Column("last_synced_at", sa.TIMESTAMP(), nullable=True),
|
|
sa.UniqueConstraint("tenant_id", "installation_id", name="uq_github_app_installations_tenant_installation"),
|
|
)
|
|
op.create_index("ix_github_app_installations_tenant_id", "github_app_installations", ["tenant_id"], unique=False)
|
|
op.create_index("ix_github_app_installations_installation_id", "github_app_installations", ["installation_id"], unique=False)
|
|
op.create_index("ix_github_app_installations_account_login", "github_app_installations", ["account_login"], unique=False)
|
|
op.create_index("ix_github_app_installations_status", "github_app_installations", ["status"], unique=False)
|
|
|
|
if not _table_exists(bind, "github_app_repositories"):
|
|
op.create_table(
|
|
"github_app_repositories",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("tenant_id", sa.BigInteger(), nullable=False),
|
|
sa.Column("created_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False),
|
|
sa.Column("updated_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False),
|
|
sa.Column("installation_id", sa.String(length=255), nullable=False),
|
|
sa.Column("external_repo_id", sa.String(length=255), nullable=False),
|
|
sa.Column("owner", sa.String(length=255), nullable=False),
|
|
sa.Column("repo_name", sa.String(length=255), nullable=False),
|
|
sa.Column("full_name", sa.String(length=255), nullable=False),
|
|
sa.Column("default_branch", sa.String(length=255), nullable=True),
|
|
sa.Column("is_private", sa.Boolean(), nullable=False, server_default=sa.true()),
|
|
sa.Column("permissions", json_type, nullable=False),
|
|
sa.Column("status", sa.String(length=32), nullable=False, server_default="active"),
|
|
sa.Column("last_synced_at", sa.TIMESTAMP(), nullable=True),
|
|
sa.UniqueConstraint(
|
|
"tenant_id",
|
|
"installation_id",
|
|
"external_repo_id",
|
|
name="uq_github_app_repositories_repo",
|
|
),
|
|
)
|
|
op.create_index("ix_github_app_repositories_tenant_id", "github_app_repositories", ["tenant_id"], unique=False)
|
|
op.create_index("ix_github_app_repositories_installation_id", "github_app_repositories", ["installation_id"], unique=False)
|
|
op.create_index("ix_github_app_repositories_external_repo_id", "github_app_repositories", ["external_repo_id"], unique=False)
|
|
op.create_index("ix_github_app_repositories_owner", "github_app_repositories", ["owner"], unique=False)
|
|
op.create_index("ix_github_app_repositories_repo_name", "github_app_repositories", ["repo_name"], unique=False)
|
|
op.create_index("ix_github_app_repositories_full_name", "github_app_repositories", ["full_name"], unique=False)
|
|
op.create_index("ix_github_app_repositories_status", "github_app_repositories", ["status"], unique=False)
|
|
|
|
if not _table_exists(bind, "github_webhook_deliveries"):
|
|
op.create_table(
|
|
"github_webhook_deliveries",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("tenant_id", sa.BigInteger(), nullable=False),
|
|
sa.Column("created_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False),
|
|
sa.Column("updated_at", sa.TIMESTAMP(), server_default=sa.func.now(), nullable=False),
|
|
sa.Column("delivery_id", sa.String(length=255), nullable=False),
|
|
sa.Column("event_type", sa.String(length=64), nullable=False),
|
|
sa.Column("repo_binding_id", sa.BigInteger(), sa.ForeignKey("repo_bindings.id"), nullable=True),
|
|
sa.Column("project_id", sa.BigInteger(), sa.ForeignKey("projects.id"), nullable=True),
|
|
sa.Column("installation_id", sa.String(length=255), nullable=True),
|
|
sa.Column("status", sa.String(length=32), nullable=False, server_default="received"),
|
|
sa.Column("failure_reason", sa.Text(), nullable=True),
|
|
sa.Column("payload", json_type, nullable=False),
|
|
sa.Column("received_at", sa.TIMESTAMP(), nullable=True),
|
|
sa.UniqueConstraint("tenant_id", "delivery_id", name="uq_github_webhook_deliveries_tenant_delivery"),
|
|
)
|
|
op.create_index("ix_github_webhook_deliveries_tenant_id", "github_webhook_deliveries", ["tenant_id"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_delivery_id", "github_webhook_deliveries", ["delivery_id"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_event_type", "github_webhook_deliveries", ["event_type"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_repo_binding_id", "github_webhook_deliveries", ["repo_binding_id"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_project_id", "github_webhook_deliveries", ["project_id"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_installation_id", "github_webhook_deliveries", ["installation_id"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_status", "github_webhook_deliveries", ["status"], unique=False)
|
|
op.create_index("ix_github_webhook_deliveries_received_at", "github_webhook_deliveries", ["received_at"], unique=False)
|
|
|
|
|
|
def downgrade() -> None:
|
|
bind = op.get_bind()
|
|
|
|
if _table_exists(bind, "github_webhook_deliveries"):
|
|
op.drop_table("github_webhook_deliveries")
|
|
if _table_exists(bind, "github_app_repositories"):
|
|
op.drop_table("github_app_repositories")
|
|
if _table_exists(bind, "github_app_installations"):
|
|
op.drop_table("github_app_installations")
|
|
|
|
if _table_exists(bind, "progress_events") and _column_exists(bind, "progress_events", "event_source_id"):
|
|
op.drop_index("ix_progress_events_event_source_id", table_name="progress_events")
|
|
op.drop_column("progress_events", "event_source_id")
|
|
if _table_exists(bind, "progress_events") and _column_exists(bind, "progress_events", "delivery_id"):
|
|
op.drop_index("ix_progress_events_delivery_id", table_name="progress_events")
|
|
op.drop_column("progress_events", "delivery_id")
|
|
|
|
if _table_exists(bind, "repo_bindings") and _column_exists(bind, "repo_bindings", "installation_account_login"):
|
|
op.drop_column("repo_bindings", "installation_account_login")
|
|
|
|
if _table_exists(bind, "revenue_events") and _column_exists(bind, "revenue_events", "category"):
|
|
op.drop_index("ix_revenue_events_category", table_name="revenue_events")
|
|
op.drop_column("revenue_events", "category")
|