袁聪merge:合并分支

This commit is contained in:
2026-09-11 17:26:18 +08:00
95 changed files with 18208 additions and 120 deletions
+33 -9
View File
@@ -16,7 +16,9 @@ from app.service.config_release_service import ConfigReleaseError, ConfigRelease
async def test_config_release_lifecycle_is_versioned_and_audited() -> None:
now = datetime.now(UTC).replace(tzinfo=None)
release_no = f"it-{uuid4().hex}"
peer_release_no = f"it-peer-{uuid4().hex}"
release_id = 0
peer_release_id = 0
rollback_id = 0
# 本测试会激活临时版本,把平台当前生效的版本顶成 superseded。先记下它是谁,
# 清理时恢复——否则平台会静默停在"零个 active 版本"(见 finally 的说明)。
@@ -43,13 +45,31 @@ async def test_config_release_lifecycle_is_versioned_and_audited() -> None:
with pytest.raises(ConfigReleaseError, match="not pending review"):
await service.approve(release_id, 101)
await service.submit_for_review(release_id, 101)
# 单人复核:创建人 101 自己审核通过。库侧的
# chk_config_release_separation 已由迁移 20260910_drop_review_separation 撤下,
# 因此自审与多人复核一样**如实写入** reviewer_id(列含义就是"审核人")。
approved = await service.approve(release_id, 101)
assert approved.reviewer_id == 101
assert approved.reviewed_at is not None
await service.activate(release_id, 101)
# 自审允许:创建人 101 审核自己提交的版本不报错,并如实写入 reviewer_id
# (chk_config_release_separation 已由 20260910 / 20260911 两个
# drop_review_separation 迁移撤下,均幂等)。
self_reviewed = await service.approve(release_id, 101)
assert self_reviewed.reviewer_id == 101
assert self_reviewed.reviewed_at is not None
await service.activate(release_id, 202)
# 他人复核:`reviewer_id` 如实写入审核人,覆盖 approve 的另一条分支。
peer = ConfigRelease(
release_no=peer_release_no,
title="integration-peer",
change_summary="integration-peer",
status="draft",
created_by=101,
created_at=now,
updated_at=now,
)
session.add(peer)
await session.flush()
peer_release_id = peer.id
await service.submit_for_review(peer_release_id, 101)
assert (await service.approve(peer_release_id, 202)).reviewer_id == 202
with pytest.raises(ConfigReleaseError, match="not pending review"):
await service.approve(peer_release_id, 202)
await session.commit()
async with SessionFactory() as session:
@@ -93,12 +113,16 @@ async def test_config_release_lifecycle_is_versioned_and_audited() -> None:
async with SessionFactory() as session:
await session.execute(
delete(InteractionAudit).where(
InteractionAudit.detail["release_id"].in_([release_id, rollback_id])
InteractionAudit.detail["release_id"].in_(
[release_id, peer_release_id, rollback_id]
)
)
)
await session.execute(
delete(DomainEventOutbox).where(
DomainEventOutbox.aggregate_id.in_([str(release_id), str(rollback_id)])
DomainEventOutbox.aggregate_id.in_(
[str(release_id), str(peer_release_id), str(rollback_id)]
)
)
)
await session.execute(