From c05bac61127fae78eb659dba89a0b76920c1fbaf Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 15 Apr 2026 22:03:59 +0800 Subject: [PATCH] =?UTF-8?q?fix(playbook):=20seed=20tuple=20unpack=20+=20te?= =?UTF-8?q?xt[]=20=E2=86=92=20jsonb=20migration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - playbook_seed_service.py: list_playbooks 回傳 tuple[list, int], 缺少解包導致 'list' has no attribute 'source' - fix_playbooks_array_to_jsonb.sql: source_incident_ids/tags text[] → jsonb (已手動套用 prod DB) 2026-04-15 ogt + Claude Sonnet 4.6(亞太) Co-Authored-By: Claude Sonnet 4.6 --- apps/api/migrations/fix_playbooks_array_to_jsonb.sql | 11 +++++++++++ apps/api/src/services/playbook_seed_service.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 apps/api/migrations/fix_playbooks_array_to_jsonb.sql diff --git a/apps/api/migrations/fix_playbooks_array_to_jsonb.sql b/apps/api/migrations/fix_playbooks_array_to_jsonb.sql new file mode 100644 index 00000000..4cf2193d --- /dev/null +++ b/apps/api/migrations/fix_playbooks_array_to_jsonb.sql @@ -0,0 +1,11 @@ +-- 修正 playbooks 表 text[] 欄位 → jsonb +-- 原因: ORM 送 JSON type,DB 欄位為 text[],導致 DatatypeMismatchError +-- 2026-04-15 ogt + Claude Sonnet 4.6(亞太): 已手動套用到 prod + +ALTER TABLE playbooks ALTER COLUMN source_incident_ids DROP DEFAULT; +ALTER TABLE playbooks ALTER COLUMN source_incident_ids TYPE jsonb USING to_jsonb(source_incident_ids); +ALTER TABLE playbooks ALTER COLUMN source_incident_ids SET DEFAULT '[]'::jsonb; + +ALTER TABLE playbooks ALTER COLUMN tags DROP DEFAULT; +ALTER TABLE playbooks ALTER COLUMN tags TYPE jsonb USING to_jsonb(tags); +ALTER TABLE playbooks ALTER COLUMN tags SET DEFAULT '[]'::jsonb; diff --git a/apps/api/src/services/playbook_seed_service.py b/apps/api/src/services/playbook_seed_service.py index 977def53..437afdab 100644 --- a/apps/api/src/services/playbook_seed_service.py +++ b/apps/api/src/services/playbook_seed_service.py @@ -43,7 +43,7 @@ async def seed_playbooks_from_rules() -> None: repo = get_playbook_repository() # 取得現有 playbook source_ids,避免重複建立 - existing = await repo.list_playbooks(status=PlaybookStatus.APPROVED, limit=500) + existing, _ = await repo.list_playbooks(status=PlaybookStatus.APPROVED, limit=500) existing_sources = {p.source for p in existing if p.source} seeded = 0