Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m20s
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>
154 lines
5.9 KiB
SQL
154 lines
5.9 KiB
SQL
-- 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);
|