mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[ENV-LADDER] Add per-project ordered environment ladder column + shim
Replace the single default_branch with an ordered environments ladder
(list[{name,branch}]; first=head=PR target, last=prod=release target,
middle=intermediates). Migration 073 adds nullable JSONB projects.environments;
a read-time shim (roboco/models/env_branches.py) synthesizes a degenerate
single-branch ladder from default_branch when environments is null, so
behavior is unchanged until the operator declares a real split in the panel.
Wired through Project/ProjectCreate/ProjectUpdate models (normalize_environments
validator: rejects empty name/branch + dup branches), ProjectTable column,
API request/response schemas, create+update routes + service. EnvSyncEngine
+ consumer rewires follow.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
"""Per-project ordered environment ladder column.
|
||||
|
||||
Replaces the single ``default_branch`` as the source of truth for a project's
|
||||
PR target (head rung) and release target (prod rung). The ladder is an ordered
|
||||
``list[{name, branch}]``: index 0 = head (where dev/cell/leaf PRs land), index
|
||||
-1 = prod (where the gated release executor commits + tags), middle rungs =
|
||||
intermediates (qa/stag). The ``EnvSyncEngine`` cascades prod→…→head so dev
|
||||
never falls behind prod, and the CEO-gated release promotes the full chain
|
||||
head→…→prod before bumping.
|
||||
|
||||
Additive and nullable: an unset (null) ``environments`` falls back to a
|
||||
degenerate single-branch ladder synthesized from ``default_branch`` at read
|
||||
time (``roboco/services/env_branches.py``), so every existing project keeps
|
||||
behaving byte-for-byte as before until the operator declares a real ladder
|
||||
in the panel. ``default_branch`` is retained as the legacy/shim source.
|
||||
|
||||
Revision ID: 073_project_environments
|
||||
Revises: 072_project_sandbox_extensions
|
||||
Create Date: 2026-07-15
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
revision = "073_project_environments"
|
||||
down_revision = "072_project_sandbox_extensions"
|
||||
branch_labels: dict[str, str] | None = None
|
||||
depends_on: dict[str, str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"projects",
|
||||
sa.Column("environments", postgresql.JSONB(), nullable=True),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("projects", "environments")
|
||||
Reference in New Issue
Block a user