fix(db): linearize Alembic migration chain to resolve branch conflicts

This commit is contained in:
null 2026-05-20 22:37:36 -05:00
parent f8f885a499
commit 7cc9e86de1
9 changed files with 102 additions and 18 deletions

View File

@ -510,14 +510,32 @@ async def get_runtime_usage(
"""
now = utcnow()
cost_raw, status_raw = await asyncio.gather(
cost_raw, status_raw, sessions_raw = await asyncio.gather(
_safe_call("usage.cost", config),
_safe_call("usage.status", config),
_safe_call("sessions.list", config),
)
# Extract sessions from sessions.list response (primary source)
# Fallback to usage.cost if sessions.list fails
if isinstance(sessions_raw, dict):
raw_sessions = sessions_raw.get("sessions") or []
elif isinstance(sessions_raw, list):
raw_sessions = sessions_raw
else:
raw_sessions = []
# Filter to dicts and merge with usage.cost data if available
sessions: list[dict[str, Any]] = []
if raw_sessions:
sessions = [s for s in raw_sessions if isinstance(s, dict)]
else:
# Fallback: parse from usage.cost response
sessions = _parse_sessions(cost_raw)
# Merge both payloads — some gateways return everything in one response
merged_status = {**cost_raw, **status_raw}
sessions = _parse_sessions(cost_raw)
per_model = aggregate_per_model(sessions, account_key=account_key)
window = _build_window(merged_status, now)
current = _build_current(per_model, merged_status)

View File

@ -0,0 +1,70 @@
"""Add board_webhooks table.
Revision ID: a1b2c3d4e5f5
Revises: 658dca8f4a11
Create Date: 2026-03-03 00:00:00.000000
"""
from __future__ import annotations
import sqlalchemy as sa
import sqlmodel
from alembic import op
# revision identifiers, used by Alembic.
revision = "a1b2c3d4e5f5"
down_revision = "4c1f5e2a7b9d"
branch_labels = None
depends_on = None
def upgrade() -> None:
"""Create board_webhooks table."""
op.create_table(
"board_webhooks",
sa.Column("id", sa.Uuid(), nullable=False),
sa.Column("board_id", sa.Uuid(), nullable=False),
sa.Column("agent_id", sa.Uuid(), nullable=True),
sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column("enabled", sa.Boolean(), nullable=False),
sa.Column("secret", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("signature_header", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=False),
sa.Column("updated_at", sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(
["board_id"],
["boards.id"],
),
sa.ForeignKeyConstraint(
["agent_id"],
["agents.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(
op.f("ix_board_webhooks_board_id"),
"board_webhooks",
["board_id"],
unique=False,
)
op.create_index(
op.f("ix_board_webhooks_agent_id"),
"board_webhooks",
["agent_id"],
unique=False,
)
op.create_index(
op.f("ix_board_webhooks_enabled"),
"board_webhooks",
["enabled"],
unique=False,
)
def downgrade() -> None:
"""Drop board_webhooks table."""
op.drop_index(op.f("ix_board_webhooks_enabled"), table_name="board_webhooks")
op.drop_index(op.f("ix_board_webhooks_agent_id"), table_name="board_webhooks")
op.drop_index(op.f("ix_board_webhooks_board_id"), table_name="board_webhooks")
op.drop_table("board_webhooks")

View File

@ -13,7 +13,7 @@ from alembic import op
# revision identifiers, used by Alembic.
revision = "a1b2c3d4e5f6"
down_revision = "f1b2c3d4e5a6"
down_revision = "a1b2c3d4e5f5"
branch_labels = None
depends_on = None

View File

@ -13,7 +13,7 @@ from alembic import op
# revision identifiers, used by Alembic.
revision = "a2f6c9d4b7e8"
down_revision = "4c1f5e2a7b9d"
down_revision = "d1e2f3a4b5c6"
branch_labels = None
depends_on = None

View File

@ -13,7 +13,7 @@ from alembic import op
# revision identifiers, used by Alembic.
revision = "b7a1d9c3e4f5"
down_revision = "a2f6c9d4b7e8"
down_revision = "a9b1c2d3e4f7"
branch_labels = None
depends_on = None

View File

@ -13,7 +13,7 @@ from alembic import op
# revision identifiers, used by Alembic.
revision = "c5d1a2b3e4f6"
down_revision = "b7a1d9c3e4f5"
down_revision = "c1d2e3f4a5b6"
branch_labels = None
depends_on = None

View File

@ -12,7 +12,7 @@ import sqlalchemy as sa
from alembic import op
revision = "d1e2f3a4b5c6"
down_revision = "c1d2e3f4a5b6"
down_revision = "f1b2c3d4e5a6"
branch_labels = None
depends_on = None

View File

@ -13,7 +13,7 @@ from alembic import op
# revision identifiers, used by Alembic.
revision = "f5a2b3c4d5e6"
down_revision = "a9b1c2d3e4f7"
down_revision = "b7a1d9c3e4f5"
branch_labels = None
depends_on = None

View File

@ -1,19 +1,15 @@
#!/usr/bin/env bash
# docker-test.sh — Rebuild and redeploy Pipeline locally from scratch.
# Clears all Docker cache before building to ensure a clean slate.
# Cleans only Pipeline Docker resources before building.
# IMPORTANT: Do not add global Docker cleanup here (for example `docker system prune`).
# This script must only stop/remove resources for the Pipeline compose project.
set -euo pipefail
cd "$(git rev-parse --show-toplevel)"
echo "=== Stopping and removing existing containers, images, volumes ==="
echo "=== Stopping and removing Pipeline containers, images, volumes ==="
docker compose down --rmi all --volumes --remove-orphans 2>/dev/null || true
echo "=== Pruning all dangling Docker resources ==="
docker system prune -a --volumes -f
echo "=== Removing Pipeline build cache ==="
docker builder prune -f 2>/dev/null || true
echo "=== Building and starting all containers ==="
docker compose up --build -d
@ -25,5 +21,5 @@ docker compose ps
echo ""
echo "=== Deploy complete ==="
echo "Frontend: http://localhost:3030"
echo "Backend: http://localhost:8001"
echo 'Frontend: http://localhost:3030'
echo 'Backend: http://localhost:8001'