Files
Sankofa/api/src/db/migrations/019_deployments.ts

153 lines
5.0 KiB
TypeScript
Raw Normal View History

import { Migration } from '../migrate.js'
export const up: Migration['up'] = async (db) => {
// Deployments table
await db.query(`
CREATE TABLE IF NOT EXISTS deployments (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(255) NOT NULL,
product_id UUID REFERENCES products(id) ON DELETE SET NULL,
product_version_id UUID REFERENCES product_versions(id) ON DELETE SET NULL,
template_id UUID REFERENCES templates(id) ON DELETE SET NULL,
template_version_id UUID REFERENCES template_versions(id) ON DELETE SET NULL,
tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,
region VARCHAR(100),
status VARCHAR(50) NOT NULL DEFAULT 'PENDING' CHECK (status IN (
'PENDING',
'PROVISIONING',
'DEPLOYING',
'RUNNING',
'UPDATING',
'STOPPED',
'FAILED',
'DELETING',
'DELETED'
)),
deployment_type VARCHAR(50) NOT NULL CHECK (deployment_type IN (
'TERRAFORM',
'HELM',
'ANSIBLE',
'KUBERNETES',
'HYBRID'
)),
parameters JSONB DEFAULT '{}'::jsonb,
rendered_content TEXT,
terraform_state JSONB,
outputs JSONB DEFAULT '{}'::jsonb,
error_message TEXT,
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
started_at TIMESTAMP WITH TIME ZONE,
completed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
)
`)
// Deployment logs table
await db.query(`
CREATE TABLE IF NOT EXISTS deployment_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
deployment_id UUID NOT NULL REFERENCES deployments(id) ON DELETE CASCADE,
level VARCHAR(20) NOT NULL CHECK (level IN ('DEBUG', 'INFO', 'WARN', 'ERROR')),
message TEXT NOT NULL,
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
)
`)
// Deployment resources table (links deployments to resources)
await db.query(`
CREATE TABLE IF NOT EXISTS deployment_resources (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
deployment_id UUID NOT NULL REFERENCES deployments(id) ON DELETE CASCADE,
resource_id UUID REFERENCES resources(id) ON DELETE SET NULL,
resource_type VARCHAR(100) NOT NULL,
resource_name VARCHAR(255) NOT NULL,
provider_resource_id VARCHAR(255),
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
)
`)
// Deployment events table (for event sourcing)
await db.query(`
CREATE TABLE IF NOT EXISTS deployment_events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
deployment_id UUID NOT NULL REFERENCES deployments(id) ON DELETE CASCADE,
event_type VARCHAR(100) NOT NULL,
event_data JSONB DEFAULT '{}'::jsonb,
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
)
`)
// Indexes
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployments_tenant ON deployments(tenant_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployments_status ON deployments(status)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployments_product ON deployments(product_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployments_template ON deployments(template_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployments_region ON deployments(region)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployment_logs_deployment ON deployment_logs(deployment_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployment_logs_created ON deployment_logs(deployment_id, created_at)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployment_resources_deployment ON deployment_resources(deployment_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployment_resources_resource ON deployment_resources(resource_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployment_events_deployment ON deployment_events(deployment_id)
`)
await db.query(`
CREATE INDEX IF NOT EXISTS idx_deployment_events_type ON deployment_events(deployment_id, event_type)
`)
// Update triggers
await db.query(`
CREATE TRIGGER update_deployments_updated_at
BEFORE UPDATE ON deployments
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column()
`)
await db.query(`
CREATE TRIGGER update_deployment_resources_updated_at
BEFORE UPDATE ON deployment_resources
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column()
`)
}
export const down: Migration['down'] = async (db) => {
await db.query(`DROP TABLE IF EXISTS deployment_events`)
await db.query(`DROP TABLE IF EXISTS deployment_resources`)
await db.query(`DROP TABLE IF EXISTS deployment_logs`)
await db.query(`DROP TABLE IF EXISTS deployments`)
}