All checks were successful
CD / build (pull_request) Successful in 5m2s
Adequa o repo ao guia de promoção lab -> homolog mantendo Python (Gate 0 via stackException). Cumpre os gates aplicáveis: - promotion-manifest.yaml: stackException (Python/Vanna), Gate B N/A, Gate D/G declarados, capacidade e deltas. - k8s/hml/: overlay homolog — secret DB dedicado (vanna-clubpetro-db, Gate G), probes httpGet /health (Gate E), resources.requests, replicas:1, non-root securityContext; host homologation.clubpetro.com (sem host de lab). - server.py: rota GET /health (alvo das probes). - Dockerfile: usuário non-root uid/gid 10001 + HOME/cache graváveis (Gate E). - .env.example: remove literal lab.clubpetro.com do CORS (Gate D). - k8s/ flat movido para k8s/lab/ (simetria lab/hml); cd.yml aplica k8s/lab/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
116 lines
5.1 KiB
YAML
116 lines
5.1 KiB
YAML
# promotion-manifest.yaml
|
|
# Manifesto de promoção lab -> homolog (ClubPetro).
|
|
# A PR de promoção deve ser marcada com [lab] e conter este arquivo.
|
|
# O pipeline lê os campos abaixo pra rodar os gates 0 + A-F + G + admissao.
|
|
#
|
|
# OBS: o schema exato é definido pelo parser do pipeline (referências vivas:
|
|
# backend=external_apis, seed=action-plan). As chaves aqui são auto-descritivas;
|
|
# reconcilie com o parser se ele exigir nomes específicos.
|
|
|
|
apiVersion: v1
|
|
kind: PromotionManifest
|
|
|
|
service:
|
|
name: vanna-clubpetro
|
|
kind: backend # serviço HTTP (não é MFE)
|
|
description: >
|
|
Deploy do Vanna 2.0 (text-to-SQL sobre LLM) que responde perguntas em
|
|
pt-BR consultando o ClickHouse Cloud (database gold) com RLS por tenant
|
|
(program_id + store_id).
|
|
owner: dados-plataforma # TODO: confirmar squad/owner
|
|
runtimePort: 8765
|
|
|
|
promotion:
|
|
from: lab
|
|
to: homolog
|
|
# Onde o pipeline re-materializa o código (branch limpa, sem histórico do lab).
|
|
kubernetesOverlay: k8s/hml
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Gate 0 — Stack
|
|
# ---------------------------------------------------------------------------
|
|
stack:
|
|
language: python
|
|
runtime: python-3.11
|
|
framework: vanna-2.0 + fastapi + uvicorn
|
|
packageManager: pip
|
|
# Stack padrão do core é NestJS>=10/TypeORM0.3 (yarn) OU MFE React17/MUI5.
|
|
# Python é NO-GO por padrão -> exceção formal abaixo (Gate 0).
|
|
stackException:
|
|
requested: true
|
|
reason: >
|
|
O serviço é um deploy da biblioteca Vanna 2.0, que é Python e não tem
|
|
equivalente em NestJS. O núcleo (agente LLM, memória vetorial ChromaDB,
|
|
runner RLS do ClickHouse e o web component <vanna-chat>) vem do upstream
|
|
vanna-ai/vanna. Reescrever em Node significaria reimplementar toda essa
|
|
cadeia — inviável e sem ganho. Mantém-se Python; todos os demais gates
|
|
aplicáveis são cumpridos (ver abaixo).
|
|
approvedBy: "" # TODO: preencher com o aprovador humano do stackException
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Gate B — Migrations
|
|
# ---------------------------------------------------------------------------
|
|
migrations:
|
|
applicable: false
|
|
reason: >
|
|
O serviço não possui schema relacional próprio. O ClickHouse Cloud
|
|
(database gold) é gerido fora do serviço; o "treino" (train.py) apenas
|
|
popula um vector store ChromaDB local, idempotente e reconstruível
|
|
(rm -rf chroma_db/ && python train.py). Não há migrations TypeORM.
|
|
Toda query ao ClickHouse é parametrizada via settings do clickhouse_connect
|
|
(RLS), nunca por interpolação de string — ver rls_runner.py.
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Gate D — Atalhos / segurança
|
|
# ---------------------------------------------------------------------------
|
|
security:
|
|
envVersioned: false # apenas .env.example versionado; .env no .gitignore
|
|
hardcodedSecrets: false # segredos vêm de k8s Secret (envFrom), nunca do git
|
|
hardcodedLabHost: false # overlay homolog usa homologation.clubpetro.com
|
|
npmrcVersioned: false # sem .npmrc no repo
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Gate G — Isolamento de credenciais de banco
|
|
# ---------------------------------------------------------------------------
|
|
database:
|
|
# Credenciais do ClickHouse em secret DEDICADO ao serviço (não genérico).
|
|
credentialsSecret: vanna-clubpetro-db
|
|
genericSecret: false # NÃO usa sqlhomologation / sqluserhomolgeneric etc.
|
|
engine: clickhouse-cloud
|
|
database: gold
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Admissão de capacidade
|
|
# ---------------------------------------------------------------------------
|
|
capacity:
|
|
replicas: 1 # ChromaDB é SQLite-based; réplicas > 1 corrompem o store
|
|
strategy: Recreate # PVC ReadWriteOnce — não dá 2 pods montando ao mesmo tempo
|
|
resources:
|
|
requests:
|
|
cpu: "200m"
|
|
memory: "1Gi"
|
|
limits:
|
|
cpu: "1"
|
|
memory: "2Gi"
|
|
persistentVolume:
|
|
size: 5Gi
|
|
accessMode: ReadWriteOnce # store vetorial + cache ONNX + CSVs
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Deltas (avisos — não bloqueiam)
|
|
# ---------------------------------------------------------------------------
|
|
deltas:
|
|
A_architecture: >
|
|
Tenant (program_id/store_id) resolvido via RequestContext e validado por
|
|
regex ^[A-Za-z0-9_-]+$ (agent.py). O embed confiável passa os IDs por query
|
|
param do <vanna-chat> — não há token JWT nesta arquitetura de embed.
|
|
C_contract: >
|
|
OpenAPI auto-servido pelo FastAPI (/openapi.json, /docs). Rotas de chat já
|
|
versionadas: /api/vanna/v2/chat_sse|chat_websocket|chat_poll (upstream).
|
|
E_ops: >
|
|
Probes de liveness/readiness em GET /health; replicas: 1; Dockerfile
|
|
multi-stage rodando como usuário non-root (uid 10001).
|
|
F_ci: >
|
|
CI/CD via .gitea/workflows/cd.yml (build remoto no Cloud Build + rollout
|
|
no GKE). bitbucket-pipelines.yml N/A: o repo vive no Gitea self-hosted.
|