feat: make output types workflow-first contracts

This commit is contained in:
2026-04-08 21:43:55 +02:00
parent bd18cccb5e
commit 8c9648d5dc
8 changed files with 1049 additions and 110 deletions
@@ -0,0 +1,57 @@
"""Add workflow contract fields to output_types.
Revision ID: 065
Revises: 064
"""
from alembic import op
import sqlalchemy as sa
revision = "065"
down_revision = "064"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column(
"output_types",
sa.Column("workflow_family", sa.String(length=20), nullable=False, server_default="order_line"),
)
op.add_column(
"output_types",
sa.Column("artifact_kind", sa.String(length=50), nullable=False, server_default="still_image"),
)
op.execute(
"""
UPDATE output_types
SET workflow_family = CASE
WHEN lower(coalesce(output_format, '')) IN ('gltf', 'glb', 'stl', 'obj', 'usd', 'usdz')
THEN 'cad_file'
ELSE 'order_line'
END
"""
)
op.execute(
"""
UPDATE output_types
SET artifact_kind = CASE
WHEN is_animation IS TRUE OR lower(coalesce(output_format, '')) IN ('mp4', 'webm', 'mov')
THEN 'turntable_video'
WHEN lower(coalesce(output_format, '')) IN ('gltf', 'glb', 'stl', 'obj', 'usd', 'usdz')
THEN 'model_export'
WHEN workflow_family = 'cad_file' AND lower(coalesce(output_format, '')) IN ('png', 'jpg', 'jpeg', 'webp')
THEN 'thumbnail_image'
ELSE 'still_image'
END
"""
)
op.alter_column("output_types", "workflow_family", server_default=None)
op.alter_column("output_types", "artifact_kind", server_default=None)
def downgrade() -> None:
op.drop_column("output_types", "artifact_kind")
op.drop_column("output_types", "workflow_family")
@@ -0,0 +1,72 @@
"""Add invocation overrides to output_types.
Revision ID: 066
Revises: 065
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
revision = "066"
down_revision = "065"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column(
"output_types",
sa.Column(
"invocation_overrides",
postgresql.JSONB(astext_type=sa.Text()),
nullable=False,
server_default=sa.text("'{}'::jsonb"),
),
)
op.execute(
"""
UPDATE output_types
SET invocation_overrides = COALESCE(jsonb_strip_nulls(jsonb_build_object(
'width', CASE
WHEN coalesce(render_settings->>'width', '') ~ '^[0-9]+$'
THEN (render_settings->>'width')::int
ELSE NULL
END,
'height', CASE
WHEN coalesce(render_settings->>'height', '') ~ '^[0-9]+$'
THEN (render_settings->>'height')::int
ELSE NULL
END,
'engine', NULLIF(render_settings->>'engine', ''),
'samples', CASE
WHEN coalesce(render_settings->>'samples', '') ~ '^[0-9]+$'
THEN (render_settings->>'samples')::int
ELSE NULL
END,
'frame_count', CASE
WHEN coalesce(render_settings->>'frame_count', '') ~ '^[0-9]+$'
THEN (render_settings->>'frame_count')::int
ELSE NULL
END,
'fps', CASE
WHEN coalesce(render_settings->>'fps', '') ~ '^[0-9]+$'
THEN (render_settings->>'fps')::int
ELSE NULL
END,
'turntable_axis', NULLIF(render_settings->>'turntable_axis', ''),
'bg_color', NULLIF(render_settings->>'bg_color', ''),
'noise_threshold', NULLIF(render_settings->>'noise_threshold', ''),
'denoiser', NULLIF(render_settings->>'denoiser', ''),
'denoising_input_passes', NULLIF(render_settings->>'denoising_input_passes', ''),
'denoising_prefilter', NULLIF(render_settings->>'denoising_prefilter', ''),
'denoising_quality', NULLIF(render_settings->>'denoising_quality', ''),
'denoising_use_gpu', NULLIF(render_settings->>'denoising_use_gpu', '')
)), '{}'::jsonb)
"""
)
op.alter_column("output_types", "invocation_overrides", server_default=None)
def downgrade() -> None:
op.drop_column("output_types", "invocation_overrides")