@tamyla/clodo-framework 3.1.21 โ 3.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +53 -0
- package/dist/bin/clodo-service.js +47 -15
- package/dist/bin/commands/deploy.js +115 -83
- package/dist/bin/commands/helpers/deployment-ui.js +138 -0
- package/dist/bin/commands/helpers/deployment-verification.js +251 -0
- package/dist/bin/commands/helpers/error-recovery.js +80 -0
- package/dist/bin/commands/helpers/resource-detection.js +113 -0
- package/dist/bin/commands/validate.js +1 -1
- package/dist/bin/security/security-cli.js +1 -1
- package/dist/bin/shared/cache/configuration-cache.js +82 -0
- package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
- package/dist/bin/shared/cloudflare/index.js +1 -1
- package/dist/bin/shared/cloudflare/ops.js +6 -4
- package/dist/bin/shared/config/ConfigurationManager.js +23 -1
- package/dist/bin/shared/config/command-config-manager.js +19 -3
- package/dist/bin/shared/config/index.js +1 -1
- package/dist/bin/shared/deployment/credential-collector.js +30 -7
- package/dist/bin/shared/deployment/index.js +2 -2
- package/dist/bin/shared/deployment/rollback-manager.js +4 -520
- package/dist/bin/shared/deployment/utilities/d1-error-recovery.js +177 -0
- package/dist/bin/shared/deployment/validator.js +40 -10
- package/dist/bin/shared/deployment/workflows/deployment-summary.js +214 -0
- package/dist/bin/shared/deployment/workflows/interactive-confirmation.js +188 -0
- package/dist/bin/shared/deployment/workflows/interactive-database-workflow.js +234 -0
- package/dist/bin/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
- package/dist/bin/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
- package/dist/bin/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
- package/dist/bin/shared/deployment/workflows/interactive-validation.js +218 -0
- package/dist/bin/shared/error-handling/error-classifier.js +46 -0
- package/dist/bin/shared/monitoring/health-checker.js +129 -1
- package/dist/bin/shared/monitoring/memory-manager.js +17 -6
- package/dist/bin/shared/routing/domain-router.js +1 -1
- package/dist/bin/shared/utils/deployment-validator.js +97 -0
- package/dist/bin/shared/utils/formatters.js +10 -0
- package/dist/bin/shared/utils/index.js +13 -1
- package/dist/bin/shared/utils/interactive-prompts.js +34 -18
- package/dist/bin/shared/utils/progress-manager.js +2 -2
- package/dist/bin/shared/utils/progress-spinner.js +53 -0
- package/dist/bin/shared/utils/sensitive-redactor.js +91 -0
- package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/patterns/insecure-patterns.js +1 -1
- package/dist/utils/constants.js +102 -0
- package/dist/utils/deployment/wrangler-config-manager.js +215 -48
- package/dist/utils/framework-config.js +2 -2
- package/dist/utils/interactive-prompts.js +10 -59
- package/package.json +16 -8
- package/dist/bin/clodo-service-old.js +0 -868
- package/dist/bin/clodo-service-test.js +0 -10
- package/dist/bin/commands/assess.js +0 -91
- package/dist/bin/commands/create.js +0 -77
- package/dist/bin/commands/diagnose.js +0 -83
- package/dist/bin/commands/helpers.js +0 -138
- package/dist/bin/commands/update.js +0 -75
- package/dist/bin/database/deployment-db-manager.js +0 -423
- package/dist/bin/database/enterprise-db-manager.js +0 -457
- package/dist/bin/database/wrangler-d1-manager.js +0 -685
- package/dist/bin/deployment/enterprise-deploy.js +0 -877
- package/dist/bin/deployment/master-deploy.js +0 -1376
- package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
- package/dist/bin/deployment/modules/DeploymentConfiguration.js +0 -395
- package/dist/bin/deployment/modules/DeploymentOrchestrator.js +0 -492
- package/dist/bin/deployment/modules/EnvironmentManager.js +0 -517
- package/dist/bin/deployment/modules/MonitoringIntegration.js +0 -560
- package/dist/bin/deployment/modules/ValidationManager.js +0 -342
- package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
- package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +0 -273
- package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
- package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
- package/dist/bin/deployment/test-interactive-utils.js +0 -66
- package/dist/bin/portfolio/portfolio-manager.js +0 -487
- package/dist/bin/service-management/create-service.js +0 -122
- package/dist/bin/service-management/init-service.js +0 -79
- package/dist/config/customers.js +0 -623
- package/dist/config/domains.js +0 -186
- package/dist/config/index.js +0 -6
- package/dist/database/database-orchestrator.js +0 -795
- package/dist/database/index.js +0 -4
- package/dist/deployment/index.js +0 -11
- package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
- package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
- package/dist/deployment/orchestration/PortfolioOrchestrator.js +0 -273
- package/dist/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
- package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
- package/dist/deployment/orchestration/index.js +0 -17
- package/dist/deployment/rollback-manager.js +0 -36
- package/dist/deployment/wrangler-deployer.js +0 -640
- package/dist/handlers/GenericRouteHandler.js +0 -532
- package/dist/migration/MigrationAdapters.js +0 -562
- package/dist/modules/ModuleManager.js +0 -668
- package/dist/modules/security.js +0 -96
- package/dist/orchestration/cross-domain-coordinator.js +0 -1083
- package/dist/orchestration/index.js +0 -5
- package/dist/orchestration/modules/DeploymentCoordinator.js +0 -368
- package/dist/orchestration/modules/DomainResolver.js +0 -198
- package/dist/orchestration/modules/StateManager.js +0 -332
- package/dist/orchestration/multi-domain-orchestrator.js +0 -724
- package/dist/routing/EnhancedRouter.js +0 -158
- package/dist/schema/SchemaManager.js +0 -778
- package/dist/service-management/ConfirmationEngine.js +0 -412
- package/dist/service-management/ErrorTracker.js +0 -299
- package/dist/service-management/GenerationEngine.js +0 -447
- package/dist/service-management/InputCollector.js +0 -619
- package/dist/service-management/ServiceCreator.js +0 -265
- package/dist/service-management/ServiceInitializer.js +0 -453
- package/dist/service-management/ServiceOrchestrator.js +0 -633
- package/dist/service-management/generators/BaseGenerator.js +0 -233
- package/dist/service-management/generators/GeneratorRegistry.js +0 -254
- package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +0 -87
- package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +0 -106
- package/dist/service-management/generators/code/ServiceHandlersGenerator.js +0 -235
- package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +0 -116
- package/dist/service-management/generators/code/ServiceUtilsGenerator.js +0 -246
- package/dist/service-management/generators/code/WorkerIndexGenerator.js +0 -143
- package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +0 -101
- package/dist/service-management/generators/config/DomainsConfigGenerator.js +0 -175
- package/dist/service-management/generators/config/EnvExampleGenerator.js +0 -178
- package/dist/service-management/generators/config/ProductionEnvGenerator.js +0 -97
- package/dist/service-management/generators/config/StagingEnvGenerator.js +0 -97
- package/dist/service-management/generators/config/WranglerTomlGenerator.js +0 -238
- package/dist/service-management/generators/core/PackageJsonGenerator.js +0 -243
- package/dist/service-management/generators/core/SiteConfigGenerator.js +0 -115
- package/dist/service-management/generators/documentation/ApiDocsGenerator.js +0 -331
- package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +0 -294
- package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +0 -244
- package/dist/service-management/generators/documentation/ReadmeGenerator.js +0 -196
- package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +0 -190
- package/dist/service-management/generators/scripts/DeployScriptGenerator.js +0 -123
- package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +0 -101
- package/dist/service-management/generators/scripts/SetupScriptGenerator.js +0 -88
- package/dist/service-management/generators/service-types/StaticSiteGenerator.js +0 -342
- package/dist/service-management/generators/testing/EslintConfigGenerator.js +0 -85
- package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +0 -237
- package/dist/service-management/generators/testing/JestConfigGenerator.js +0 -72
- package/dist/service-management/generators/testing/UnitTestsGenerator.js +0 -277
- package/dist/service-management/generators/tooling/DockerComposeGenerator.js +0 -71
- package/dist/service-management/generators/tooling/GitignoreGenerator.js +0 -143
- package/dist/service-management/generators/utils/FileWriter.js +0 -179
- package/dist/service-management/generators/utils/PathResolver.js +0 -157
- package/dist/service-management/generators/utils/ServiceManifestGenerator.js +0 -111
- package/dist/service-management/generators/utils/TemplateEngine.js +0 -185
- package/dist/service-management/generators/utils/index.js +0 -18
- package/dist/service-management/handlers/ConfirmationHandler.js +0 -71
- package/dist/service-management/handlers/GenerationHandler.js +0 -80
- package/dist/service-management/handlers/InputHandler.js +0 -59
- package/dist/service-management/handlers/ValidationHandler.js +0 -203
- package/dist/service-management/index.js +0 -14
- package/dist/service-management/routing/DomainRouteMapper.js +0 -311
- package/dist/service-management/routing/RouteGenerator.js +0 -266
- package/dist/service-management/routing/WranglerRoutesBuilder.js +0 -273
- package/dist/service-management/routing/index.js +0 -14
- package/dist/service-management/services/DirectoryStructureService.js +0 -56
- package/dist/service-management/services/GenerationCoordinator.js +0 -208
- package/dist/service-management/services/GeneratorRegistry.js +0 -174
- package/dist/services/GenericDataService.js +0 -501
- package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +0 -286
- package/dist/ui-structures/concepts/service-lifecycle-management.md +0 -150
- package/dist/ui-structures/concepts/service-manifest-guide.md +0 -309
- package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +0 -231
- package/dist/ui-structures/creation/automated-generation-ui.json +0 -246
- package/dist/ui-structures/creation/core-inputs-ui.json +0 -217
- package/dist/ui-structures/creation/smart-confirmable-ui.json +0 -451
- package/dist/ui-structures/reference/absolutely-required-inputs.json +0 -315
- package/dist/ui-structures/reference/service-manifest-template.json +0 -342
- package/dist/version/VersionDetector.js +0 -723
- package/dist/worker/index.js +0 -4
- package/dist/worker/integration.js +0 -351
|
@@ -1,877 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Enterprise Deployment CLI
|
|
5
|
-
*
|
|
6
|
-
* Advanced command-line deployment system powered by enterprise modules.
|
|
7
|
-
* Provides comprehensive deployment options, portfolio management, and automation.
|
|
8
|
-
*
|
|
9
|
-
* Enterprise Features:
|
|
10
|
-
* - Command-line driven deployment with rich options
|
|
11
|
-
* - Multi-domain and portfolio deployment capabilities
|
|
12
|
-
* - Automated configuration discovery and generation
|
|
13
|
-
* - Advanced validation and testing pipelines
|
|
14
|
-
* - Rollback and recovery management
|
|
15
|
-
* - Comprehensive audit and reporting
|
|
16
|
-
* - CI/CD integration support
|
|
17
|
-
* - Batch operations and automation
|
|
18
|
-
* - Performance monitoring and analytics
|
|
19
|
-
* - Compliance and security features
|
|
20
|
-
*
|
|
21
|
-
* @version 2.0.0 - Enterprise Edition
|
|
22
|
-
*/
|
|
23
|
-
import { program } from 'commander';
|
|
24
|
-
import { existsSync, readFileSync } from 'fs';
|
|
25
|
-
import { join } from 'path';
|
|
26
|
-
|
|
27
|
-
// Enterprise module imports - organized shared modules
|
|
28
|
-
import { MultiDomainOrchestrator } from "../../orchestration/multi-domain-orchestrator.js";
|
|
29
|
-
import { RollbackManager } from '../shared/deployment/rollback-manager.js';
|
|
30
|
-
import { ProductionTester } from '../shared/production-tester/index.js';
|
|
31
|
-
import { DeploymentValidator } from '../shared/deployment/validator.js';
|
|
32
|
-
import { DomainDiscovery } from '../shared/cloudflare/domain-discovery.js';
|
|
33
|
-
import { DatabaseOrchestrator } from "../../database/database-orchestrator.js";
|
|
34
|
-
import { EnhancedSecretManager } from '../shared/security/secret-generator.js';
|
|
35
|
-
import { DeploymentAuditor } from '../shared/deployment/auditor.js';
|
|
36
|
-
import { ConfigurationCacheManager } from '../shared/config/cache.js';
|
|
37
|
-
import { CrossDomainCoordinator } from "../../orchestration/cross-domain-coordinator.js";
|
|
38
|
-
import { askChoice, askUser, closePrompts } from '../shared/utils/interactive-prompts.js';
|
|
39
|
-
import { CloudflareDomainManager } from '../shared/cloudflare/domain-manager.js';
|
|
40
|
-
|
|
41
|
-
// Consolidated environment manager
|
|
42
|
-
import { EnvironmentManager } from './modules/EnvironmentManager.js';
|
|
43
|
-
class EnterpriseDeploymentCLI {
|
|
44
|
-
constructor() {
|
|
45
|
-
this.version = '2.0.0';
|
|
46
|
-
this.modules = {};
|
|
47
|
-
this.globalConfig = this.loadGlobalConfig();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Initialize the CLI asynchronously
|
|
52
|
-
*/
|
|
53
|
-
async initialize() {
|
|
54
|
-
await this.initializeModules();
|
|
55
|
-
this.setupCommands();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Ensure modules are initialized (lazy initialization)
|
|
60
|
-
*/
|
|
61
|
-
async ensureInitialized() {
|
|
62
|
-
if (!this.modules || Object.keys(this.modules).length === 0) {
|
|
63
|
-
await this.initializeModules();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Load global configuration
|
|
69
|
-
*/
|
|
70
|
-
loadGlobalConfig() {
|
|
71
|
-
const configPath = join(process.cwd(), 'enterprise-deploy.config.json');
|
|
72
|
-
if (existsSync(configPath)) {
|
|
73
|
-
try {
|
|
74
|
-
return JSON.parse(readFileSync(configPath, 'utf8'));
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.warn('โ ๏ธ Failed to load config file, using defaults');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
defaultEnvironment: 'production',
|
|
81
|
-
validationLevel: 'comprehensive',
|
|
82
|
-
auditLevel: 'detailed',
|
|
83
|
-
enableRollback: true,
|
|
84
|
-
enableTesting: true,
|
|
85
|
-
maxConcurrentDeployments: 3,
|
|
86
|
-
deploymentTimeout: 1800000,
|
|
87
|
-
// 30 minutes
|
|
88
|
-
outputFormat: 'enhanced' // 'minimal', 'standard', 'enhanced'
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Add unified environment option to command
|
|
94
|
-
* Consolidates -e, --env option definition across all commands
|
|
95
|
-
*/
|
|
96
|
-
addEnvironmentOption(command, defaultValue) {
|
|
97
|
-
const envOpt = EnvironmentManager.getEnvironmentOption();
|
|
98
|
-
return command.option(envOpt.flag, envOpt.description, defaultValue || this.globalConfig.defaultEnvironment);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Initialize enterprise modules
|
|
103
|
-
*/
|
|
104
|
-
async initializeModules() {
|
|
105
|
-
const domainDiscovery = new DomainDiscovery({
|
|
106
|
-
enableCaching: true
|
|
107
|
-
});
|
|
108
|
-
domainDiscovery.initializeDiscovery();
|
|
109
|
-
this.modules = {
|
|
110
|
-
orchestrator: new MultiDomainOrchestrator({
|
|
111
|
-
maxConcurrentDeployments: this.globalConfig.maxConcurrentDeployments,
|
|
112
|
-
timeout: this.globalConfig.deploymentTimeout
|
|
113
|
-
}),
|
|
114
|
-
validator: new DeploymentValidator({
|
|
115
|
-
validationLevel: this.globalConfig.validationLevel
|
|
116
|
-
}),
|
|
117
|
-
rollbackManager: new RollbackManager({
|
|
118
|
-
autoRollbackEnabled: this.globalConfig.enableRollback
|
|
119
|
-
}),
|
|
120
|
-
domainDiscovery,
|
|
121
|
-
databaseOrchestrator: new DatabaseOrchestrator({
|
|
122
|
-
enableSafeMode: true
|
|
123
|
-
}),
|
|
124
|
-
secretManager: new EnhancedSecretManager({
|
|
125
|
-
crossDomainCoordination: true
|
|
126
|
-
}),
|
|
127
|
-
productionTester: new ProductionTester({
|
|
128
|
-
comprehensiveTests: this.globalConfig.enableTesting
|
|
129
|
-
}),
|
|
130
|
-
auditor: new DeploymentAuditor({
|
|
131
|
-
auditLevel: this.globalConfig.auditLevel
|
|
132
|
-
}),
|
|
133
|
-
configCache: new ConfigurationCacheManager({
|
|
134
|
-
enableRuntimeDiscovery: true
|
|
135
|
-
}),
|
|
136
|
-
coordinator: new CrossDomainCoordinator({
|
|
137
|
-
portfolioName: 'enterprise-cli-portfolio'
|
|
138
|
-
})
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// Initialize async components
|
|
142
|
-
await this.modules.orchestrator.initialize();
|
|
143
|
-
await this.modules.rollbackManager.initialize();
|
|
144
|
-
await this.modules.configCache.initialize();
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Setup CLI commands
|
|
149
|
-
*/
|
|
150
|
-
setupCommands() {
|
|
151
|
-
program.name('enterprise-deploy').description('Enterprise Deployment System - Advanced deployment and portfolio management').version(this.version);
|
|
152
|
-
|
|
153
|
-
// Single domain deployment
|
|
154
|
-
this.addEnvironmentOption(program.command('deploy [domain]').description('Deploy a single domain with enterprise features')).option('-v, --validation <level>', 'validation level (basic|standard|comprehensive)', this.globalConfig.validationLevel).option('-a, --audit <level>', 'audit level (minimal|standard|detailed|verbose)', this.globalConfig.auditLevel).option('-i, --interactive', 'interactive mode - select domain from available options').option('--no-tests', 'skip production testing').option('--no-rollback', 'disable automatic rollback').option('--dry-run', 'simulate deployment without changes').option('--force', 'force deployment even if validation fails').option('--config <file>', 'custom configuration file').action(async (domain, options) => {
|
|
155
|
-
try {
|
|
156
|
-
await this.ensureInitialized();
|
|
157
|
-
if (options.interactive && !domain) {
|
|
158
|
-
domain = await this.selectDomainInteractively();
|
|
159
|
-
}
|
|
160
|
-
if (!domain) {
|
|
161
|
-
console.error('โ Domain is required. Use --interactive to select from available domains, or provide domain as argument.');
|
|
162
|
-
process.exit(1);
|
|
163
|
-
}
|
|
164
|
-
await this.deploySingleDomain(domain, options);
|
|
165
|
-
process.exit(0);
|
|
166
|
-
} catch (error) {
|
|
167
|
-
console.error('โ Deployment failed:', error.message);
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Multi-domain deployment
|
|
173
|
-
this.addEnvironmentOption(program.command('deploy-multi <domains...>').description('Deploy multiple domains with coordination')).option('-b, --batch-size <size>', 'batch size for parallel deployments', '3').option('--coordination', 'enable cross-domain coordination').option('--shared-secrets', 'enable shared secret management').option('--dependency-order', 'resolve and use dependency ordering').option('--dry-run', 'simulate deployment without changes').action(async (domains, options) => {
|
|
174
|
-
try {
|
|
175
|
-
await this.deployMultiDomain(domains, options);
|
|
176
|
-
process.exit(0);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
console.error('โ Multi-domain deployment failed:', error.message);
|
|
179
|
-
process.exit(1);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// Portfolio deployment
|
|
184
|
-
this.addEnvironmentOption(program.command('deploy-portfolio').description('Deploy entire domain portfolio')).option('-f, --filter <pattern>', 'filter domains by pattern').option('--exclude <pattern>', 'exclude domains matching pattern').option('--health-check', 'run health checks before deployment').option('--rollback-threshold <percent>', 'rollback threshold (0-1)', '0.8').option('--dry-run', 'simulate deployment without changes').action(async options => {
|
|
185
|
-
try {
|
|
186
|
-
await this.deployPortfolio(options);
|
|
187
|
-
process.exit(0);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
console.error('โ Portfolio deployment failed:', error.message);
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// Discovery commands
|
|
195
|
-
program.command('discover <domain>').description('Discover domain configuration from Cloudflare').option('--token <token>', 'Cloudflare API token').option('--cache', 'cache discovered configuration').option('--update-config', 'update domains.js with discovery results').action(async (domain, options) => {
|
|
196
|
-
try {
|
|
197
|
-
await this.discoverDomain(domain, options);
|
|
198
|
-
process.exit(0);
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.error('โ Domain discovery failed:', error.message);
|
|
201
|
-
process.exit(1);
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
program.command('discover-portfolio').description('Discover entire portfolio configuration').option('--token <token>', 'Cloudflare API token').option('--update-all', 'update all domain configurations').action(options => this.discoverPortfolio(options));
|
|
205
|
-
|
|
206
|
-
// Validation commands
|
|
207
|
-
this.addEnvironmentOption(program.command('validate <domain>').description('Validate domain deployment readiness')).option('-l, --level <level>', 'validation level', this.globalConfig.validationLevel).option('--fix', 'attempt to fix validation issues').action((domain, options) => this.validateDomain(domain, options));
|
|
208
|
-
this.addEnvironmentOption(program.command('validate-portfolio').description('Validate entire portfolio deployment readiness')).option('--cross-domain', 'include cross-domain compatibility checks').option('--report <format>', 'generate validation report (json|html|csv)', 'json').action(options => this.validatePortfolio(options));
|
|
209
|
-
|
|
210
|
-
// Testing commands
|
|
211
|
-
program.command('test <domain>').description('Run production tests for domain').option('--url <url>', 'custom URL to test').option('--suites <suites>', 'test suites to run (comma-separated)', 'health,endpoints,integration').option('--timeout <ms>', 'test timeout in milliseconds', '30000').option('--report <format>', 'test report format (json|html|junit)', 'json').action((domain, options) => this.testDomain(domain, options));
|
|
212
|
-
program.command('test-portfolio').description('Run production tests for entire portfolio').option('--parallel', 'run tests in parallel').option('--threshold <percent>', 'success threshold (0-1)', '0.9').option('--report <format>', 'test report format', 'html').action(options => this.testPortfolio(options));
|
|
213
|
-
|
|
214
|
-
// Database commands
|
|
215
|
-
this.addEnvironmentOption(program.command('db-migrate <domain>').description('Run database migrations for domain')).option('--create-db', 'create database if it doesn\'t exist').option('--dry-run', 'show migrations without executing').action((domain, options) => this.migrateDomain(domain, options));
|
|
216
|
-
this.addEnvironmentOption(program.command('db-migrate-all').description('Run database migrations for all domains')).option('--parallel', 'run migrations in parallel').option('--safe-mode', 'enable extra safety checks').action(options => this.migrateAll(options));
|
|
217
|
-
|
|
218
|
-
// Secret management commands
|
|
219
|
-
this.addEnvironmentOption(program.command('secrets-generate <domain>').description('Generate secrets for domain')).option('--formats <formats>', 'output formats (comma-separated)', 'env,json,wrangler').option('--coordinate', 'coordinate with other domains').option('--deploy', 'deploy secrets to Cloudflare').action((domain, options) => this.generateSecrets(domain, options));
|
|
220
|
-
this.addEnvironmentOption(program.command('secrets-coordinate <domains...>').description('Coordinate secrets across multiple domains')).option('--sync-critical', 'sync critical secrets across domains').option('--deploy', 'deploy coordinated secrets').action((domains, options) => this.coordinateSecrets(domains, options));
|
|
221
|
-
|
|
222
|
-
// Rollback commands
|
|
223
|
-
program.command('rollback <domain>').description('Rollback domain deployment').option('--deployment-id <id>', 'specific deployment ID to rollback').option('--reason <reason>', 'rollback reason for audit').option('--force', 'force rollback without confirmation').action((domain, options) => this.rollbackDomain(domain, options));
|
|
224
|
-
program.command('rollback-portfolio').description('Rollback portfolio deployment').option('--coordination-id <id>', 'coordination ID to rollback').option('--partial', 'allow partial rollback').action(options => this.rollbackPortfolio(options));
|
|
225
|
-
|
|
226
|
-
// Monitoring commands
|
|
227
|
-
program.command('monitor').description('Monitor portfolio health').option('--interval <ms>', 'monitoring interval', '300000').option('--alert-webhook <url>', 'webhook for alerts').option('--continuous', 'run continuous monitoring').action(options => this.monitorPortfolio(options));
|
|
228
|
-
program.command('status [domain]').description('Get deployment status').option('--detailed', 'show detailed status').option('--format <format>', 'output format (table|json|yaml)', 'table').action((domain, options) => this.getStatus(domain, options));
|
|
229
|
-
|
|
230
|
-
// Audit commands
|
|
231
|
-
program.command('audit <domain>').description('Generate audit report for domain').option('--deployment-id <id>', 'specific deployment ID').option('--format <format>', 'report format (json|html|csv)', 'html').option('--period <days>', 'audit period in days', '30').action((domain, options) => this.auditDomain(domain, options));
|
|
232
|
-
program.command('audit-portfolio').description('Generate portfolio audit report').option('--format <format>', 'report format', 'html').option('--compliance', 'include compliance report').action(options => this.auditPortfolio(options));
|
|
233
|
-
|
|
234
|
-
// Configuration commands
|
|
235
|
-
program.command('config-cache <domain>').description('Manage configuration cache for domain').option('--clear', 'clear cached configuration').option('--refresh', 'refresh cached configuration').option('--show', 'show cached configuration').action((domain, options) => this.manageConfigCache(domain, options));
|
|
236
|
-
|
|
237
|
-
// Utility commands
|
|
238
|
-
program.command('list-domains').description('List all discovered domains').option('--format <format>', 'output format (table|json|yaml)', 'table').action(async options => {
|
|
239
|
-
try {
|
|
240
|
-
await this.ensureInitialized();
|
|
241
|
-
await this.listDomains(options);
|
|
242
|
-
process.exit(0);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.error('โ List domains failed:', error.message);
|
|
245
|
-
process.exit(1);
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
program.command('cleanup').description('Clean up old deployments and logs').option('--days <days>', 'retention period in days', '90').option('--force', 'force cleanup without confirmation').action(options => this.cleanupDeployments(options));
|
|
249
|
-
|
|
250
|
-
// Global options
|
|
251
|
-
program.option('--verbose', 'verbose output').option('--quiet', 'quiet mode - minimal output').option('--no-color', 'disable colored output').option('--output <format>', 'global output format override');
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Deploy single domain
|
|
256
|
-
*/
|
|
257
|
-
async deploySingleDomain(domain, options) {
|
|
258
|
-
try {
|
|
259
|
-
this.logOutput(`๐ Enterprise deployment: ${domain}`, 'info');
|
|
260
|
-
|
|
261
|
-
// Step 1: Comprehensive Cloudflare Domain Verification
|
|
262
|
-
const domainManager = new CloudflareDomainManager();
|
|
263
|
-
let domainVerification;
|
|
264
|
-
try {
|
|
265
|
-
this.logOutput('๐ Verifying domain with Cloudflare...', 'info');
|
|
266
|
-
domainVerification = await domainManager.verifyDomainWorkflow(domain);
|
|
267
|
-
if (domainVerification.action === 'choose_different') {
|
|
268
|
-
// User wants to choose different domain
|
|
269
|
-
domain = await this.selectDomainInteractively();
|
|
270
|
-
this.logOutput(`๐ Enterprise deployment: ${domain}`, 'info');
|
|
271
|
-
// Re-verify the new domain
|
|
272
|
-
domainVerification = await domainManager.verifyDomainWorkflow(domain);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Log domain verification results
|
|
276
|
-
this.logOutput(`โ
Domain verification complete:`, 'success');
|
|
277
|
-
this.logOutput(` ๐ Status: ${domainVerification.domainStatus}`, 'info');
|
|
278
|
-
this.logOutput(` ๐ฏ Action: ${domainVerification.recommendedAction}`, 'info');
|
|
279
|
-
if (domainVerification.existingServices?.length > 0) {
|
|
280
|
-
this.logOutput(` ๐ Existing services: ${domainVerification.existingServices.length}`, 'info');
|
|
281
|
-
}
|
|
282
|
-
} catch (error) {
|
|
283
|
-
if (error.message.includes('DEPLOYMENT_CANCELLED') || error.message.includes('authentication required')) {
|
|
284
|
-
this.logOutput(`โ ${error.message}`, 'error');
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
// Continue with deployment even if verification fails
|
|
288
|
-
this.logOutput(`โ ๏ธ Domain verification failed: ${error.message}`, 'warn');
|
|
289
|
-
this.logOutput('๐ Continuing with deployment...', 'info');
|
|
290
|
-
domainVerification = {
|
|
291
|
-
domainStatus: 'unknown',
|
|
292
|
-
recommendedAction: 'deploy'
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Interactive confirmation (unless force is enabled)
|
|
297
|
-
if (!options.force) {
|
|
298
|
-
const originalDomain = domain;
|
|
299
|
-
let domainSelected = false;
|
|
300
|
-
while (!domainSelected) {
|
|
301
|
-
const confirm = await askChoice(`\nReady to deploy ${domain}?`, ['Yes, proceed with deployment', 'Choose different domain', 'Cancel deployment'], 0);
|
|
302
|
-
if (confirm === 0) {
|
|
303
|
-
// Yes, proceed
|
|
304
|
-
domainSelected = true;
|
|
305
|
-
} else if (confirm === 1) {
|
|
306
|
-
// Choose different domain
|
|
307
|
-
const availableDomains = await this.discoverAvailableDomains();
|
|
308
|
-
if (availableDomains.length <= 1) {
|
|
309
|
-
// No other domains available
|
|
310
|
-
const createNew = await askChoice('No other domains available. What would you like to do?', ['Create a new service', 'Go back to deployment options', 'Cancel deployment'], 0);
|
|
311
|
-
if (createNew === 0) {
|
|
312
|
-
// Create new service
|
|
313
|
-
let serviceName;
|
|
314
|
-
let validServiceName = false;
|
|
315
|
-
while (!validServiceName) {
|
|
316
|
-
serviceName = await askUser('Enter service name (lowercase letters, numbers, hyphens only):');
|
|
317
|
-
if (!serviceName || serviceName.trim() === '') {
|
|
318
|
-
this.logOutput('โ Service name is required', 'error');
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// Validate service name format
|
|
323
|
-
if (!/^[a-z0-9-]+$/.test(serviceName.trim())) {
|
|
324
|
-
this.logOutput('โ Service name must contain only lowercase letters, numbers, and hyphens', 'error');
|
|
325
|
-
this.logOutput('๐ก Example: data-service, user-auth, content-api', 'info');
|
|
326
|
-
continue;
|
|
327
|
-
}
|
|
328
|
-
validServiceName = true;
|
|
329
|
-
serviceName = serviceName.trim();
|
|
330
|
-
}
|
|
331
|
-
try {
|
|
332
|
-
this.logOutput(`๐๏ธ Creating new service: ${serviceName}`, 'info');
|
|
333
|
-
|
|
334
|
-
// Also ask for domain name
|
|
335
|
-
const domainName = await askUser('Enter domain name for this service (e.g., api.example.com):');
|
|
336
|
-
if (!domainName || domainName.trim() === '') {
|
|
337
|
-
this.logOutput('โ Domain name is required', 'error');
|
|
338
|
-
continue;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Run service initialization using spawn with absolute path
|
|
342
|
-
const {
|
|
343
|
-
spawn
|
|
344
|
-
} = await import('child_process');
|
|
345
|
-
const initScriptPath = join(process.cwd(), 'bin', 'service-management', 'init-service.js');
|
|
346
|
-
const initProcess = spawn('node', [initScriptPath, serviceName, '--domains', domainName, '--output', process.cwd()], {
|
|
347
|
-
stdio: 'inherit',
|
|
348
|
-
cwd: process.cwd()
|
|
349
|
-
});
|
|
350
|
-
await new Promise((resolve, reject) => {
|
|
351
|
-
initProcess.on('close', code => {
|
|
352
|
-
if (code === 0) {
|
|
353
|
-
resolve();
|
|
354
|
-
} else {
|
|
355
|
-
reject(new Error(`Service initialization failed with code ${code}`));
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
initProcess.on('error', reject);
|
|
359
|
-
});
|
|
360
|
-
this.logOutput(`โ
Service ${serviceName} created successfully!`, 'success');
|
|
361
|
-
|
|
362
|
-
// Re-discover domains now that we have a new service
|
|
363
|
-
this.logOutput('๐ Re-discovering available domains...', 'info');
|
|
364
|
-
const updatedDomains = await this.discoverAvailableDomains();
|
|
365
|
-
if (updatedDomains.length > 0) {
|
|
366
|
-
domain = await this.selectDomainInteractively();
|
|
367
|
-
this.logOutput(`๐ Enterprise deployment: ${domain}`, 'info');
|
|
368
|
-
} else {
|
|
369
|
-
this.logOutput('โ No domains found after service creation', 'error');
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
} catch (error) {
|
|
373
|
-
this.logOutput(`โ Failed to create service: ${error.message}`, 'error');
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
} else if (createNew === 1) {
|
|
377
|
-
// Go back - continue the loop
|
|
378
|
-
continue;
|
|
379
|
-
} else {
|
|
380
|
-
// Cancel
|
|
381
|
-
this.logOutput('โ Deployment cancelled by user', 'warn');
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
} else {
|
|
385
|
-
// Multiple domains available, let user choose
|
|
386
|
-
domain = await this.selectDomainInteractively();
|
|
387
|
-
this.logOutput(`๐ Enterprise deployment: ${domain}`, 'info');
|
|
388
|
-
}
|
|
389
|
-
} else {
|
|
390
|
-
// Cancel
|
|
391
|
-
this.logOutput('โ Deployment cancelled by user', 'warn');
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const deploymentId = this.generateDeploymentId();
|
|
397
|
-
const auditor = this.modules.auditor;
|
|
398
|
-
|
|
399
|
-
// Start audit session
|
|
400
|
-
const deploymentContext = auditor.startDeploymentAudit(deploymentId, domain, {
|
|
401
|
-
environment: options.env,
|
|
402
|
-
cliMode: true,
|
|
403
|
-
options
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
// Validation phase
|
|
407
|
-
if (!options.force) {
|
|
408
|
-
this.logOutput('๐ Running validation...', 'info');
|
|
409
|
-
const validation = await this.modules.validator.validateDeployment(domain, {
|
|
410
|
-
environment: options.env,
|
|
411
|
-
validationLevel: options.validation,
|
|
412
|
-
deploymentType: domainVerification.domainStatus,
|
|
413
|
-
// 'available', 'update', etc.
|
|
414
|
-
skipEndpointCheck: domainVerification.domainStatus === 'available'
|
|
415
|
-
});
|
|
416
|
-
if (validation.overall !== 'passed') {
|
|
417
|
-
this.logOutput('โ Validation failed:', 'error');
|
|
418
|
-
validation.errors.forEach(error => this.logOutput(` - ${error.message}`, 'error'));
|
|
419
|
-
if (!options.force) {
|
|
420
|
-
process.exit(1);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Execute deployment - Create domain-specific orchestrator
|
|
426
|
-
const domainOrchestrator = new MultiDomainOrchestrator({
|
|
427
|
-
domains: [domain],
|
|
428
|
-
environment: options.env,
|
|
429
|
-
dryRun: options.dryRun,
|
|
430
|
-
parallelDeployments: 1,
|
|
431
|
-
enableRollback: options.rollback !== false
|
|
432
|
-
});
|
|
433
|
-
await domainOrchestrator.initialize();
|
|
434
|
-
const deploymentResult = await domainOrchestrator.deploySingleDomain(domain);
|
|
435
|
-
|
|
436
|
-
// Run tests if enabled
|
|
437
|
-
if (options.tests !== false && deploymentResult.url) {
|
|
438
|
-
this.logOutput('๐งช Running production tests...', 'info');
|
|
439
|
-
this.logOutput('โณ Waiting for deployment to propagate...', 'info');
|
|
440
|
-
|
|
441
|
-
// Wait for deployment to propagate (especially important for new services)
|
|
442
|
-
await new Promise(resolve => setTimeout(resolve, 10000)); // 10 second delay
|
|
443
|
-
|
|
444
|
-
const deploymentUrl = deploymentResult.url;
|
|
445
|
-
const testResult = await this.modules.productionTester.runFullTestSuite(options.env);
|
|
446
|
-
if (testResult.failed > 0) {
|
|
447
|
-
this.logOutput(`โ ๏ธ ${testResult.failed}/${testResult.total} tests failed`, 'warn');
|
|
448
|
-
this.logOutput('๐ก Note: Some test failures may be expected for new deployments during DNS propagation', 'info');
|
|
449
|
-
} else {
|
|
450
|
-
this.logOutput(`โ
All ${testResult.total} tests passed`, 'success');
|
|
451
|
-
}
|
|
452
|
-
} else if (options.tests !== false && !deploymentResult.url) {
|
|
453
|
-
this.logOutput('โญ๏ธ Skipping tests - no deployment URL available', 'warn');
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// End audit session
|
|
457
|
-
auditor.endDeploymentAudit(deploymentId, 'success', {
|
|
458
|
-
url: deploymentResult.url,
|
|
459
|
-
duration: deploymentResult.duration
|
|
460
|
-
});
|
|
461
|
-
this.logOutput(`โ
Deployment successful: ${deploymentResult.url}`, 'success');
|
|
462
|
-
if (this.globalConfig.outputFormat !== 'minimal') {
|
|
463
|
-
console.log('\\n๐ Deployment Summary:');
|
|
464
|
-
console.log(` ๐ ID: ${deploymentId}`);
|
|
465
|
-
console.log(` ๐ Domain: ${domain}`);
|
|
466
|
-
console.log(` ๐ Environment: ${options.env}`);
|
|
467
|
-
console.log(` ๐ URL: ${deploymentResult.url}`);
|
|
468
|
-
console.log(` โฑ๏ธ Duration: ${deploymentResult.duration}s`);
|
|
469
|
-
}
|
|
470
|
-
} catch (error) {
|
|
471
|
-
this.logOutput(`โ Deployment failed: ${error.message}`, 'error');
|
|
472
|
-
process.exit(1);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Deploy multiple domains
|
|
478
|
-
*/
|
|
479
|
-
async deployMultiDomain(domains, options) {
|
|
480
|
-
try {
|
|
481
|
-
this.logOutput(`๐ Multi-domain deployment: ${domains.length} domains`, 'info');
|
|
482
|
-
const coordinationResult = await this.modules.coordinator.coordinateMultiDomainDeployment(domains, {
|
|
483
|
-
environment: options.env,
|
|
484
|
-
batchSize: parseInt(options.batchSize),
|
|
485
|
-
enableCoordination: options.coordination,
|
|
486
|
-
sharedSecrets: options.sharedSecrets,
|
|
487
|
-
resolveDependencies: options.dependencyOrder,
|
|
488
|
-
dryRun: options.dryRun
|
|
489
|
-
});
|
|
490
|
-
this.logOutput(`โ
Multi-domain deployment completed`, 'success');
|
|
491
|
-
console.log(` โ
Successful: ${coordinationResult.results.successful.length}`);
|
|
492
|
-
console.log(` โ Failed: ${coordinationResult.results.failed.length}`);
|
|
493
|
-
} catch (error) {
|
|
494
|
-
this.logOutput(`โ Multi-domain deployment failed: ${error.message}`, 'error');
|
|
495
|
-
process.exit(1);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Deploy portfolio
|
|
501
|
-
*/
|
|
502
|
-
async deployPortfolio(options) {
|
|
503
|
-
try {
|
|
504
|
-
this.logOutput('๐ Portfolio deployment', 'info');
|
|
505
|
-
|
|
506
|
-
// Discover portfolio first
|
|
507
|
-
const portfolio = await this.modules.coordinator.discoverPortfolio();
|
|
508
|
-
let domains = portfolio.domains.map(d => d.name || d.domain);
|
|
509
|
-
|
|
510
|
-
// Apply filters
|
|
511
|
-
if (options.filter) {
|
|
512
|
-
const filterRegex = new RegExp(options.filter);
|
|
513
|
-
domains = domains.filter(domain => filterRegex.test(domain));
|
|
514
|
-
}
|
|
515
|
-
if (options.exclude) {
|
|
516
|
-
const excludeRegex = new RegExp(options.exclude);
|
|
517
|
-
domains = domains.filter(domain => !excludeRegex.test(domain));
|
|
518
|
-
}
|
|
519
|
-
this.logOutput(`๐ Deploying ${domains.length} domains from portfolio`, 'info');
|
|
520
|
-
|
|
521
|
-
// Health check if requested
|
|
522
|
-
if (options.healthCheck) {
|
|
523
|
-
this.logOutput('โค๏ธ Running pre-deployment health checks...', 'info');
|
|
524
|
-
const healthResults = await this.modules.coordinator.monitorPortfolioHealth();
|
|
525
|
-
this.logOutput(`๐ Health: ${healthResults.summary.healthy}/${healthResults.summary.total} healthy`, 'info');
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// Execute portfolio deployment
|
|
529
|
-
const result = await this.modules.coordinator.coordinateMultiDomainDeployment(domains, {
|
|
530
|
-
environment: options.env,
|
|
531
|
-
rollbackThreshold: parseFloat(options.rollbackThreshold),
|
|
532
|
-
dryRun: options.dryRun
|
|
533
|
-
});
|
|
534
|
-
this.logOutput('โ
Portfolio deployment completed', 'success');
|
|
535
|
-
} catch (error) {
|
|
536
|
-
this.logOutput(`โ Portfolio deployment failed: ${error.message}`, 'error');
|
|
537
|
-
process.exit(1);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Discover domain configuration
|
|
543
|
-
*/
|
|
544
|
-
async discoverDomain(domain, options) {
|
|
545
|
-
try {
|
|
546
|
-
this.logOutput(`๐ Discovering configuration for: ${domain}`, 'info');
|
|
547
|
-
const discoveredConfig = await this.modules.domainDiscovery.discoverDomainConfig(domain, {
|
|
548
|
-
cloudflareToken: options.token,
|
|
549
|
-
useCache: options.cache,
|
|
550
|
-
updateDomainsJs: options.updateConfig
|
|
551
|
-
});
|
|
552
|
-
this.logOutput('โ
Discovery completed', 'success');
|
|
553
|
-
if (this.globalConfig.outputFormat !== 'minimal') {
|
|
554
|
-
console.log('\\n๐ Discovered Configuration:');
|
|
555
|
-
console.log(JSON.stringify(discoveredConfig, null, 2));
|
|
556
|
-
}
|
|
557
|
-
} catch (error) {
|
|
558
|
-
this.logOutput(`โ Discovery failed: ${error.message}`, 'error');
|
|
559
|
-
process.exit(1);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/**
|
|
564
|
-
* Validate domain
|
|
565
|
-
*/
|
|
566
|
-
async validateDomain(domain, options) {
|
|
567
|
-
try {
|
|
568
|
-
this.logOutput(`๐ Validating: ${domain}`, 'info');
|
|
569
|
-
const validation = await this.modules.validator.validateDeploymentReadiness(domain, {
|
|
570
|
-
environment: options.env,
|
|
571
|
-
validationLevel: options.level
|
|
572
|
-
});
|
|
573
|
-
if (validation.valid) {
|
|
574
|
-
this.logOutput('โ
Validation passed', 'success');
|
|
575
|
-
} else {
|
|
576
|
-
this.logOutput('โ Validation failed:', 'error');
|
|
577
|
-
validation.errors.forEach(error => this.logOutput(` - ${error}`, 'error'));
|
|
578
|
-
if (validation.warnings?.length > 0) {
|
|
579
|
-
this.logOutput('โ ๏ธ Warnings:', 'warn');
|
|
580
|
-
validation.warnings.forEach(warning => this.logOutput(` - ${warning}`, 'warn'));
|
|
581
|
-
}
|
|
582
|
-
process.exit(1);
|
|
583
|
-
}
|
|
584
|
-
} catch (error) {
|
|
585
|
-
this.logOutput(`โ Validation error: ${error.message}`, 'error');
|
|
586
|
-
process.exit(1);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* Test domain
|
|
592
|
-
*/
|
|
593
|
-
async testDomain(domain, options) {
|
|
594
|
-
try {
|
|
595
|
-
this.logOutput(`๐งช Testing: ${domain}`, 'info');
|
|
596
|
-
const url = options.url || this.getDomainUrl(domain);
|
|
597
|
-
const testSuites = options.suites.split(',');
|
|
598
|
-
const testResult = await this.modules.productionTester.runFullTestSuite(options.env || 'production');
|
|
599
|
-
if (testResult.failed === 0) {
|
|
600
|
-
this.logOutput(`โ
All ${testResult.total} tests passed`, 'success');
|
|
601
|
-
} else {
|
|
602
|
-
this.logOutput(`โ ${testResult.failed}/${testResult.total} tests failed`, 'error');
|
|
603
|
-
process.exit(1);
|
|
604
|
-
}
|
|
605
|
-
} catch (error) {
|
|
606
|
-
this.logOutput(`โ Testing failed: ${error.message}`, 'error');
|
|
607
|
-
process.exit(1);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* Generate secrets for domain
|
|
613
|
-
*/
|
|
614
|
-
async generateSecrets(domain, options) {
|
|
615
|
-
try {
|
|
616
|
-
this.logOutput(`๐ Generating secrets for: ${domain}`, 'info');
|
|
617
|
-
const formats = options.formats.split(',');
|
|
618
|
-
const secretResult = await this.modules.secretManager.generateDomainSpecificSecrets(domain, options.env, {
|
|
619
|
-
formats,
|
|
620
|
-
coordinate: options.coordinate,
|
|
621
|
-
deployToCloudflare: options.deploy
|
|
622
|
-
});
|
|
623
|
-
this.logOutput(`โ
Generated ${Object.keys(secretResult.secrets).length} secrets`, 'success');
|
|
624
|
-
if (this.globalConfig.outputFormat !== 'minimal') {
|
|
625
|
-
console.log('\\n๐ Generated Secrets:');
|
|
626
|
-
Object.keys(secretResult.secrets).forEach(key => {
|
|
627
|
-
console.log(` - ${key}: ${secretResult.secrets[key].substring(0, 8)}...`);
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
} catch (error) {
|
|
631
|
-
this.logOutput(`โ Secret generation failed: ${error.message}`, 'error');
|
|
632
|
-
process.exit(1);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
/**
|
|
637
|
-
* Monitor portfolio health
|
|
638
|
-
*/
|
|
639
|
-
async monitorPortfolio(options) {
|
|
640
|
-
try {
|
|
641
|
-
this.logOutput('๐ Starting portfolio monitoring...', 'info');
|
|
642
|
-
if (options.continuous) {
|
|
643
|
-
const interval = parseInt(options.interval);
|
|
644
|
-
const runHealthCheck = async () => {
|
|
645
|
-
const healthResults = await this.modules.coordinator.monitorPortfolioHealth();
|
|
646
|
-
this.logOutput(`๐ Health: ${healthResults.summary.healthy}/${healthResults.summary.total} healthy`, 'info');
|
|
647
|
-
if (healthResults.summary.unhealthy > 0 && options.alertWebhook) {
|
|
648
|
-
// Send alert (implementation would send to webhook)
|
|
649
|
-
this.logOutput(`๐จ Alert: ${healthResults.summary.unhealthy} domains unhealthy`, 'warn');
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
|
|
653
|
-
// Initial check
|
|
654
|
-
await runHealthCheck();
|
|
655
|
-
|
|
656
|
-
// Continuous monitoring
|
|
657
|
-
setInterval(runHealthCheck, interval);
|
|
658
|
-
this.logOutput(`๐ Continuous monitoring enabled (interval: ${interval}ms)`, 'info');
|
|
659
|
-
} else {
|
|
660
|
-
// One-time health check
|
|
661
|
-
const healthResults = await this.modules.coordinator.monitorPortfolioHealth();
|
|
662
|
-
this.logOutput('โ
Portfolio health check completed', 'success');
|
|
663
|
-
console.log(` ๐ Total: ${healthResults.summary.total}`);
|
|
664
|
-
console.log(` โ
Healthy: ${healthResults.summary.healthy}`);
|
|
665
|
-
console.log(` โ Unhealthy: ${healthResults.summary.unhealthy}`);
|
|
666
|
-
console.log(` ๐ฅ Errors: ${healthResults.summary.errors}`);
|
|
667
|
-
}
|
|
668
|
-
} catch (error) {
|
|
669
|
-
this.logOutput(`โ Monitoring failed: ${error.message}`, 'error');
|
|
670
|
-
process.exit(1);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
/**
|
|
675
|
-
* Get domain URL for testing
|
|
676
|
-
*/
|
|
677
|
-
getDomainUrl(domain) {
|
|
678
|
-
// Generate standard URL pattern
|
|
679
|
-
const domainKey = domain.replace(/\\./g, '');
|
|
680
|
-
return `https://${domainKey}-data-service.tamylatrading.workers.dev`;
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
* Generate deployment ID
|
|
685
|
-
*/
|
|
686
|
-
generateDeploymentId() {
|
|
687
|
-
const timestamp = Date.now().toString(36);
|
|
688
|
-
const random = Math.random().toString(36).substr(2, 9);
|
|
689
|
-
return `cli_${timestamp}_${random}`;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* Log output with different levels
|
|
694
|
-
*/
|
|
695
|
-
logOutput(message, level = 'info') {
|
|
696
|
-
if (program.opts().quiet && level !== 'error') return;
|
|
697
|
-
const colors = {
|
|
698
|
-
info: '\\x1b[36m',
|
|
699
|
-
// Cyan
|
|
700
|
-
success: '\\x1b[32m',
|
|
701
|
-
// Green
|
|
702
|
-
warn: '\\x1b[33m',
|
|
703
|
-
// Yellow
|
|
704
|
-
error: '\\x1b[31m',
|
|
705
|
-
// Red
|
|
706
|
-
reset: '\\x1b[0m' // Reset
|
|
707
|
-
};
|
|
708
|
-
const useColor = !program.opts().noColor;
|
|
709
|
-
const colorCode = useColor ? colors[level] || colors.info : '';
|
|
710
|
-
const resetCode = useColor ? colors.reset : '';
|
|
711
|
-
console.log(`${colorCode}${message}${resetCode}`);
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
/**
|
|
715
|
-
* Placeholder implementations for remaining methods
|
|
716
|
-
*/
|
|
717
|
-
async discoverPortfolio(options) {
|
|
718
|
-
this.logOutput('๐ Portfolio discovery not yet implemented', 'warn');
|
|
719
|
-
}
|
|
720
|
-
async validatePortfolio(options) {
|
|
721
|
-
this.logOutput('๐ Portfolio validation not yet implemented', 'warn');
|
|
722
|
-
}
|
|
723
|
-
async testPortfolio(options) {
|
|
724
|
-
this.logOutput('๐งช Portfolio testing not yet implemented', 'warn');
|
|
725
|
-
}
|
|
726
|
-
async migrateDomain(domain, options) {
|
|
727
|
-
this.logOutput(`๐๏ธ Database migration for ${domain} not yet implemented`, 'warn');
|
|
728
|
-
}
|
|
729
|
-
async migrateAll(options) {
|
|
730
|
-
this.logOutput('๐๏ธ Bulk database migration not yet implemented', 'warn');
|
|
731
|
-
}
|
|
732
|
-
async coordinateSecrets(domains, options) {
|
|
733
|
-
this.logOutput(`๐ Secret coordination for ${domains.length} domains not yet implemented`, 'warn');
|
|
734
|
-
}
|
|
735
|
-
async rollbackDomain(domain, options) {
|
|
736
|
-
this.logOutput(`๐ Domain rollback for ${domain} not yet implemented`, 'warn');
|
|
737
|
-
}
|
|
738
|
-
async rollbackPortfolio(options) {
|
|
739
|
-
this.logOutput('๐ Portfolio rollback not yet implemented', 'warn');
|
|
740
|
-
}
|
|
741
|
-
async getStatus(domain, options) {
|
|
742
|
-
this.logOutput(`๐ Status check for ${domain || 'portfolio'} not yet implemented`, 'warn');
|
|
743
|
-
}
|
|
744
|
-
async auditDomain(domain, options) {
|
|
745
|
-
this.logOutput(`๐ Audit report for ${domain} not yet implemented`, 'warn');
|
|
746
|
-
}
|
|
747
|
-
async auditPortfolio(options) {
|
|
748
|
-
this.logOutput('๐ Portfolio audit not yet implemented', 'warn');
|
|
749
|
-
}
|
|
750
|
-
async manageConfigCache(domain, options) {
|
|
751
|
-
this.logOutput(`โ๏ธ Config cache management for ${domain} not yet implemented`, 'warn');
|
|
752
|
-
}
|
|
753
|
-
async listDomains(options) {
|
|
754
|
-
this.logOutput('๐ Discovering available domains...', 'info');
|
|
755
|
-
const domains = await this.discoverAvailableDomains();
|
|
756
|
-
if (domains.length === 0) {
|
|
757
|
-
this.logOutput('โ No domains found in services directory', 'error');
|
|
758
|
-
this.logOutput('๐ก Create a service first using: node bin/service-management/init-service.js', 'info');
|
|
759
|
-
return;
|
|
760
|
-
}
|
|
761
|
-
if (options.format === 'json') {
|
|
762
|
-
console.log(JSON.stringify({
|
|
763
|
-
domains,
|
|
764
|
-
count: domains.length
|
|
765
|
-
}, null, 2));
|
|
766
|
-
} else if (options.format === 'yaml') {
|
|
767
|
-
console.log('domains:');
|
|
768
|
-
domains.forEach(domain => console.log(` - ${domain}`));
|
|
769
|
-
console.log(`count: ${domains.length}`);
|
|
770
|
-
} else {
|
|
771
|
-
// Table format (default)
|
|
772
|
-
this.logOutput(`๐ Found ${domains.length} domain(s):`, 'success');
|
|
773
|
-
console.log('');
|
|
774
|
-
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
775
|
-
console.log('โ Domain โ');
|
|
776
|
-
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค');
|
|
777
|
-
domains.forEach(domain => {
|
|
778
|
-
console.log(`โ ${domain.padEnd(35)} โ`);
|
|
779
|
-
});
|
|
780
|
-
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
/**
|
|
785
|
-
* Discover available domains from services directory
|
|
786
|
-
*/
|
|
787
|
-
async discoverAvailableDomains() {
|
|
788
|
-
const domains = new Set();
|
|
789
|
-
try {
|
|
790
|
-
const servicesPath = join(process.cwd(), 'services');
|
|
791
|
-
const fs = await import('fs/promises');
|
|
792
|
-
|
|
793
|
-
// Check if services directory exists
|
|
794
|
-
try {
|
|
795
|
-
await fs.access(servicesPath);
|
|
796
|
-
} catch {
|
|
797
|
-
this.logOutput('โ ๏ธ No services directory found', 'warn');
|
|
798
|
-
return [];
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
// Read service directories
|
|
802
|
-
const serviceDirs = await fs.readdir(servicesPath, {
|
|
803
|
-
withFileTypes: true
|
|
804
|
-
});
|
|
805
|
-
for (const dir of serviceDirs) {
|
|
806
|
-
if (!dir.isDirectory()) continue;
|
|
807
|
-
const servicePath = join(servicesPath, dir.name);
|
|
808
|
-
const wranglerPath = join(servicePath, 'wrangler.toml');
|
|
809
|
-
try {
|
|
810
|
-
// Check if wrangler.toml exists
|
|
811
|
-
await fs.access(wranglerPath);
|
|
812
|
-
|
|
813
|
-
// Read and parse wrangler.toml
|
|
814
|
-
const content = await fs.readFile(wranglerPath, 'utf-8');
|
|
815
|
-
const domainMatch = content.match(/DOMAIN_NAME\s*=\s*["']([^"']+)["']/);
|
|
816
|
-
if (domainMatch) {
|
|
817
|
-
domains.add(domainMatch[1]);
|
|
818
|
-
}
|
|
819
|
-
} catch {
|
|
820
|
-
// Skip services without wrangler.toml or domain config
|
|
821
|
-
continue;
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
} catch (error) {
|
|
825
|
-
this.logOutput(`โ Error discovering domains: ${error.message}`, 'error');
|
|
826
|
-
}
|
|
827
|
-
return Array.from(domains).sort();
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
/**
|
|
831
|
-
* Interactively select a domain from available options
|
|
832
|
-
*/
|
|
833
|
-
async selectDomainInteractively() {
|
|
834
|
-
this.logOutput('๐ Discovering available domains...', 'info');
|
|
835
|
-
const domains = await this.discoverAvailableDomains();
|
|
836
|
-
if (domains.length === 0) {
|
|
837
|
-
this.logOutput('โ No domains found in services. Please create a service first or specify domain manually.', 'error');
|
|
838
|
-
process.exit(1);
|
|
839
|
-
}
|
|
840
|
-
if (domains.length === 1) {
|
|
841
|
-
const domain = domains[0];
|
|
842
|
-
this.logOutput(`โ
Only one domain found: ${domain}`, 'success');
|
|
843
|
-
return domain;
|
|
844
|
-
}
|
|
845
|
-
this.logOutput(`๐ Found ${domains.length} available domains:`, 'info');
|
|
846
|
-
domains.forEach((domain, index) => {
|
|
847
|
-
console.log(` ${index + 1}. ${domain}`);
|
|
848
|
-
});
|
|
849
|
-
const choice = await askChoice('Select a domain to deploy:', domains);
|
|
850
|
-
const selectedDomain = domains[choice];
|
|
851
|
-
this.logOutput(`โ
Selected domain: ${selectedDomain}`, 'success');
|
|
852
|
-
return selectedDomain;
|
|
853
|
-
}
|
|
854
|
-
async cleanupDeployments(options) {
|
|
855
|
-
this.logOutput('๐งน Deployment cleanup not yet implemented', 'warn');
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
// Initialize and run CLI
|
|
860
|
-
const cli = new EnterpriseDeploymentCLI();
|
|
861
|
-
|
|
862
|
-
// Set up commands first (before heavy module initialization)
|
|
863
|
-
cli.setupCommands();
|
|
864
|
-
|
|
865
|
-
// Parse command line arguments
|
|
866
|
-
program.parse();
|
|
867
|
-
|
|
868
|
-
// Handle unhandled errors
|
|
869
|
-
process.on('uncaughtException', error => {
|
|
870
|
-
console.error('โ Uncaught Exception:', error.message);
|
|
871
|
-
process.exit(1);
|
|
872
|
-
});
|
|
873
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
874
|
-
console.error('โ Unhandled Rejection at:', promise, 'reason:', reason);
|
|
875
|
-
process.exit(1);
|
|
876
|
-
});
|
|
877
|
-
export { EnterpriseDeploymentCLI };
|