Files
awoooi/apps/api/tests/integration/setup_test_schema.sql
Your Name ed205489c1
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m20s
feat(p3.2-tests+ci-schema): model_version 測試 + CI test_schema 對齊 + Grafana SLO Dashboard
P3.2 配套測試 + CI 環境同步 + ADR-100 Grafana 視覺化:

CI test_schema 補齊(解 1162-1172 阻塞之延伸):
- setup_test_schema.sql 加 ai_provider_version_history 表
- 對齊 production p3_2_provider_version_history.sql(已 K8s exec 上線)

新增測試 (636 行):
- test_model_version_probe.py (387) — Provider 探測單元測試
- test_model_version_tracker.py (249) — Tracker 整合測試
  · 4 個 DB-dependent tests 標 @pytest.mark.integration
  · 15 unit + 4 integration(unit step 跳過 integration class)

新增配套:
- ai-slo-dashboard.json (496 行) — Grafana 儀表板
  · 對應 ADR-100 SLO 規則的 4 大面板:
    自主修復成功率 / 飛輪閉環延遲 / 治理事件 / Provider 健康度

修改:
- governance_agent.py +122 行 — SLO 指標暴露 + retrieve metric 整合

Tests: 15 passed (probe + tracker unit), 4 deselected (integration class)

Production 部署狀態:
- p2_decision_fusion_columns.sql  K8s exec 完成(commit c58bdd0c)
- p3_2_provider_version_history.sql  K8s exec 完成(this commit)
- 兩個 production migration 都已上線,CI test_schema 同步補齊

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:57:16 +08:00

154 lines
5.9 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Integration Test Schema Setup
-- ================================
-- 為 CI 環境的臨時 PostgreSQL 建立測試所需的 schema
-- 使用: psql $TEST_DATABASE_URL -f setup_test_schema.sql
-- 2026-04-10 Claude Sonnet 4.6 Asia/Taipei
CREATE EXTENSION IF NOT EXISTS vector;
DO $$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'incidentstatus') THEN
CREATE TYPE incidentstatus AS ENUM ('INVESTIGATING','MITIGATING','RESOLVED','CLOSED','ESCALATED');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'severity') THEN
CREATE TYPE severity AS ENUM ('P0','P1','P2','P3');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'approvalstatus') THEN
CREATE TYPE approvalstatus AS ENUM ('PENDING','APPROVED','REJECTED','EXPIRED','EXECUTION_SUCCESS','EXECUTION_FAILED');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'risklevel') THEN
CREATE TYPE risklevel AS ENUM ('LOW','MEDIUM','HIGH','CRITICAL');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'entrysource') THEN
CREATE TYPE entrysource AS ENUM ('AI_EXTRACTED','HUMAN');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'entrystatus') THEN
CREATE TYPE entrystatus AS ENUM ('DRAFT','REVIEW','APPROVED','ARCHIVED','published');
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'entrytype') THEN
CREATE TYPE entrytype AS ENUM ('INCIDENT_CASE','RUNBOOK','BEST_PRACTICE','POSTMORTEM','auto_runbook','anti_pattern');
END IF;
END $$;
CREATE TABLE IF NOT EXISTS incidents (
incident_id VARCHAR(30) PRIMARY KEY,
status incidentstatus NOT NULL DEFAULT 'INVESTIGATING',
severity severity NOT NULL DEFAULT 'P2',
signals JSON DEFAULT '[]',
affected_services JSON DEFAULT '[]',
decision_chain JSON DEFAULT '[]',
proposal_ids JSON DEFAULT '[]',
outcome JSON DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
resolved_at TIMESTAMPTZ,
closed_at TIMESTAMPTZ,
ttl_days INTEGER DEFAULT 30,
vectorized BOOLEAN DEFAULT false
);
CREATE TABLE IF NOT EXISTS approval_records (
id VARCHAR(36) PRIMARY KEY,
action VARCHAR(500) NOT NULL,
description TEXT NOT NULL,
status approvalstatus NOT NULL DEFAULT 'PENDING',
risk_level risklevel NOT NULL,
required_signatures INTEGER DEFAULT 1,
current_signatures INTEGER DEFAULT 0,
signatures JSON DEFAULT '[]',
blast_radius JSON DEFAULT '{}',
dry_run_checks JSON DEFAULT '[]',
requested_by VARCHAR,
rejection_reason TEXT,
extra_metadata JSON DEFAULT '{}',
fingerprint VARCHAR,
hit_count INTEGER DEFAULT 1,
last_seen_at TIMESTAMPTZ,
approval_level VARCHAR DEFAULT 'standard',
approval_votes JSONB,
required_votes INTEGER DEFAULT 1,
incident_id VARCHAR,
telegram_message_id INTEGER,
telegram_chat_id BIGINT, -- ADR-093 2026-04-25: 支援群組負數 ID
matched_playbook_id VARCHAR(36),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ,
resolved_at TIMESTAMPTZ
);
-- 2026-04-27 P2.1 DecisionFusion 欄位(對齊 p2_decision_fusion_columns.sql 已上 production
-- IF NOT EXISTS 形式 idempotent重跑安全
ALTER TABLE approval_records
ADD COLUMN IF NOT EXISTS composite_score REAL,
ADD COLUMN IF NOT EXISTS complexity_tier VARCHAR(16),
ADD COLUMN IF NOT EXISTS decision_fusion_details JSONB;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chk_complexity_tier') THEN
ALTER TABLE approval_records
ADD CONSTRAINT chk_complexity_tier CHECK (
complexity_tier IS NULL
OR complexity_tier IN ('low','medium','high','critical')
);
END IF;
END $$;
-- 2026-04-27 P3.2.2 — AI Provider 版本歷史表(對齊 p3_2_provider_version_history.sql
CREATE TABLE IF NOT EXISTS ai_provider_version_history (
id SERIAL PRIMARY KEY,
provider VARCHAR(40) NOT NULL,
model VARCHAR(100) NOT NULL,
version VARCHAR(200),
digest VARCHAR(80),
captured_at TIMESTAMPTZ NOT NULL DEFAULT now(),
prev_version VARCHAR(200),
changed BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE TABLE IF NOT EXISTS knowledge_entries (
id VARCHAR(36) PRIMARY KEY,
title VARCHAR NOT NULL,
content TEXT,
entry_type entrytype NOT NULL,
category VARCHAR,
tags JSON DEFAULT '[]',
source entrysource NOT NULL DEFAULT 'HUMAN',
status entrystatus NOT NULL DEFAULT 'DRAFT',
related_incident_id VARCHAR,
related_playbook_id VARCHAR,
symptoms_hash VARCHAR,
view_count INTEGER DEFAULT 0,
created_by VARCHAR,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS rag_chunks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
source TEXT NOT NULL,
source_id TEXT NOT NULL,
title TEXT,
chunk_text TEXT NOT NULL,
embedding vector(768),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- adr091: aider_events schema (2026-04-22 @ Asia/Taipei, 補入 integration test schema)
CREATE TABLE IF NOT EXISTS aider_events (
id BIGSERIAL PRIMARY KEY,
session_id TEXT NOT NULL,
ts TIMESTAMPTZ NOT NULL,
type TEXT NOT NULL,
host TEXT DEFAULT 'ogt-mac',
payload JSONB NOT NULL,
incident_id TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS aider_events_session_idx ON aider_events(session_id);
CREATE INDEX IF NOT EXISTS aider_events_type_ts_idx ON aider_events(type, ts DESC);
CREATE INDEX IF NOT EXISTS aider_events_ts_idx ON aider_events(ts DESC);
CREATE INDEX IF NOT EXISTS aider_events_payload_gin ON aider_events USING GIN (payload);