style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 47s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m29s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 3m20s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m7s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 5m24s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 9m38s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 11m37s
CI/CD Pipeline / CI Gate (pull_request) Failing after 3s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m47s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 21h33m14s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 21h44m45s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 21h44m52s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 21h44m54s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 21h44m9s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 21h44m9s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 21h44m9s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 21h44m10s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 21h44m12s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 21h44m13s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 21h44m15s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 21h44m4s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 21h44m4s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 21h32m33s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 21h32m35s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 21h32m35s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 21h44m11s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 21h44m12s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 22h8m14s

This commit is contained in:
CI Bot
2026-09-15 09:38:45 +00:00
parent 7cea7a938c
commit a62dc33599
2 changed files with 46 additions and 13 deletions
@@ -6,6 +6,7 @@ Create Date: 2026-09-15
"""
import sqlalchemy as sa
from alembic import op
revision = "077_merge_title_library_into_scripts"
@@ -29,9 +30,7 @@ def upgrade() -> None:
# 从 title_libraries 迁移活跃数据到 scripts(若 title_libraries 表存在)
conn = op.get_bind()
exists = conn.execute(
sa.text("SELECT to_regclass('public.title_libraries') IS NOT NULL")
).scalar()
exists = conn.execute(sa.text("SELECT to_regclass('public.title_libraries') IS NOT NULL")).scalar()
if exists:
conn.execute(sa.text("""
INSERT INTO scripts (id, user_id, title, content, segments, tags, title_text, title_category, title_config, created_at, updated_at)
+44 -10
View File
@@ -16,12 +16,11 @@ from unittest.mock import MagicMock, patch
import pytest
from fastapi.testclient import TestClient
from main import app
# ── helpers ──────────────────────────────────────────────────────────────
def _make_script(**overrides):
"""构造一个模拟 ScriptModel 对象."""
defaults = dict(
@@ -33,7 +32,13 @@ def _make_script(**overrides):
tags=["测试"],
title_text="开场大标题",
title_category="片头",
title_config={"text": "开场大标题", "font": "思源黑体", "font_size": 48, "font_color": "#FFFFFF", "position": "top"},
title_config={
"text": "开场大标题",
"font": "思源黑体",
"font_size": 48,
"font_color": "#FFFFFF",
"position": "top",
},
created_at=datetime(2026, 9, 1, tzinfo=timezone.utc),
updated_at=datetime(2026, 9, 1, tzinfo=timezone.utc),
)
@@ -43,11 +48,13 @@ def _make_script(**overrides):
# ── TestScriptModelNewFields ─────────────────────────────────────────────
class TestScriptModelNewFields:
"""验证 ScriptModel 新增字段的定义."""
def test_model_has_title_text_column(self):
from packages.adapters.sqlalchemy_impl.models import ScriptModel
assert hasattr(ScriptModel, "title_text")
col = ScriptModel.__table__.columns["title_text"]
assert col is not None
@@ -55,6 +62,7 @@ class TestScriptModelNewFields:
def test_model_has_title_category_column(self):
from packages.adapters.sqlalchemy_impl.models import ScriptModel
assert hasattr(ScriptModel, "title_category")
col = ScriptModel.__table__.columns["title_category"]
assert col is not None
@@ -62,6 +70,7 @@ class TestScriptModelNewFields:
def test_model_has_title_config_column(self):
from packages.adapters.sqlalchemy_impl.models import ScriptModel
assert hasattr(ScriptModel, "title_config")
col = ScriptModel.__table__.columns["title_config"]
assert col is not None
@@ -69,6 +78,7 @@ class TestScriptModelNewFields:
def test_model_defaults(self):
"""新字段默认值为空字符串/空 dict."""
from packages.adapters.sqlalchemy_impl.models import ScriptModel
s = ScriptModel(id="x", user_id="u", title="t")
# 检查 default 值
assert ScriptModel.__table__.columns["title_text"].default.arg == ""
@@ -77,6 +87,7 @@ class TestScriptModelNewFields:
# ── TestScriptServiceTitleConfig ─────────────────────────────────────────
class TestScriptServiceTitleConfig:
"""验证 ScriptService 新方法 get_title_config_for_script."""
@@ -137,6 +148,7 @@ class TestScriptServiceTitleConfig:
# ── TestScriptServiceCreateWithNewFields ─────────────────────────────────
class TestScriptServiceCreateWithNewFields:
"""验证 create_script 和 update_script 支持新字段."""
@@ -184,6 +196,7 @@ class TestScriptServiceCreateWithNewFields:
# ── TestScriptsRoutesNewFields ───────────────────────────────────────────
class TestScriptsRoutesNewFields:
"""验证 scripts API 路由正确处理新字段."""
@@ -196,12 +209,15 @@ class TestScriptsRoutesNewFields:
mock_svc = MagicMock()
mock_svc.create_script.return_value = mock_script
from app.auth import get_current_user
from app.api.routes.scripts import _get_service
from app.auth import get_current_user
async def _fake_user():
return MagicMock(user=MagicMock(id="user-001"))
def _fake_svc():
return mock_svc
app.dependency_overrides[get_current_user] = _fake_user
app.dependency_overrides[_get_service] = _fake_svc
try:
@@ -235,12 +251,15 @@ class TestScriptsRoutesNewFields:
mock_svc = MagicMock()
mock_svc.get_script.return_value = mock_script
from app.auth import get_current_user
from app.api.routes.scripts import _get_service
from app.auth import get_current_user
async def _fake_user():
return MagicMock(user=MagicMock(id="user-001"))
def _fake_svc():
return mock_svc
app.dependency_overrides[get_current_user] = _fake_user
app.dependency_overrides[_get_service] = _fake_svc
try:
@@ -258,6 +277,7 @@ class TestScriptsRoutesNewFields:
# ── TestTitleLibraryDeprecated ───────────────────────────────────────────
class TestTitleLibraryDeprecated:
"""验证 title_libraries API 返回 deprecated Warning header."""
@@ -265,12 +285,15 @@ class TestTitleLibraryDeprecated:
mock_repo = MagicMock()
mock_repo.count_by_user.return_value = 0
from app.auth import get_current_user
from app.api.routes.titles import _get_title_repository
from app.auth import get_current_user
async def _fake_user():
return MagicMock(user=MagicMock(id="user-001"))
def _fake_repo():
return mock_repo
app.dependency_overrides[get_current_user] = _fake_user
app.dependency_overrides[_get_title_repository] = _fake_repo
try:
@@ -284,20 +307,31 @@ class TestTitleLibraryDeprecated:
def test_get_title_has_warning_header(self):
from packages.domain.title_library import TitleLibraryItem
mock_item = TitleLibraryItem(
id="t1", user_id="user-001", name="测试", text="标题文字",
category="通用", description="", tags=[], usage_count=0,
is_active=True, created_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
id="t1",
user_id="user-001",
name="测试",
text="标题文字",
category="通用",
description="",
tags=[],
usage_count=0,
is_active=True,
created_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
updated_at=datetime(2026, 1, 1, tzinfo=timezone.utc),
)
mock_repo = MagicMock()
from app.auth import get_current_user
from app.api.routes.titles import _get_title_repository
from app.auth import get_current_user
async def _fake_user():
return MagicMock(user=MagicMock(id="user-001"))
def _fake_repo():
return mock_repo
app.dependency_overrides[get_current_user] = _fake_user
app.dependency_overrides[_get_title_repository] = _fake_repo
try: