@tamyla/clodo-framework 4.0.13 → 4.0.14

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +7 -0
  3. package/dist/cli/commands/create.js +2 -1
  4. package/dist/middleware/Composer.js +38 -0
  5. package/dist/middleware/Registry.js +14 -0
  6. package/dist/middleware/index.js +3 -0
  7. package/dist/middleware/shared/basicAuth.js +21 -0
  8. package/dist/middleware/shared/cors.js +28 -0
  9. package/dist/middleware/shared/index.js +3 -0
  10. package/dist/middleware/shared/logging.js +14 -0
  11. package/dist/service-management/GenerationEngine.js +13 -2
  12. package/dist/service-management/ServiceOrchestrator.js +6 -2
  13. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +156 -10
  14. package/dist/service-management/generators/code/WorkerIndexGenerator.js +75 -9
  15. package/dist/simple-api.js +32 -1
  16. package/docs/MIDDLEWARE_MIGRATION_SUMMARY.md +121 -0
  17. package/package.json +4 -1
  18. package/scripts/DEPLOY_COMMAND_NEW.js +128 -0
  19. package/scripts/README-automated-testing-suite.md +356 -0
  20. package/scripts/README-test-clodo-deployment.md +157 -0
  21. package/scripts/README.md +50 -0
  22. package/scripts/analyze-imports.ps1 +104 -0
  23. package/scripts/analyze-mixed-code.js +163 -0
  24. package/scripts/analyze-mixed-rationale.js +149 -0
  25. package/scripts/automated-testing-suite.js +776 -0
  26. package/scripts/deployment/README.md +31 -0
  27. package/scripts/deployment/deploy-domain.ps1 +449 -0
  28. package/scripts/deployment/deploy-staging.js +120 -0
  29. package/scripts/deployment/validate-staging.js +166 -0
  30. package/scripts/diagnose-imports.js +362 -0
  31. package/scripts/framework-diagnostic.js +368 -0
  32. package/scripts/migration/migrate-middleware-legacy-to-contract.js +47 -0
  33. package/scripts/post-publish-test.js +663 -0
  34. package/scripts/scan-worker-issues.js +52 -0
  35. package/scripts/service-management/README.md +27 -0
  36. package/scripts/service-management/setup-interactive.ps1 +693 -0
  37. package/scripts/test-clodo-deployment.js +588 -0
  38. package/scripts/test-downstream-install.js +237 -0
  39. package/scripts/test-local-package.ps1 +126 -0
  40. package/scripts/test-local-package.sh +166 -0
  41. package/scripts/test-package.js +339 -0
  42. package/scripts/testing/README.md +49 -0
  43. package/scripts/testing/test-first.ps1 +0 -0
  44. package/scripts/testing/test-first50.ps1 +0 -0
  45. package/scripts/testing/test.ps1 +0 -0
  46. package/scripts/utilities/README.md +61 -0
  47. package/scripts/utilities/check-bin.js +8 -0
  48. package/scripts/utilities/check-bundle.js +23 -0
  49. package/scripts/utilities/check-dist-imports.js +65 -0
  50. package/scripts/utilities/check-import-paths.js +191 -0
  51. package/scripts/utilities/cleanup-cli.js +159 -0
  52. package/scripts/utilities/deployment-helpers.ps1 +199 -0
  53. package/scripts/utilities/fix-dist-imports.js +135 -0
  54. package/scripts/utilities/generate-secrets.js +159 -0
  55. package/scripts/utilities/safe-push.ps1 +51 -0
  56. package/scripts/utilities/setup-helpers.ps1 +206 -0
  57. package/scripts/utilities/test-packaged-artifact.js +92 -0
  58. package/scripts/utilities/validate-dist-imports.js +189 -0
  59. package/scripts/utilities/validate-schema.js +102 -0
  60. package/scripts/verify-exports.js +193 -0
  61. package/scripts/verify-worker-safety.js +73 -0
  62. package/types/middleware.d.ts +1 -0
@@ -0,0 +1,31 @@
1
+ # Deployment Scripts
2
+
3
+ Scripts for deploying Clodo Framework services to various environments and platforms.
4
+
5
+ ## Scripts
6
+
7
+ ### deploy-domain.ps1
8
+ Deploy services to specific domains with comprehensive validation and testing.
9
+
10
+ **Features:**
11
+ - Domain-specific deployment configuration
12
+ - Pre-deployment validation
13
+ - Automated testing (optional)
14
+ - Environment-specific settings
15
+ - Rollback capabilities
16
+
17
+ **Usage:**
18
+ ```powershell
19
+ .\scripts\deployment\deploy-domain.ps1 -DomainName api.example.com -ServiceName my-api -Environment production
20
+ ```
21
+
22
+ **Parameters:**
23
+ - `DomainName` - Target domain for deployment (required)
24
+ - `ServiceName` - Name of the service to deploy
25
+ - `Environment` - Target environment (development, staging, production)
26
+ - `SkipTests` - Skip automated testing
27
+ - `SkipValidation` - Skip pre-deployment validation
28
+ - `DryRun` - Show what would be deployed without actually deploying
29
+ - `ConfigPath` - Path to domain configuration file
30
+ - `WranglerPath` - Path to wrangler configuration file
31
+ - `PackagePath` - Path to package.json file
@@ -0,0 +1,449 @@
1
+ param(
2
+ [Parameter(Mandatory=$true)]
3
+ [string]$DomainName,
4
+
5
+ [Parameter(Mandatory=$false)]
6
+ [string]$ServiceName = "generic-service",
7
+
8
+ [Parameter(Mandatory=$false)]
9
+ [ValidateSet("development", "staging", "production")]
10
+ [string]$Environment = "staging",
11
+
12
+ [Parameter(Mandatory=$false)]
13
+ [switch]$SkipTests,
14
+
15
+ [Parameter(Mandatory=$false)]
16
+ [switch]$SkipValidation,
17
+
18
+ [Parameter(Mandatory=$false)]
19
+ [switch]$DryRun,
20
+
21
+ [Parameter(Mandatory=$false)]
22
+ [string]$ConfigPath = ".\src\config\domains.js",
23
+
24
+ [Parameter(Mandatory=$false)]
25
+ [string]$WranglerPath = ".\wrangler.toml",
26
+
27
+ [Parameter(Mandatory=$false)]
28
+ [string]$PackagePath = ".\package.json"
29
+ )
30
+
31
+ # Import Clodo Framework utilities
32
+ . "$PSScriptRoot\..\utilities\deployment-helpers.ps1"
33
+
34
+ # Configuration
35
+ $ErrorActionPreference = "Stop"
36
+ $ProgressPreference = "SilentlyContinue"
37
+
38
+ # Colors for output
39
+ $Green = "Green"
40
+ $Yellow = "Yellow"
41
+ $Red = "Red"
42
+ $Cyan = "Cyan"
43
+ $White = "White"
44
+
45
+ function Write-Step {
46
+ param([string]$Message)
47
+ Write-Host "==> $Message" -ForegroundColor $Cyan
48
+ }
49
+
50
+ function Write-Success {
51
+ param([string]$Message)
52
+ Write-Host "āœ“ $Message" -ForegroundColor $Green
53
+ }
54
+
55
+ function Write-Warning {
56
+ param([string]$Message)
57
+ Write-Host "⚠ $Message" -ForegroundColor $Yellow
58
+ }
59
+
60
+ function Write-Error-Message {
61
+ param([string]$Message)
62
+ Write-Host "āœ— $Message" -ForegroundColor $Red
63
+ }
64
+
65
+ function Exit-WithError {
66
+ param([string]$Message, [int]$ExitCode = 1)
67
+ Write-Error-Message $Message
68
+ exit $ExitCode
69
+ }
70
+
71
+ # Main deployment function
72
+ function Invoke-ServiceDeployment {
73
+ Write-Step "Starting deployment of $ServiceName for domain $DomainName ($Environment)"
74
+
75
+ # Validate prerequisites
76
+ if (-not $SkipValidation) {
77
+ Test-Prerequisites
78
+ }
79
+
80
+ # Load and validate domain configuration
81
+ $domainConfig = Get-DomainConfig -DomainName $DomainName -ConfigPath $ConfigPath
82
+ if (-not $domainConfig) {
83
+ Exit-WithError "Domain configuration not found for: $DomainName"
84
+ }
85
+
86
+ Write-Success "Domain configuration loaded: $($domainConfig.displayName)"
87
+
88
+ # Validate service configuration
89
+ if (-not $SkipValidation) {
90
+ Test-ServiceConfiguration -DomainConfig $domainConfig -ServiceName $ServiceName
91
+ }
92
+
93
+ # Prepare deployment environment
94
+ $deployConfig = New-DeploymentConfig -DomainConfig $domainConfig -Environment $Environment -ServiceName $ServiceName
95
+
96
+ # Generate wrangler configuration
97
+ Write-Step "Generating wrangler configuration"
98
+ $wranglerConfig = New-WranglerConfig -DeployConfig $deployConfig -TemplatePath $WranglerPath
99
+
100
+ if ($DryRun) {
101
+ Write-Warning "DRY RUN: Would write wrangler config to $($wranglerConfig.Path)"
102
+ Write-Host ($wranglerConfig.Content | ConvertTo-Json -Depth 10) -ForegroundColor $White
103
+ } else {
104
+ $wranglerConfig.Content | Out-File -FilePath $wranglerConfig.Path -Encoding UTF8
105
+ Write-Success "Wrangler configuration generated"
106
+ }
107
+
108
+ # Install dependencies
109
+ if (-not $DryRun -and (Test-Path $PackagePath)) {
110
+ Write-Step "Installing dependencies"
111
+ Invoke-Command "npm install" -ErrorAction Stop
112
+ Write-Success "Dependencies installed"
113
+ }
114
+
115
+ # Run tests
116
+ if (-not $SkipTests -and -not $DryRun) {
117
+ Write-Step "Running tests"
118
+ try {
119
+ Invoke-Command "npm test" -ErrorAction Stop
120
+ Write-Success "Tests passed"
121
+ } catch {
122
+ Write-Warning "Tests failed, but continuing with deployment"
123
+ }
124
+ }
125
+
126
+ # Create/update databases
127
+ if (-not $DryRun) {
128
+ Write-Step "Setting up databases"
129
+ Initialize-ServiceDatabases -DeployConfig $deployConfig
130
+ Write-Success "Databases configured"
131
+ }
132
+
133
+ # Deploy to Cloudflare
134
+ if (-not $DryRun) {
135
+ Write-Step "Deploying to Cloudflare Workers"
136
+ $deployResult = Publish-CloudflareWorker -DeployConfig $deployConfig
137
+
138
+ if ($deployResult.Success) {
139
+ Write-Success "Deployment completed successfully"
140
+ Write-Host "Worker URL: $($deployResult.Url)" -ForegroundColor $Green
141
+ Write-Host "Deployment ID: $($deployResult.DeploymentId)" -ForegroundColor $White
142
+ } else {
143
+ Exit-WithError "Deployment failed: $($deployResult.Error)"
144
+ }
145
+ } else {
146
+ Write-Warning "DRY RUN: Would deploy to Cloudflare Workers"
147
+ }
148
+
149
+ # Run post-deployment validation
150
+ if (-not $DryRun -and -not $SkipValidation) {
151
+ Write-Step "Running post-deployment validation"
152
+ $validationResult = Test-DeploymentHealth -DeployConfig $deployConfig
153
+
154
+ if ($validationResult.Success) {
155
+ Write-Success "Post-deployment validation passed"
156
+ } else {
157
+ Write-Warning "Post-deployment validation failed: $($validationResult.Error)"
158
+ }
159
+ }
160
+
161
+ Write-Step "Deployment process completed"
162
+ if ($DryRun) {
163
+ Write-Warning "This was a dry run - no actual deployment occurred"
164
+ }
165
+ }
166
+
167
+ # Validate prerequisites
168
+ function Test-Prerequisites {
169
+ Write-Step "Validating prerequisites"
170
+
171
+ # Check Node.js
172
+ try {
173
+ $nodeVersion = & node --version 2>$null
174
+ Write-Success "Node.js found: $nodeVersion"
175
+ } catch {
176
+ Exit-WithError "Node.js is not installed or not in PATH"
177
+ }
178
+
179
+ # Check npm
180
+ try {
181
+ $npmVersion = & npm --version 2>$null
182
+ Write-Success "npm found: v$npmVersion"
183
+ } catch {
184
+ Exit-WithError "npm is not installed or not in PATH"
185
+ }
186
+
187
+ # Check wrangler
188
+ try {
189
+ $wranglerVersion = & npx wrangler --version 2>$null
190
+ Write-Success "Wrangler found: $wranglerVersion"
191
+ } catch {
192
+ Exit-WithError "Wrangler is not installed. Run: npm install -g wrangler"
193
+ }
194
+
195
+ # Check PowerShell version
196
+ if ($PSVersionTable.PSVersion.Major -lt 5) {
197
+ Exit-WithError "PowerShell 5.0 or higher is required"
198
+ }
199
+
200
+ Write-Success "Prerequisites validation completed"
201
+ }
202
+
203
+ # Load domain configuration
204
+ function Get-DomainConfig {
205
+ param([string]$DomainName, [string]$ConfigPath)
206
+
207
+ if (-not (Test-Path $ConfigPath)) {
208
+ return $null
209
+ }
210
+
211
+ try {
212
+ # This is a simplified version - in practice, you'd parse the JS config file
213
+ # For now, we'll assume the config is available as a PowerShell object
214
+ # In a real implementation, you might use Node.js to parse the JS file
215
+
216
+ Write-Warning "Note: Domain config parsing from JS files requires Node.js integration"
217
+ Write-Warning "For now, using mock configuration"
218
+
219
+ # Mock domain config - replace with actual parsing logic
220
+ return @{
221
+ name = $DomainName
222
+ displayName = "$DomainName Service"
223
+ accountId = "mock-account-id"
224
+ zoneId = "mock-zone-id"
225
+ domains = @{
226
+ production = "api.$DomainName.com"
227
+ staging = "staging-api.$DomainName.com"
228
+ development = "dev-api.$DomainName.com"
229
+ }
230
+ databases = @(
231
+ @{
232
+ name = "${DomainName}-db"
233
+ type = "d1"
234
+ }
235
+ )
236
+ features = @{
237
+ authentication = $true
238
+ logging = $true
239
+ monitoring = ($Environment -eq "production")
240
+ }
241
+ }
242
+ } catch {
243
+ Write-Error-Message "Failed to load domain configuration: $_"
244
+ return $null
245
+ }
246
+ }
247
+
248
+ # Validate service configuration
249
+ function Test-ServiceConfiguration {
250
+ param($DomainConfig, [string]$ServiceName)
251
+
252
+ # Check if service has required configuration
253
+ if (-not $DomainConfig.databases -and -not $DomainConfig.services) {
254
+ Write-Warning "No databases or services configured for $ServiceName"
255
+ }
256
+
257
+ # Validate environment-specific settings
258
+ if (-not $DomainConfig.domains.$Environment) {
259
+ Write-Warning "No domain configured for environment: $Environment"
260
+ }
261
+
262
+ Write-Success "Service configuration validated"
263
+ }
264
+
265
+ # Create deployment configuration
266
+ function New-DeploymentConfig {
267
+ param($DomainConfig, [string]$Environment, [string]$ServiceName)
268
+
269
+ return @{
270
+ domain = $DomainConfig
271
+ environment = $Environment
272
+ serviceName = $ServiceName
273
+ timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
274
+ deploymentId = [Guid]::NewGuid().ToString()
275
+ workerName = "$ServiceName-$Environment-$DomainName"
276
+ domainUrl = $DomainConfig.domains.$Environment
277
+ }
278
+ }
279
+
280
+ # Generate wrangler configuration
281
+ function New-WranglerConfig {
282
+ param($DeployConfig, [string]$TemplatePath)
283
+
284
+ $config = @"
285
+ name = "$($DeployConfig.workerName)"
286
+ main = "src/worker/index.js"
287
+ compatibility_date = "$(Get-Date -Format "yyyy-MM-dd")"
288
+
289
+ [env.$($DeployConfig.environment)]
290
+ "@
291
+
292
+ # Add database bindings
293
+ if ($DeployConfig.domain.databases) {
294
+ foreach ($db in $DeployConfig.domain.databases) {
295
+ $config += @"
296
+
297
+ [[d1_databases]]
298
+ binding = "$($db.name)"
299
+ database_name = "$($db.name)"
300
+ database_id = "$($db.id)"
301
+ "@
302
+ }
303
+ }
304
+
305
+ # Add environment variables
306
+ $config += @"
307
+
308
+ [vars]
309
+ DOMAIN_NAME = "$($DeployConfig.domain.name)"
310
+ ENVIRONMENT = "$($DeployConfig.environment)"
311
+ SERVICE_NAME = "$($DeployConfig.serviceName)"
312
+ DEPLOYMENT_ID = "$($DeployConfig.deploymentId)"
313
+ "@
314
+
315
+ # Add domain routing if configured
316
+ if ($DeployConfig.domainUrl) {
317
+ $config += @"
318
+
319
+ [[routes]]
320
+ pattern = "$($DeployConfig.domainUrl)/*"
321
+ zone_id = "$($DeployConfig.domain.zoneId)"
322
+ "@
323
+ }
324
+
325
+ return @{
326
+ Path = $TemplatePath
327
+ Content = $config
328
+ }
329
+ }
330
+
331
+ # Initialize service databases
332
+ function Initialize-ServiceDatabases {
333
+ param($DeployConfig)
334
+
335
+ if (-not $DeployConfig.domain.databases) {
336
+ Write-Warning "No databases configured for service"
337
+ return
338
+ }
339
+
340
+ foreach ($db in $DeployConfig.domain.databases) {
341
+ Write-Step "Setting up database: $($db.name)"
342
+
343
+ try {
344
+ # Create database if it doesn't exist
345
+ $createResult = Invoke-Command "npx wrangler d1 create $($db.name)" -ErrorAction Stop
346
+
347
+ if ($createResult -match "database_id = (.+)") {
348
+ $db.id = $matches[1]
349
+ Write-Success "Database created: $($db.name)"
350
+ } else {
351
+ Write-Warning "Database may already exist: $($db.name)"
352
+ }
353
+
354
+ # Run migrations if they exist
355
+ $migrationPath = ".\migrations"
356
+ if (Test-Path $migrationPath) {
357
+ Write-Step "Running database migrations"
358
+ Invoke-Command "npx wrangler d1 migrations apply $($db.name) --local" -ErrorAction Stop
359
+ Write-Success "Migrations applied"
360
+ }
361
+
362
+ } catch {
363
+ Write-Error-Message "Failed to setup database $($db.name): $_"
364
+ # Continue with other databases
365
+ }
366
+ }
367
+ }
368
+
369
+ # Deploy to Cloudflare Workers
370
+ function Publish-CloudflareWorker {
371
+ param($DeployConfig)
372
+
373
+ try {
374
+ Write-Step "Publishing worker: $($DeployConfig.workerName)"
375
+
376
+ $deployCommand = "npx wrangler deploy --env $($DeployConfig.environment)"
377
+ $result = Invoke-Command $deployCommand -ErrorAction Stop
378
+
379
+ # Parse deployment result
380
+ $urlMatch = $result | Select-String -Pattern "https://(.+)\.workers\.dev"
381
+ $deploymentUrl = if ($urlMatch) { $urlMatch.Matches[0].Value } else { $null }
382
+
383
+ return @{
384
+ Success = $true
385
+ Url = $deploymentUrl
386
+ DeploymentId = $DeployConfig.deploymentId
387
+ Output = $result
388
+ }
389
+ } catch {
390
+ return @{
391
+ Success = $false
392
+ Error = $_.Exception.Message
393
+ Output = $result
394
+ }
395
+ }
396
+ }
397
+
398
+ # Test deployment health
399
+ function Test-DeploymentHealth {
400
+ param($DeployConfig)
401
+
402
+ if (-not $DeployConfig.domainUrl) {
403
+ return @{ Success = $true; Message = "No domain URL configured for health check" }
404
+ }
405
+
406
+ try {
407
+ Write-Step "Testing deployment health at: $($DeployConfig.domainUrl)"
408
+
409
+ # Simple health check - try to access the worker
410
+ $response = Invoke-WebRequest -Uri "$($DeployConfig.domainUrl)/health" -TimeoutSec 30 -ErrorAction Stop
411
+
412
+ if ($response.StatusCode -eq 200) {
413
+ Write-Success "Health check passed"
414
+ return @{ Success = $true }
415
+ } else {
416
+ return @{ Success = $false; Error = "Health check returned status $($response.StatusCode)" }
417
+ }
418
+ } catch {
419
+ return @{ Success = $false; Error = "Health check failed: $_" }
420
+ }
421
+ }
422
+
423
+ # Utility function to run commands
424
+ function Invoke-Command {
425
+ param([string]$Command, [switch]$ErrorAction)
426
+
427
+ Write-Host "Running: $Command" -ForegroundColor $White
428
+
429
+ try {
430
+ $output = Invoke-Expression $Command 2>&1
431
+ if ($LASTEXITCODE -ne 0 -and $ErrorAction) {
432
+ throw "Command failed with exit code $LASTEXITCODE"
433
+ }
434
+ return $output
435
+ } catch {
436
+ if ($ErrorAction) {
437
+ throw
438
+ }
439
+ Write-Error-Message "Command failed: $_"
440
+ return $null
441
+ }
442
+ }
443
+
444
+ # Run main deployment
445
+ try {
446
+ Invoke-ServiceDeployment
447
+ } catch {
448
+ Exit-WithError "Deployment failed: $_"
449
+ }
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Staging Deployment Script
5
+ *
6
+ * This script sets up staging environment variables and deploys to staging.
7
+ * Make sure to copy .env.staging.example to .env.staging and fill in your credentials.
8
+ */
9
+
10
+ import { execSync } from 'child_process';
11
+ import { readFileSync, existsSync } from 'fs';
12
+ import { resolve } from 'path';
13
+ import chalk from 'chalk';
14
+
15
+ const ENV_FILE = '.env.staging';
16
+ const CONFIG_FILE = 'config/staging-deployment.json';
17
+
18
+ console.log(chalk.blue('šŸš€ Starting Staging Deployment...\n'));
19
+
20
+ // Check if staging environment file exists
21
+ if (!existsSync(ENV_FILE)) {
22
+ console.error(chalk.red(`āŒ Error: ${ENV_FILE} not found!`));
23
+ console.log(chalk.yellow('Please copy .env.staging.example to .env.staging and fill in your credentials.'));
24
+ process.exit(1);
25
+ }
26
+
27
+ // Load environment variables from staging file
28
+ try {
29
+ const envContent = readFileSync(ENV_FILE, 'utf8');
30
+ const envVars = {};
31
+
32
+ envContent.split('\n').forEach(line => {
33
+ const trimmed = line.trim();
34
+ if (trimmed && !trimmed.startsWith('#')) {
35
+ const [key, ...valueParts] = trimmed.split('=');
36
+ if (key && valueParts.length > 0) {
37
+ envVars[key] = valueParts.join('=');
38
+ }
39
+ }
40
+ });
41
+
42
+ // Set environment variables
43
+ Object.entries(envVars).forEach(([key, value]) => {
44
+ process.env[key] = value;
45
+ });
46
+
47
+ console.log(chalk.green('āœ… Staging environment variables loaded'));
48
+
49
+ } catch (error) {
50
+ console.error(chalk.red('āŒ Error loading staging environment variables:'), error.message);
51
+ process.exit(1);
52
+ }
53
+
54
+ // Validate required environment variables
55
+ const requiredVars = ['CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_ZONE_ID'];
56
+ const missingVars = requiredVars.filter(varName => !process.env[varName]);
57
+
58
+ if (missingVars.length > 0) {
59
+ console.error(chalk.red('āŒ Missing required environment variables:'), missingVars.join(', '));
60
+ process.exit(1);
61
+ }
62
+
63
+ console.log(chalk.green('āœ… All required credentials present'));
64
+
65
+ // Check if config file exists
66
+ if (!existsSync(CONFIG_FILE)) {
67
+ console.error(chalk.red(`āŒ Error: ${CONFIG_FILE} not found!`));
68
+ process.exit(1);
69
+ }
70
+
71
+ console.log(chalk.green('āœ… Staging deployment configuration found'));
72
+
73
+ // Run deployment with dry-run first
74
+ console.log(chalk.yellow('\nšŸ” Running dry-run deployment first...'));
75
+
76
+ try {
77
+ const dryRunCommand = `npx clodo-service deploy --config-file ${CONFIG_FILE} --environment staging --dry-run --verbose`;
78
+ console.log(chalk.gray(`Executing: ${dryRunCommand}`));
79
+
80
+ execSync(dryRunCommand, {
81
+ stdio: 'inherit',
82
+ env: { ...process.env, FORCE_COLOR: '1' }
83
+ });
84
+
85
+ console.log(chalk.green('āœ… Dry-run completed successfully'));
86
+
87
+ } catch (error) {
88
+ console.error(chalk.red('āŒ Dry-run failed:'), error.message);
89
+ console.log(chalk.yellow('Please fix the issues above before proceeding with actual deployment.'));
90
+ process.exit(1);
91
+ }
92
+
93
+ // Ask for confirmation before actual deployment
94
+ console.log(chalk.yellow('\nāš ļø Dry-run successful! Ready for actual deployment.'));
95
+ console.log(chalk.cyan('This will deploy to staging environment. Continue? (y/N): '));
96
+
97
+ // For automated deployment, we'll proceed automatically
98
+ console.log(chalk.blue('šŸš€ Proceeding with staging deployment...\n'));
99
+
100
+ try {
101
+ const deployCommand = `npx clodo-service deploy --config-file ${CONFIG_FILE} --environment staging --verbose`;
102
+ console.log(chalk.gray(`Executing: ${deployCommand}`));
103
+
104
+ execSync(deployCommand, {
105
+ stdio: 'inherit',
106
+ env: { ...process.env, FORCE_COLOR: '1' }
107
+ });
108
+
109
+ console.log(chalk.green('\nšŸŽ‰ Staging deployment completed successfully!'));
110
+ console.log(chalk.cyan('\nšŸ“‹ Next steps:'));
111
+ console.log(chalk.white(' 1. Verify staging deployment at: https://staging.example.com'));
112
+ console.log(chalk.white(' 2. Check monitoring dashboard'));
113
+ console.log(chalk.white(' 3. Run integration tests against staging'));
114
+ console.log(chalk.white(' 4. If successful, proceed to production deployment'));
115
+
116
+ } catch (error) {
117
+ console.error(chalk.red('\nāŒ Staging deployment failed:'), error.message);
118
+ console.log(chalk.yellow('Check the error details above and try again.'));
119
+ process.exit(1);
120
+ }