mcp-adr-analysis-server
Version:
MCP server for analyzing Architectural Decision Records and project architecture
696 lines (677 loc) • 30 kB
JavaScript
/**
* Deployment Readiness Tool - Version 1.0
*
* Comprehensive deployment validation with test failure tracking, deployment history analysis,
* and hard blocking integration with smart git push.
*
* IMPORTANT FOR AI ASSISTANTS: This tool provides:
* 1. Test Execution Validation: Zero tolerance for test failures
* 2. Deployment History Analysis: Pattern detection and success rate tracking
* 3. Code Quality Gates: Mock vs production code detection
* 4. Hard Blocking: Prevents unsafe deployments via smart git push integration
*
* Cache Dependencies:
* - CREATES/UPDATES: .mcp-adr-cache/deployment-history.json (deployment tracking)
* - CREATES/UPDATES: .mcp-adr-cache/deployment-readiness-cache.json (analysis cache)
* - INTEGRATES: smart-git-push-tool for deployment blocking
* - INTEGRATES: todo-management-tool for automatic task creation
*/
import { z } from 'zod';
import { McpAdrError } from '../types/index.js';
import { execSync } from 'child_process';
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { join } from 'path';
import { validateMcpResponse } from '../utils/mcp-response-validator.js';
import { jsonSafeError } from '../utils/json-safe.js';
// Core schemas
const DeploymentReadinessSchema = z.object({
operation: z.enum([
'check_readiness', // Full deployment readiness check
'validate_production', // Production-specific validation
'test_validation', // Test execution and failure analysis
'deployment_history', // Deployment history analysis
'full_audit', // Comprehensive audit (all checks)
'emergency_override' // Emergency bypass with justification
]).describe('Operation to perform'),
// Core Configuration
projectPath: z.string().optional().describe('Project root path'),
targetEnvironment: z.enum(['staging', 'production', 'integration']).default('production').describe('Target deployment environment'),
strictMode: z.boolean().default(true).describe('Enable strict validation (recommended)'),
// Code Quality Gates
allowMockCode: z.boolean().default(false).describe('Allow mock code in deployment (NOT RECOMMENDED)'),
productionCodeThreshold: z.number().default(85).describe('Minimum production code quality score (0-100)'),
mockCodeMaxAllowed: z.number().default(0).describe('Maximum mock code indicators allowed'),
// Test Failure Gates
maxTestFailures: z.number().default(0).describe('Maximum test failures allowed (0 = zero tolerance)'),
requireTestCoverage: z.number().default(80).describe('Minimum test coverage percentage required'),
blockOnFailingTests: z.boolean().default(true).describe('Block deployment if tests are failing'),
testSuiteRequired: z.array(z.string()).default([]).describe('Required test suites that must pass'),
// Deployment History Gates
maxRecentFailures: z.number().default(2).describe('Maximum recent deployment failures allowed'),
deploymentSuccessThreshold: z.number().default(80).describe('Minimum deployment success rate required (%)'),
blockOnRecentFailures: z.boolean().default(true).describe('Block if recent deployments failed'),
rollbackFrequencyThreshold: z.number().default(20).describe('Maximum rollback frequency allowed (%)'),
// Integration Rules
requireAdrCompliance: z.boolean().default(true).describe('Require ADR compliance validation'),
integrateTodoTasks: z.boolean().default(true).describe('Auto-create blocking tasks for issues'),
updateHealthScoring: z.boolean().default(true).describe('Update project health scores'),
triggerSmartGitPush: z.boolean().default(false).describe('Trigger smart git push validation'),
// Human Override System
emergencyBypass: z.boolean().default(false).describe('Emergency bypass for critical fixes'),
businessJustification: z.string().optional().describe('Business justification for overrides'),
approvalRequired: z.boolean().default(true).describe('Require approval for overrides')
});
/**
* Main deployment readiness function
*/
export async function deploymentReadiness(args) {
try {
const validatedArgs = DeploymentReadinessSchema.parse(args);
// Initialize paths and cache
const projectPath = validatedArgs.projectPath || process.cwd();
const cacheDir = join(projectPath, '.mcp-adr-cache');
const deploymentHistoryPath = join(cacheDir, 'deployment-history.json');
const readinessCachePath = join(cacheDir, 'deployment-readiness-cache.json');
// Ensure cache directory exists
if (!existsSync(cacheDir)) {
mkdirSync(cacheDir, { recursive: true });
}
let result;
switch (validatedArgs.operation) {
case 'test_validation':
result = await performTestValidation(validatedArgs, projectPath);
break;
case 'deployment_history':
result = await performDeploymentHistoryAnalysis(validatedArgs, deploymentHistoryPath);
break;
case 'check_readiness':
case 'validate_production':
case 'full_audit':
result = await performFullAudit(validatedArgs, projectPath, deploymentHistoryPath);
break;
case 'emergency_override':
result = await performEmergencyOverride(validatedArgs, projectPath);
break;
default:
throw new McpAdrError('INVALID_ARGS', `Unknown operation: ${validatedArgs.operation}`);
}
// Cache result for performance
writeFileSync(readinessCachePath, JSON.stringify({
timestamp: new Date().toISOString(),
operation: validatedArgs.operation,
result
}, null, 2));
// Generate response based on deployment readiness
return generateDeploymentReadinessResponse(result, validatedArgs);
}
catch (error) {
throw new McpAdrError('DEPLOYMENT_READINESS_ERROR', `Deployment readiness check failed: ${jsonSafeError(error)}`);
}
}
/**
* Perform comprehensive test validation
*/
async function performTestValidation(args, projectPath) {
const testResult = await executeTestSuite(projectPath, args.testSuiteRequired);
const testBlockers = [];
// Check for test failures
if (testResult.failureCount > args.maxTestFailures) {
testBlockers.push({
category: 'test_failure',
title: 'Test Failures Detected',
description: `${testResult.failureCount} test failures found (max allowed: ${args.maxTestFailures})`,
severity: 'critical',
impact: 'Blocks deployment due to failing tests',
resolutionSteps: [
'Run npm test to see detailed failures',
'Fix failing tests one by one',
'Ensure all tests pass before deployment',
'Consider increasing test coverage'
],
estimatedResolutionTime: `${Math.ceil(testResult.failureCount * 0.5)} hours`,
blocksDeployment: args.blockOnFailingTests
});
}
// Check test coverage
if (testResult.coveragePercentage < args.requireTestCoverage) {
testBlockers.push({
category: 'test_failure',
title: 'Insufficient Test Coverage',
description: `Test coverage is ${testResult.coveragePercentage}% (minimum required: ${args.requireTestCoverage}%)`,
severity: 'high',
impact: 'May indicate untested code paths',
resolutionSteps: [
'Add tests for uncovered code',
'Run npm run test:coverage to see detailed coverage',
'Focus on critical business logic first'
],
estimatedResolutionTime: '2-4 hours',
blocksDeployment: args.strictMode
});
}
// Basic result structure
return {
isDeploymentReady: testBlockers.length === 0,
overallScore: calculateTestScore(testResult, args),
confidence: 85,
codeQualityAnalysis: { qualityScore: 75, productionIndicators: 10, mockIndicators: 2, failingFiles: [], recommendations: [] },
testValidationResult: testResult,
deploymentHistoryAnalysis: { recentDeployments: [], successRate: 100, rollbackRate: 0, averageDeploymentTime: 0, failurePatterns: [], environmentStability: { stabilityScore: 100, riskLevel: 'low', recommendation: 'Proceed with deployment' }, recommendedAction: 'proceed' },
adrComplianceResult: { score: 100, compliantAdrs: 0, totalAdrs: 0, missingImplementations: [], recommendations: [] },
criticalBlockers: testBlockers.filter(b => b.severity === 'critical'),
testFailureBlockers: testBlockers,
deploymentHistoryBlockers: [],
warnings: [],
todoTasksCreated: [],
healthScoreUpdate: {},
gitPushStatus: testBlockers.length === 0 ? 'allowed' : 'blocked',
overrideStatus: {}
};
}
/**
* Execute test suite and analyze results
*/
async function executeTestSuite(projectPath, _requiredSuites) {
const startTime = Date.now();
let testOutput = '';
let exitCode = 0;
try {
// Try to run tests with different commands
const testCommands = ['npm test', 'yarn test', 'npx jest'];
for (const command of testCommands) {
try {
testOutput = execSync(command, {
cwd: projectPath,
encoding: 'utf8',
timeout: 300000 // 5 minute timeout
});
break;
}
catch (error) {
if (error.status !== undefined) {
// Command executed but tests failed
testOutput = error.stdout + error.stderr;
exitCode = error.status;
break;
}
// Command not found, try next
}
}
}
catch (error) {
testOutput = `Test execution failed: ${error}`;
exitCode = 1;
}
const executionTime = Date.now() - startTime;
// Parse test results (simplified for now)
const testSuites = parseTestOutput(testOutput);
const totalFailures = testSuites.reduce((sum, suite) => sum + suite.failedTests, 0);
const overallStatus = exitCode === 0 ? 'passed' : (totalFailures > 0 ? 'failed' : 'partial');
// Check coverage (simplified)
const coverage = await checkTestCoverage(projectPath);
return {
testSuitesExecuted: testSuites,
overallTestStatus: overallStatus,
failureCount: totalFailures,
coveragePercentage: coverage,
requiredSuitesMissing: [],
criticalTestFailures: testSuites.flatMap(suite => suite.failureDetails.filter(f => f.severity === 'critical')),
testExecutionTime: executionTime,
lastTestRun: new Date().toISOString()
};
}
/**
* Parse test output to extract results
*/
function parseTestOutput(output) {
// Simplified parser - in production, would handle Jest, Mocha, etc.
const lines = output.split('\n');
const suites = [];
// Look for Jest-style output
let currentSuite = {};
for (const line of lines) {
if (line.includes('PASS') || line.includes('FAIL')) {
if (currentSuite.suiteName) {
suites.push(currentSuite);
}
currentSuite = {
suiteName: line.split(' ').pop() || 'unknown',
status: line.includes('PASS') ? 'passed' : 'failed',
passedTests: 0,
failedTests: 0,
coverage: 0,
executionTime: 0,
failureDetails: []
};
}
// Count tests
if (line.includes('✓') || line.includes('✗')) {
if (line.includes('✓')) {
currentSuite.passedTests = (currentSuite.passedTests || 0) + 1;
}
else {
currentSuite.failedTests = (currentSuite.failedTests || 0) + 1;
// Add failure detail
currentSuite.failureDetails?.push({
testName: line.trim(),
testSuite: currentSuite.suiteName || 'unknown',
errorMessage: line,
severity: 'medium',
blocksDeployment: true,
relatedFiles: []
});
}
}
}
if (currentSuite.suiteName) {
suites.push(currentSuite);
}
return suites.length > 0 ? suites : [{
suiteName: 'default',
status: output.includes('failing') ? 'failed' : 'passed',
passedTests: 0,
failedTests: output.includes('failing') ? 1 : 0,
coverage: 0,
executionTime: 0,
failureDetails: []
}];
}
/**
* Check test coverage
*/
async function checkTestCoverage(projectPath) {
try {
// Try to read coverage from common locations
const coverageFiles = [
'coverage/lcov-report/index.html',
'coverage/coverage-summary.json',
'coverage/coverage-final.json'
];
for (const file of coverageFiles) {
const filePath = join(projectPath, file);
if (existsSync(filePath)) {
const content = readFileSync(filePath, 'utf8');
// Extract coverage percentage (simplified)
const match = content.match(/(\d+(?:\.\d+)?)%/);
if (match && match[1]) {
return parseFloat(match[1]);
}
}
}
}
catch (error) {
// Coverage not available
}
return 0; // Default to 0 if coverage cannot be determined
}
/**
* Perform deployment history analysis
*/
async function performDeploymentHistoryAnalysis(args, historyPath) {
const history = loadDeploymentHistory(historyPath);
const analysis = analyzeDeploymentHistory(history, args.targetEnvironment);
const historyBlockers = [];
// Check success rate
if (analysis.successRate < args.deploymentSuccessThreshold) {
historyBlockers.push({
category: 'deployment_history',
title: 'Low Deployment Success Rate',
description: `Success rate is ${analysis.successRate}% (minimum required: ${args.deploymentSuccessThreshold}%)`,
severity: 'high',
impact: 'Indicates potential infrastructure or process issues',
resolutionSteps: [
'Review recent deployment failures',
'Fix underlying infrastructure issues',
'Improve deployment process reliability',
'Add more comprehensive pre-deployment checks'
],
estimatedResolutionTime: '1-2 days',
blocksDeployment: args.blockOnRecentFailures
});
}
// Check rollback rate
if (analysis.rollbackRate > args.rollbackFrequencyThreshold) {
historyBlockers.push({
category: 'deployment_history',
title: 'High Rollback Frequency',
description: `Rollback rate is ${analysis.rollbackRate}% (threshold: ${args.rollbackFrequencyThreshold}%)`,
severity: 'medium',
impact: 'May indicate deployment quality issues',
resolutionSteps: [
'Improve testing before deployment',
'Add more validation steps',
'Review rollback causes',
'Strengthen deployment pipeline'
],
estimatedResolutionTime: '4-8 hours',
blocksDeployment: args.strictMode
});
}
return {
isDeploymentReady: historyBlockers.length === 0,
overallScore: Math.min(analysis.successRate, 100 - analysis.rollbackRate),
confidence: 80,
codeQualityAnalysis: { qualityScore: 75, productionIndicators: 10, mockIndicators: 2, failingFiles: [], recommendations: [] },
testValidationResult: { testSuitesExecuted: [], overallTestStatus: 'not_run', failureCount: 0, coveragePercentage: 0, requiredSuitesMissing: [], criticalTestFailures: [], testExecutionTime: 0, lastTestRun: '' },
deploymentHistoryAnalysis: analysis,
adrComplianceResult: { score: 100, compliantAdrs: 0, totalAdrs: 0, missingImplementations: [], recommendations: [] },
criticalBlockers: historyBlockers.filter(b => b.severity === 'critical'),
testFailureBlockers: [],
deploymentHistoryBlockers: historyBlockers,
warnings: [],
todoTasksCreated: [],
healthScoreUpdate: {},
gitPushStatus: historyBlockers.length === 0 ? 'allowed' : 'blocked',
overrideStatus: {}
};
}
/**
* Load deployment history from cache
*/
function loadDeploymentHistory(historyPath) {
if (!existsSync(historyPath)) {
return { deployments: [] };
}
try {
const content = readFileSync(historyPath, 'utf8');
return JSON.parse(content);
}
catch (error) {
return { deployments: [] };
}
}
/**
* Analyze deployment history patterns
*/
function analyzeDeploymentHistory(history, environment) {
const recentDeployments = history.deployments
.filter(d => d.environment === environment)
.slice(0, 10);
const successCount = recentDeployments.filter(d => d.status === 'success').length;
const rollbackCount = recentDeployments.filter(d => d.rollbackRequired).length;
const successRate = recentDeployments.length > 0 ? (successCount / recentDeployments.length) * 100 : 100;
const rollbackRate = recentDeployments.length > 0 ? (rollbackCount / recentDeployments.length) * 100 : 0;
const failurePatterns = analyzeFailurePatterns(recentDeployments.filter(d => d.status === 'failed'));
return {
recentDeployments,
successRate,
rollbackRate,
averageDeploymentTime: calculateAverageDeploymentTime(recentDeployments),
failurePatterns,
environmentStability: assessEnvironmentStability(successRate, rollbackRate),
recommendedAction: recommendAction(successRate, rollbackRate, failurePatterns.length)
};
}
/**
* Analyze failure patterns
*/
function analyzeFailurePatterns(failedDeployments) {
const patterns = new Map();
failedDeployments.forEach(deployment => {
if (deployment.failureReason) {
const category = categorizeFailure(deployment.failureReason);
const existing = patterns.get(category);
if (existing) {
existing.frequency++;
existing.lastOccurrence = deployment.timestamp;
}
else {
patterns.set(category, {
pattern: category,
frequency: 1,
environments: [deployment.environment],
lastOccurrence: deployment.timestamp,
resolution: suggestResolution(category),
preventable: isPreventable(category)
});
}
}
});
return Array.from(patterns.values());
}
/**
* Perform full audit (all checks)
*/
async function performFullAudit(args, projectPath, historyPath) {
// Combine all validations
const testResult = await performTestValidation(args, projectPath);
const historyResult = await performDeploymentHistoryAnalysis(args, historyPath);
const allBlockers = [
...testResult.criticalBlockers,
...testResult.testFailureBlockers,
...historyResult.deploymentHistoryBlockers
];
const overallScore = (testResult.overallScore + historyResult.overallScore) / 2;
const isReady = allBlockers.length === 0;
return {
isDeploymentReady: isReady,
overallScore,
confidence: Math.min(testResult.confidence, historyResult.confidence),
codeQualityAnalysis: testResult.codeQualityAnalysis,
testValidationResult: testResult.testValidationResult,
deploymentHistoryAnalysis: historyResult.deploymentHistoryAnalysis,
adrComplianceResult: testResult.adrComplianceResult,
criticalBlockers: allBlockers.filter(b => b.severity === 'critical'),
testFailureBlockers: testResult.testFailureBlockers,
deploymentHistoryBlockers: historyResult.deploymentHistoryBlockers,
warnings: [...testResult.warnings, ...historyResult.warnings],
todoTasksCreated: [],
healthScoreUpdate: {},
gitPushStatus: isReady ? 'allowed' : 'blocked',
overrideStatus: {}
};
}
/**
* Perform emergency override
*/
async function performEmergencyOverride(args, projectPath) {
if (!args.businessJustification) {
throw new McpAdrError('INVALID_ARGS', 'Business justification required for emergency override');
}
// Log override for audit trail
const overrideRecord = {
timestamp: new Date().toISOString(),
justification: args.businessJustification || 'No justification provided',
environment: args.targetEnvironment,
overriddenBy: process.env['USER'] || 'unknown'
};
const overridePath = join(projectPath, '.mcp-adr-cache', 'emergency-overrides.json');
const overrides = existsSync(overridePath) ? JSON.parse(readFileSync(overridePath, 'utf8')) : [];
overrides.push(overrideRecord);
writeFileSync(overridePath, JSON.stringify(overrides, null, 2));
return {
isDeploymentReady: true,
overallScore: 100,
confidence: 50, // Lower confidence for overrides
codeQualityAnalysis: { qualityScore: 100, productionIndicators: 0, mockIndicators: 0, failingFiles: [], recommendations: ['Emergency override active - review post-deployment'] },
testValidationResult: { testSuitesExecuted: [], overallTestStatus: 'not_run', failureCount: 0, coveragePercentage: 0, requiredSuitesMissing: [], criticalTestFailures: [], testExecutionTime: 0, lastTestRun: '' },
deploymentHistoryAnalysis: { recentDeployments: [], successRate: 100, rollbackRate: 0, averageDeploymentTime: 0, failurePatterns: [], environmentStability: { stabilityScore: 50, riskLevel: 'medium', recommendation: 'Monitor closely post-deployment' }, recommendedAction: 'proceed' },
adrComplianceResult: { score: 100, compliantAdrs: 0, totalAdrs: 0, missingImplementations: [], recommendations: [] },
criticalBlockers: [],
testFailureBlockers: [],
deploymentHistoryBlockers: [],
warnings: ['Emergency override active - all normal gates bypassed'],
todoTasksCreated: [],
healthScoreUpdate: {},
gitPushStatus: 'allowed',
overrideStatus: overrideRecord
};
}
/**
* Helper functions
*/
function calculateTestScore(testResult, _args) {
const failureScore = Math.max(0, 100 - (testResult.failureCount * 20));
const coverageScore = testResult.coveragePercentage;
return Math.min(failureScore, coverageScore);
}
function calculateAverageDeploymentTime(deployments) {
if (deployments.length === 0)
return 0;
const total = deployments.reduce((sum, d) => sum + d.duration, 0);
return total / deployments.length;
}
function assessEnvironmentStability(successRate, rollbackRate) {
const stabilityScore = Math.max(0, successRate - rollbackRate);
let riskLevel;
if (stabilityScore >= 90)
riskLevel = 'low';
else if (stabilityScore >= 70)
riskLevel = 'medium';
else if (stabilityScore >= 50)
riskLevel = 'high';
else
riskLevel = 'critical';
return {
stabilityScore,
riskLevel,
recommendation: riskLevel === 'low' ? 'Proceed with deployment' : 'Investigate before deployment'
};
}
function recommendAction(successRate, rollbackRate, failurePatternCount) {
if (successRate < 50 || rollbackRate > 40)
return 'block';
if (successRate < 80 || rollbackRate > 20 || failurePatternCount > 2)
return 'investigate';
return 'proceed';
}
function categorizeFailure(failureReason) {
const patterns = [
{ regex: /test.*fail/i, category: 'Test Failures' },
{ regex: /database.*connection/i, category: 'Database Connection Issues' },
{ regex: /environment.*variable/i, category: 'Environment Configuration' },
{ regex: /build.*fail/i, category: 'Build Failures' },
{ regex: /dependency.*error/i, category: 'Dependency Issues' },
{ regex: /timeout/i, category: 'Timeout Issues' },
{ regex: /permission.*denied/i, category: 'Permission Issues' },
{ regex: /out.*of.*memory/i, category: 'Resource Issues' }
];
for (const pattern of patterns) {
if (pattern.regex.test(failureReason)) {
return pattern.category;
}
}
return 'Unknown Failure';
}
function suggestResolution(category) {
const resolutions = {
'Test Failures': 'Fix failing tests and improve test coverage',
'Database Connection Issues': 'Check database connectivity and credentials',
'Environment Configuration': 'Verify environment variables and configuration',
'Build Failures': 'Fix build dependencies and compilation errors',
'Dependency Issues': 'Update and verify package dependencies',
'Timeout Issues': 'Optimize performance and increase timeout values',
'Permission Issues': 'Check file and directory permissions',
'Resource Issues': 'Increase available memory and resources'
};
return resolutions[category] || 'Investigate failure details and resolve underlying issue';
}
function isPreventable(category) {
const preventableCategories = [
'Test Failures',
'Environment Configuration',
'Build Failures',
'Dependency Issues'
];
return preventableCategories.includes(category);
}
/**
* Generate comprehensive response based on deployment readiness
*/
function generateDeploymentReadinessResponse(result, args) {
if (result.isDeploymentReady) {
return generateSuccessResponse(result, args);
}
else {
return generateBlockedResponse(result, args);
}
}
function generateSuccessResponse(result, args) {
return validateMcpResponse({
content: [{
type: 'text',
text: `✅ **DEPLOYMENT READY - All Gates Passed**
## 🎯 Overall Assessment
- **Deployment Ready**: ✅ **YES**
- **Readiness Score**: ${result.overallScore}%
- **Confidence**: ${result.confidence}%
- **Target Environment**: ${args.targetEnvironment}
## 🧪 Test Validation
- **Test Status**: ✅ ${result.testValidationResult.overallTestStatus.toUpperCase()}
- **Test Failures**: ${result.testValidationResult.failureCount}
- **Coverage**: ${result.testValidationResult.coveragePercentage}%
- **Execution Time**: ${result.testValidationResult.testExecutionTime}ms
## 📊 Deployment History
- **Success Rate**: ${result.deploymentHistoryAnalysis.successRate}%
- **Rollback Rate**: ${result.deploymentHistoryAnalysis.rollbackRate}%
- **Environment Stability**: ${result.deploymentHistoryAnalysis.environmentStability.riskLevel}
## 🚀 Deployment Approved
${args.triggerSmartGitPush ? 'Triggering smart git push...' : 'Ready to proceed with deployment'}
${result.warnings.length > 0 ? `
## ⚠️ Warnings
${result.warnings.map(w => `- ${w}`).join('\n')}
` : ''}
**✅ DEPLOYMENT CAN PROCEED SAFELY**`
}]
});
}
function generateBlockedResponse(result, args) {
return validateMcpResponse({
content: [{
type: 'text',
text: `🚨 **DEPLOYMENT BLOCKED - Critical Issues Found**
## 🎯 Overall Assessment
- **Deployment Ready**: ❌ **NO**
- **Readiness Score**: ${result.overallScore}%
- **Confidence**: ${result.confidence}%
- **Target Environment**: ${args.targetEnvironment}
## 🧪 Test Validation Issues
${result.testFailureBlockers.length > 0 ? `
**Test Failures**: ${result.testValidationResult.failureCount} failures detected
**Coverage**: ${result.testValidationResult.coveragePercentage}% (Required: ${args.requireTestCoverage}%)
### Critical Test Failures:
${result.testValidationResult.criticalTestFailures.map(f => `- ❌ ${f.testSuite}: ${f.testName}`).join('\n')}
` : '✅ Tests passing'}
## 📊 Deployment History Issues
${result.deploymentHistoryBlockers.length > 0 ? `
**Success Rate**: ${result.deploymentHistoryAnalysis.successRate}% (Required: ${args.deploymentSuccessThreshold}%)
**Rollback Rate**: ${result.deploymentHistoryAnalysis.rollbackRate}% (Threshold: ${args.rollbackFrequencyThreshold}%)
### Recent Failure Patterns:
${result.deploymentHistoryAnalysis.failurePatterns.map(p => `- **${p.pattern}**: ${p.frequency} occurrences`).join('\n')}
` : '✅ Deployment history stable'}
## 🚨 Critical Blockers (Must Fix Before Deployment)
${result.criticalBlockers.map(blocker => `
### ${blocker.category.toUpperCase()}: ${blocker.title}
- **Impact**: ${blocker.impact}
- **Resolution**: ${blocker.resolutionSteps.join(' → ')}
- **Estimated Time**: ${blocker.estimatedResolutionTime}
`).join('\n')}
## 🛠️ Immediate Actions Required
### 1. Fix Test Issues
\`\`\`bash
# Run tests and fix failures
npm test
# Check detailed coverage
npm run test:coverage
\`\`\`
### 2. Address Deployment History
\`\`\`bash
# Review recent failures
# Fix infrastructure issues
# Improve deployment reliability
\`\`\`
### 3. Re-validate When Fixed
\`\`\`bash
# Run full audit again
deployment_readiness --operation full_audit --target-environment ${args.targetEnvironment}
\`\`\`
## ⚠️ Emergency Override
For critical fixes only:
\`\`\`bash
deployment_readiness --operation emergency_override --business-justification "Your justification"
\`\`\`
**❌ DEPLOYMENT CANNOT PROCEED UNTIL ALL CRITICAL BLOCKERS ARE RESOLVED**`
}]
});
}
//# sourceMappingURL=deployment-readiness-tool.js.map