Add deployment tracking schema (Migration 018)
Creates deployments and deployment_logs tables for tracking all deployment types (Docker, MCP, iOS/macOS, services). Includes deployment status, timing, git integration, and structured logging. Also adds run-migration.mjs helper for running migrations against PostgreSQL database. Part of CF-290, completes CF-291. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
96
migrations/018_deployments.sql
Normal file
96
migrations/018_deployments.sql
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
-- Migration 018: Deployments tracking for deployment centralization
|
||||||
|
-- Purpose: Track all deployments (Docker, MCP, iOS/macOS, services) with logs
|
||||||
|
-- Dependencies: 001_base_schema.sql (tasks table), 010_sessions.sql (sessions table)
|
||||||
|
|
||||||
|
-- Deployments table: Store deployment information linked to sessions and tasks
|
||||||
|
CREATE TABLE IF NOT EXISTS deployments (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
session_id TEXT REFERENCES sessions(id) ON DELETE SET NULL,
|
||||||
|
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
||||||
|
|
||||||
|
-- Project identification
|
||||||
|
project_name VARCHAR(255) NOT NULL,
|
||||||
|
project_path TEXT NOT NULL,
|
||||||
|
|
||||||
|
-- Deployment type and method
|
||||||
|
deployment_type VARCHAR(50) NOT NULL CHECK (deployment_type IN (
|
||||||
|
'docker-compose',
|
||||||
|
'mcp-server',
|
||||||
|
'ios-macos-app',
|
||||||
|
'python-service',
|
||||||
|
'node-service'
|
||||||
|
)),
|
||||||
|
deployment_method VARCHAR(50) NOT NULL CHECK (deployment_method IN (
|
||||||
|
'doco-cd',
|
||||||
|
'agiliton-build',
|
||||||
|
'direct',
|
||||||
|
'manual'
|
||||||
|
)),
|
||||||
|
|
||||||
|
-- Status tracking
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'pending' CHECK (status IN (
|
||||||
|
'pending',
|
||||||
|
'running',
|
||||||
|
'success',
|
||||||
|
'failed',
|
||||||
|
'cancelled'
|
||||||
|
)),
|
||||||
|
|
||||||
|
-- Git integration
|
||||||
|
commit_sha VARCHAR(40),
|
||||||
|
git_branch TEXT,
|
||||||
|
|
||||||
|
-- Timing
|
||||||
|
started_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||||
|
completed_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
duration_seconds INTEGER GENERATED ALWAYS AS
|
||||||
|
(EXTRACT(EPOCH FROM (completed_at - started_at))) STORED,
|
||||||
|
|
||||||
|
-- Error tracking
|
||||||
|
error_message TEXT,
|
||||||
|
|
||||||
|
-- Extra deployment-specific data (JSON)
|
||||||
|
metadata JSONB DEFAULT '{}'::jsonb,
|
||||||
|
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Deployment logs table: Store deployment log messages
|
||||||
|
CREATE TABLE IF NOT EXISTS deployment_logs (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
deployment_id INT NOT NULL REFERENCES deployments(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
||||||
|
level VARCHAR(20) NOT NULL CHECK (level IN ('debug', 'info', 'warn', 'error')),
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
|
||||||
|
-- Optional structured metadata
|
||||||
|
metadata JSONB DEFAULT '{}'::jsonb
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Indexes for efficient querying
|
||||||
|
CREATE INDEX idx_deployments_project ON deployments(project_name);
|
||||||
|
CREATE INDEX idx_deployments_session ON deployments(session_id);
|
||||||
|
CREATE INDEX idx_deployments_task ON deployments(task_id);
|
||||||
|
CREATE INDEX idx_deployments_status ON deployments(status);
|
||||||
|
CREATE INDEX idx_deployments_started ON deployments(started_at DESC);
|
||||||
|
CREATE INDEX idx_deployments_type ON deployments(deployment_type);
|
||||||
|
CREATE INDEX idx_deployments_commit ON deployments(commit_sha);
|
||||||
|
|
||||||
|
CREATE INDEX idx_deployment_logs_deployment ON deployment_logs(deployment_id);
|
||||||
|
CREATE INDEX idx_deployment_logs_timestamp ON deployment_logs(timestamp DESC);
|
||||||
|
CREATE INDEX idx_deployment_logs_level ON deployment_logs(level);
|
||||||
|
|
||||||
|
-- Comments for documentation
|
||||||
|
COMMENT ON TABLE deployments IS 'Deployment tracking for all project types (Docker, MCP, iOS/macOS, services)';
|
||||||
|
COMMENT ON COLUMN deployments.project_name IS 'Human-readable project name';
|
||||||
|
COMMENT ON COLUMN deployments.project_path IS 'Absolute filesystem path to project';
|
||||||
|
COMMENT ON COLUMN deployments.deployment_type IS 'Type of deployment (docker-compose, mcp-server, ios-macos-app, etc.)';
|
||||||
|
COMMENT ON COLUMN deployments.deployment_method IS 'Method used for deployment (doco-cd, agiliton-build, direct, manual)';
|
||||||
|
COMMENT ON COLUMN deployments.status IS 'Current deployment status';
|
||||||
|
COMMENT ON COLUMN deployments.duration_seconds IS 'Auto-calculated deployment duration in seconds';
|
||||||
|
COMMENT ON COLUMN deployments.metadata IS 'Extra deployment-specific data (runtime, host, build number, etc.)';
|
||||||
|
|
||||||
|
COMMENT ON TABLE deployment_logs IS 'Deployment log messages for debugging and audit trail';
|
||||||
|
COMMENT ON COLUMN deployment_logs.level IS 'Log level (debug, info, warn, error)';
|
||||||
|
COMMENT ON COLUMN deployment_logs.metadata IS 'Optional structured log metadata (source, context, etc.)';
|
||||||
62
run-migration.mjs
Normal file
62
run-migration.mjs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Run a migration file against the task-mcp database
|
||||||
|
* Usage: node run-migration.mjs <migration-file>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import pg from 'pg';
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
const { Pool } = pg;
|
||||||
|
|
||||||
|
// Database configuration
|
||||||
|
const pool = new Pool({
|
||||||
|
host: process.env.POSTGRES_HOST || 'infra.agiliton.internal',
|
||||||
|
port: 5432,
|
||||||
|
database: 'agiliton',
|
||||||
|
user: 'agiliton',
|
||||||
|
password: 'QtqiwCOAUpQNF6pjzOMAREzUny2bY8V1',
|
||||||
|
max: 1,
|
||||||
|
connectionTimeoutMillis: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function runMigration(migrationFile) {
|
||||||
|
const client = await pool.connect();
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`Running migration: ${migrationFile}`);
|
||||||
|
|
||||||
|
// Read migration file
|
||||||
|
const migrationPath = join(__dirname, 'migrations', migrationFile);
|
||||||
|
const sql = readFileSync(migrationPath, 'utf-8');
|
||||||
|
|
||||||
|
// Execute migration
|
||||||
|
await client.query(sql);
|
||||||
|
|
||||||
|
console.log(`Migration completed successfully: ${migrationFile}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Migration failed: ${error.message}`);
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get migration file from command line
|
||||||
|
const migrationFile = process.argv[2];
|
||||||
|
|
||||||
|
if (!migrationFile) {
|
||||||
|
console.error('Usage: node run-migration.mjs <migration-file>');
|
||||||
|
console.error('Example: node run-migration.mjs 018_deployments.sql');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
runMigration(migrationFile)
|
||||||
|
.then(() => process.exit(0))
|
||||||
|
.catch(() => process.exit(1));
|
||||||
Reference in New Issue
Block a user