97 lines
3.9 KiB
Python
97 lines
3.9 KiB
Python
"""Separate project identity from source checkout configuration."""
|
|
|
|
from collections.abc import Sequence
|
|
from urllib.parse import urlsplit
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = "20260804_0007"
|
|
down_revision: str | Sequence[str] | None = "20260804_0006"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def _legacy_clone_url(value: str) -> str:
|
|
parsed = urlsplit(value)
|
|
if parsed.scheme == "git" and parsed.hostname and parsed.path:
|
|
port = f":{parsed.port}" if parsed.port else ""
|
|
return f"https://{parsed.hostname}{port}{parsed.path}.git"
|
|
return value
|
|
|
|
|
|
def upgrade() -> None:
|
|
with op.batch_alter_table("projects") as batch:
|
|
batch.add_column(sa.Column("git_remote_normalized", sa.Text()))
|
|
batch.add_column(
|
|
sa.Column("curation_enabled", sa.Boolean(), nullable=False, server_default=sa.true())
|
|
)
|
|
batch.add_column(
|
|
sa.Column("source_strategy", sa.String(20), nullable=False, server_default="auto")
|
|
)
|
|
batch.add_column(sa.Column("source_branch", sa.String(200)))
|
|
batch.add_column(sa.Column("source_credential_item_id", sa.String(100)))
|
|
batch.add_column(sa.Column("source_last_commit", sa.String(64)))
|
|
batch.add_column(sa.Column("source_last_branch", sa.String(200)))
|
|
batch.add_column(sa.Column("source_last_fetched_at", sa.DateTime(timezone=True)))
|
|
batch.add_column(sa.Column("source_last_error", sa.Text()))
|
|
batch.add_column(
|
|
sa.Column("source_cache_used", sa.Boolean(), nullable=False, server_default=sa.false())
|
|
)
|
|
batch.add_column(sa.Column("last_agent_sync_at", sa.DateTime(timezone=True)))
|
|
batch.add_column(sa.Column("last_agent_branch", sa.String(200)))
|
|
batch.add_column(sa.Column("last_agent_commit", sa.String(64)))
|
|
batch.add_column(sa.Column("last_agent_dirty", sa.Boolean()))
|
|
|
|
connection = op.get_bind()
|
|
projects = connection.execute(sa.text("SELECT id, git_remote FROM projects")).mappings()
|
|
for project in projects:
|
|
remote = project["git_remote"]
|
|
if not remote:
|
|
continue
|
|
connection.execute(
|
|
sa.text(
|
|
"UPDATE projects "
|
|
"SET git_remote = :clone_url, git_remote_normalized = :normalized "
|
|
"WHERE id = :project_id"
|
|
),
|
|
{
|
|
"clone_url": _legacy_clone_url(remote),
|
|
"normalized": remote,
|
|
"project_id": project["id"],
|
|
},
|
|
)
|
|
|
|
with op.batch_alter_table("projects") as batch:
|
|
batch.create_unique_constraint(
|
|
"uq_projects_git_remote_normalized", ["git_remote_normalized"]
|
|
)
|
|
batch.create_index("ix_projects_curation_enabled", ["curation_enabled"])
|
|
|
|
|
|
def downgrade() -> None:
|
|
connection = op.get_bind()
|
|
connection.execute(
|
|
sa.text(
|
|
"UPDATE projects SET git_remote = git_remote_normalized "
|
|
"WHERE git_remote_normalized IS NOT NULL"
|
|
)
|
|
)
|
|
with op.batch_alter_table("projects") as batch:
|
|
batch.drop_index("ix_projects_curation_enabled")
|
|
batch.drop_constraint("uq_projects_git_remote_normalized", type_="unique")
|
|
batch.drop_column("last_agent_dirty")
|
|
batch.drop_column("last_agent_commit")
|
|
batch.drop_column("last_agent_branch")
|
|
batch.drop_column("last_agent_sync_at")
|
|
batch.drop_column("source_cache_used")
|
|
batch.drop_column("source_last_error")
|
|
batch.drop_column("source_last_fetched_at")
|
|
batch.drop_column("source_last_branch")
|
|
batch.drop_column("source_last_commit")
|
|
batch.drop_column("source_credential_item_id")
|
|
batch.drop_column("source_branch")
|
|
batch.drop_column("source_strategy")
|
|
batch.drop_column("curation_enabled")
|
|
batch.drop_column("git_remote_normalized")
|