- Move test files to tests/ - Archive session notes to docs/archive/ - Remove temp/diagnostic files - Clean src/ to only contain production code
126 lines
4.9 KiB
TypeScript
Executable File
126 lines
4.9 KiB
TypeScript
Executable File
#!/usr/bin/env bun
|
|
/**
|
|
* Production Deployment Integration Test
|
|
*
|
|
* Tests the complete deployment flow with real Dokploy API:
|
|
* - Project creation
|
|
* - Environment retrieval
|
|
* - Application creation
|
|
* - Configuration
|
|
* - Domain setup
|
|
* - Deployment
|
|
* - Health verification
|
|
* - Cleanup/Rollback
|
|
*/
|
|
|
|
import { createProductionDokployClient } from './api/dokploy-production.js';
|
|
import { ProductionDeployer } from './orchestrator/production-deployer.js';
|
|
|
|
console.log('═══════════════════════════════════════');
|
|
console.log(' Production Deployment Integration Test');
|
|
console.log('═══════════════════════════════════════\n');
|
|
|
|
const TEST_STACK_NAME = `test-prod-${Date.now()}`;
|
|
const DOCKER_IMAGE = process.env.STACK_IMAGE || 'nginx:alpine';
|
|
const DOMAIN_SUFFIX = process.env.STACK_DOMAIN_SUFFIX || 'ai.flexinit.nl';
|
|
|
|
console.log(`Test Configuration:`);
|
|
console.log(` Stack Name: ${TEST_STACK_NAME}`);
|
|
console.log(` Docker Image: ${DOCKER_IMAGE}`);
|
|
console.log(` Domain: ${TEST_STACK_NAME}.${DOMAIN_SUFFIX}`);
|
|
console.log();
|
|
|
|
async function main() {
|
|
const client = createProductionDokployClient();
|
|
const deployer = new ProductionDeployer(client);
|
|
|
|
console.log('🚀 Starting deployment...\n');
|
|
|
|
const result = await deployer.deploy({
|
|
stackName: TEST_STACK_NAME,
|
|
dockerImage: DOCKER_IMAGE,
|
|
domainSuffix: DOMAIN_SUFFIX,
|
|
port: 80, // nginx default port
|
|
healthCheckTimeout: 120000, // 2 minutes
|
|
healthCheckInterval: 5000, // 5 seconds
|
|
});
|
|
|
|
console.log('\n═══════════════════════════════════════');
|
|
console.log(' Deployment Result');
|
|
console.log('═══════════════════════════════════════\n');
|
|
|
|
console.log(`Status: ${result.success ? '✅ SUCCESS' : '❌ FAILURE'}`);
|
|
console.log(`Deployment ID: ${result.state.id}`);
|
|
console.log(`Final Phase: ${result.state.phase}`);
|
|
console.log(`Progress: ${result.state.progress}%`);
|
|
console.log(`Message: ${result.state.message}`);
|
|
|
|
if (result.state.url) {
|
|
console.log(`URL: ${result.state.url}`);
|
|
}
|
|
|
|
console.log(`\nResources Created:`);
|
|
console.log(` Project ID: ${result.state.resources.projectId || 'N/A'}`);
|
|
console.log(` Environment ID: ${result.state.resources.environmentId || 'N/A'}`);
|
|
console.log(` Application ID: ${result.state.resources.applicationId || 'N/A'}`);
|
|
console.log(` Domain ID: ${result.state.resources.domainId || 'N/A'}`);
|
|
|
|
console.log(`\nTimestamps:`);
|
|
console.log(` Started: ${result.state.timestamps.started}`);
|
|
console.log(` Completed: ${result.state.timestamps.completed || 'N/A'}`);
|
|
|
|
if (result.state.error) {
|
|
console.log(`\nError Details:`);
|
|
console.log(` Phase: ${result.state.error.phase}`);
|
|
console.log(` Message: ${result.state.error.message}`);
|
|
if (result.state.error.code) {
|
|
console.log(` Code: ${result.state.error.code}`);
|
|
}
|
|
}
|
|
|
|
console.log(`\nCircuit Breaker State: ${client.getCircuitBreakerState()}`);
|
|
|
|
console.log(`\n═══════════════════════════════════════`);
|
|
console.log(' Deployment Logs');
|
|
console.log('═══════════════════════════════════════\n');
|
|
|
|
const logs = client.getLogs();
|
|
logs.forEach(log => {
|
|
const level = log.level.toUpperCase().padEnd(5);
|
|
const phase = log.phase.padEnd(15);
|
|
const action = log.action.padEnd(10);
|
|
const duration = log.duration_ms ? ` (${log.duration_ms}ms)` : '';
|
|
console.log(`[${level}] ${phase} ${action} ${log.message}${duration}`);
|
|
if (log.error) {
|
|
console.log(` Error: ${log.error.message}`);
|
|
}
|
|
});
|
|
|
|
// Cleanup test resources
|
|
if (result.success && result.state.resources.applicationId) {
|
|
console.log('\n🧹 Cleaning up test resources...');
|
|
try {
|
|
await client.deleteApplication(result.state.resources.applicationId);
|
|
console.log('✅ Test application deleted');
|
|
|
|
if (result.state.resources.projectId) {
|
|
await client.deleteProject(result.state.resources.projectId);
|
|
console.log('✅ Test project deleted');
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Cleanup failed:', error);
|
|
}
|
|
}
|
|
|
|
console.log('\n═══════════════════════════════════════');
|
|
console.log(result.success ? ' ✅ Test PASSED' : ' ❌ Test FAILED');
|
|
console.log('═══════════════════════════════════════\n');
|
|
|
|
process.exit(result.success ? 0 : 1);
|
|
}
|
|
|
|
main().catch(error => {
|
|
console.error('\n❌ Test execution failed:', error);
|
|
process.exit(1);
|
|
});
|