@jterrats/smart-deployment 1.0.3
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/README.md +193 -0
- package/lib/ai/agentforce-error-handler.d.ts +81 -0
- package/lib/ai/agentforce-error-handler.js +196 -0
- package/lib/ai/agentforce-error-handler.js.map +1 -0
- package/lib/ai/agentforce-priority-service.d.ts +82 -0
- package/lib/ai/agentforce-priority-service.js +257 -0
- package/lib/ai/agentforce-priority-service.js.map +1 -0
- package/lib/ai/agentforce-service.d.ts +99 -0
- package/lib/ai/agentforce-service.js +300 -0
- package/lib/ai/agentforce-service.js.map +1 -0
- package/lib/ai/circuit-breaker.d.ts +115 -0
- package/lib/ai/circuit-breaker.js +277 -0
- package/lib/ai/circuit-breaker.js.map +1 -0
- package/lib/ai/dependency-inference-service.d.ts +76 -0
- package/lib/ai/dependency-inference-service.js +220 -0
- package/lib/ai/dependency-inference-service.js.map +1 -0
- package/lib/ai/llm-provider-factory.d.ts +15 -0
- package/lib/ai/llm-provider-factory.js +36 -0
- package/lib/ai/llm-provider-factory.js.map +1 -0
- package/lib/ai/llm-provider.d.ts +27 -0
- package/lib/ai/llm-provider.js +2 -0
- package/lib/ai/llm-provider.js.map +1 -0
- package/lib/ai/openai-service.d.ts +20 -0
- package/lib/ai/openai-service.js +89 -0
- package/lib/ai/openai-service.js.map +1 -0
- package/lib/ai/prompt-builder.d.ts +79 -0
- package/lib/ai/prompt-builder.js +180 -0
- package/lib/ai/prompt-builder.js.map +1 -0
- package/lib/ai/response-parser.d.ts +67 -0
- package/lib/ai/response-parser.js +234 -0
- package/lib/ai/response-parser.js.map +1 -0
- package/lib/ai/wave-validation-service.d.ts +111 -0
- package/lib/ai/wave-validation-service.js +381 -0
- package/lib/ai/wave-validation-service.js.map +1 -0
- package/lib/analysis/analysis-reporter.d.ts +56 -0
- package/lib/analysis/analysis-reporter.js +170 -0
- package/lib/analysis/analysis-reporter.js.map +1 -0
- package/lib/analytics/error-analytics.d.ts +80 -0
- package/lib/analytics/error-analytics.js +162 -0
- package/lib/analytics/error-analytics.js.map +1 -0
- package/lib/commands/analyze.d.ts +49 -0
- package/lib/commands/analyze.js +232 -0
- package/lib/commands/analyze.js.map +1 -0
- package/lib/commands/config.d.ts +42 -0
- package/lib/commands/config.js +219 -0
- package/lib/commands/config.js.map +1 -0
- package/lib/commands/resume.d.ts +26 -0
- package/lib/commands/resume.js +69 -0
- package/lib/commands/resume.js.map +1 -0
- package/lib/commands/start.d.ts +70 -0
- package/lib/commands/start.js +659 -0
- package/lib/commands/start.js.map +1 -0
- package/lib/commands/status.d.ts +37 -0
- package/lib/commands/status.js +69 -0
- package/lib/commands/status.js.map +1 -0
- package/lib/commands/validate.d.ts +33 -0
- package/lib/commands/validate.js +66 -0
- package/lib/commands/validate.js.map +1 -0
- package/lib/config/repo-config.d.ts +22 -0
- package/lib/config/repo-config.js +31 -0
- package/lib/config/repo-config.js.map +1 -0
- package/lib/constants/agentforce-limits.d.ts +174 -0
- package/lib/constants/agentforce-limits.js +262 -0
- package/lib/constants/agentforce-limits.js.map +1 -0
- package/lib/constants/api-version.d.ts +70 -0
- package/lib/constants/api-version.js +122 -0
- package/lib/constants/api-version.js.map +1 -0
- package/lib/constants/deployment-order.d.ts +68 -0
- package/lib/constants/deployment-order.js +162 -0
- package/lib/constants/deployment-order.js.map +1 -0
- package/lib/constants/salesforce-limits.d.ts +107 -0
- package/lib/constants/salesforce-limits.js +104 -0
- package/lib/constants/salesforce-limits.js.map +1 -0
- package/lib/dependencies/circular-dependency-detector.d.ts +137 -0
- package/lib/dependencies/circular-dependency-detector.js +329 -0
- package/lib/dependencies/circular-dependency-detector.js.map +1 -0
- package/lib/dependencies/cycle-remediation-planner.d.ts +50 -0
- package/lib/dependencies/cycle-remediation-planner.js +192 -0
- package/lib/dependencies/cycle-remediation-planner.js.map +1 -0
- package/lib/dependencies/dependency-cache.d.ts +134 -0
- package/lib/dependencies/dependency-cache.js +303 -0
- package/lib/dependencies/dependency-cache.js.map +1 -0
- package/lib/dependencies/dependency-depth-calculator.d.ts +145 -0
- package/lib/dependencies/dependency-depth-calculator.js +368 -0
- package/lib/dependencies/dependency-depth-calculator.js.map +1 -0
- package/lib/dependencies/dependency-graph-builder.d.ts +151 -0
- package/lib/dependencies/dependency-graph-builder.js +411 -0
- package/lib/dependencies/dependency-graph-builder.js.map +1 -0
- package/lib/dependencies/dependency-impact-analyzer.d.ts +145 -0
- package/lib/dependencies/dependency-impact-analyzer.js +330 -0
- package/lib/dependencies/dependency-impact-analyzer.js.map +1 -0
- package/lib/dependencies/dependency-merger.d.ts +122 -0
- package/lib/dependencies/dependency-merger.js +245 -0
- package/lib/dependencies/dependency-merger.js.map +1 -0
- package/lib/dependencies/dependency-resolver.d.ts +157 -0
- package/lib/dependencies/dependency-resolver.js +298 -0
- package/lib/dependencies/dependency-resolver.js.map +1 -0
- package/lib/dependencies/dependency-validator.d.ts +123 -0
- package/lib/dependencies/dependency-validator.js +291 -0
- package/lib/dependencies/dependency-validator.js.map +1 -0
- package/lib/dependencies/graph-visualizer.d.ts +110 -0
- package/lib/dependencies/graph-visualizer.js +262 -0
- package/lib/dependencies/graph-visualizer.js.map +1 -0
- package/lib/dependencies/heuristic-inference.d.ts +136 -0
- package/lib/dependencies/heuristic-inference.js +430 -0
- package/lib/dependencies/heuristic-inference.js.map +1 -0
- package/lib/deployment/cycle-source-editor.d.ts +34 -0
- package/lib/deployment/cycle-source-editor.js +121 -0
- package/lib/deployment/cycle-source-editor.js.map +1 -0
- package/lib/deployment/deployment-error-handler.d.ts +38 -0
- package/lib/deployment/deployment-error-handler.js +79 -0
- package/lib/deployment/deployment-error-handler.js.map +1 -0
- package/lib/deployment/deployment-reporter.d.ts +63 -0
- package/lib/deployment/deployment-reporter.js +150 -0
- package/lib/deployment/deployment-reporter.js.map +1 -0
- package/lib/deployment/deployment-state-summary.d.ts +38 -0
- package/lib/deployment/deployment-state-summary.js +209 -0
- package/lib/deployment/deployment-state-summary.js.map +1 -0
- package/lib/deployment/deployment-status-service.d.ts +36 -0
- package/lib/deployment/deployment-status-service.js +128 -0
- package/lib/deployment/deployment-status-service.js.map +1 -0
- package/lib/deployment/deployment-tracker.d.ts +42 -0
- package/lib/deployment/deployment-tracker.js +79 -0
- package/lib/deployment/deployment-tracker.js.map +1 -0
- package/lib/deployment/deployment-validation-service.d.ts +28 -0
- package/lib/deployment/deployment-validation-service.js +161 -0
- package/lib/deployment/deployment-validation-service.js.map +1 -0
- package/lib/deployment/retry-handler.d.ts +37 -0
- package/lib/deployment/retry-handler.js +86 -0
- package/lib/deployment/retry-handler.js.map +1 -0
- package/lib/deployment/sf-cli-integration.d.ts +42 -0
- package/lib/deployment/sf-cli-integration.js +105 -0
- package/lib/deployment/sf-cli-integration.js.map +1 -0
- package/lib/deployment/state-manager.d.ts +61 -0
- package/lib/deployment/state-manager.js +83 -0
- package/lib/deployment/state-manager.js.map +1 -0
- package/lib/deployment/test-executor.d.ts +41 -0
- package/lib/deployment/test-executor.js +87 -0
- package/lib/deployment/test-executor.js.map +1 -0
- package/lib/errors/base-error.d.ts +24 -0
- package/lib/errors/base-error.js +66 -0
- package/lib/errors/base-error.js.map +1 -0
- package/lib/errors/dependency-error.d.ts +37 -0
- package/lib/errors/dependency-error.js +76 -0
- package/lib/errors/dependency-error.js.map +1 -0
- package/lib/errors/deployment-error.d.ts +55 -0
- package/lib/errors/deployment-error.js +132 -0
- package/lib/errors/deployment-error.js.map +1 -0
- package/lib/errors/index.d.ts +45 -0
- package/lib/errors/index.js +71 -0
- package/lib/errors/index.js.map +1 -0
- package/lib/errors/network-error.d.ts +53 -0
- package/lib/errors/network-error.js +111 -0
- package/lib/errors/network-error.js.map +1 -0
- package/lib/errors/parsing-error.d.ts +41 -0
- package/lib/errors/parsing-error.js +69 -0
- package/lib/errors/parsing-error.js.map +1 -0
- package/lib/errors/validation-error-reporter.d.ts +34 -0
- package/lib/errors/validation-error-reporter.js +99 -0
- package/lib/errors/validation-error-reporter.js.map +1 -0
- package/lib/errors/validation-error.d.ts +58 -0
- package/lib/errors/validation-error.js +131 -0
- package/lib/errors/validation-error.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/monitoring/performance-monitor.d.ts +98 -0
- package/lib/monitoring/performance-monitor.js +260 -0
- package/lib/monitoring/performance-monitor.js.map +1 -0
- package/lib/parsers/apex-class-parser.d.ts +47 -0
- package/lib/parsers/apex-class-parser.js +368 -0
- package/lib/parsers/apex-class-parser.js.map +1 -0
- package/lib/parsers/apex-trigger-parser.d.ts +48 -0
- package/lib/parsers/apex-trigger-parser.js +229 -0
- package/lib/parsers/apex-trigger-parser.js.map +1 -0
- package/lib/parsers/aura-parser.d.ts +55 -0
- package/lib/parsers/aura-parser.js +229 -0
- package/lib/parsers/aura-parser.js.map +1 -0
- package/lib/parsers/bot-parser.d.ts +65 -0
- package/lib/parsers/bot-parser.js +225 -0
- package/lib/parsers/bot-parser.js.map +1 -0
- package/lib/parsers/custom-metadata-parser.d.ts +94 -0
- package/lib/parsers/custom-metadata-parser.js +199 -0
- package/lib/parsers/custom-metadata-parser.js.map +1 -0
- package/lib/parsers/custom-object-parser.d.ts +62 -0
- package/lib/parsers/custom-object-parser.js +297 -0
- package/lib/parsers/custom-object-parser.js.map +1 -0
- package/lib/parsers/email-template-parser.d.ts +64 -0
- package/lib/parsers/email-template-parser.js +238 -0
- package/lib/parsers/email-template-parser.js.map +1 -0
- package/lib/parsers/error-resilient-parser.d.ts +110 -0
- package/lib/parsers/error-resilient-parser.js +277 -0
- package/lib/parsers/error-resilient-parser.js.map +1 -0
- package/lib/parsers/flexipage-parser.d.ts +64 -0
- package/lib/parsers/flexipage-parser.js +196 -0
- package/lib/parsers/flexipage-parser.js.map +1 -0
- package/lib/parsers/flow-parser.d.ts +54 -0
- package/lib/parsers/flow-parser.js +287 -0
- package/lib/parsers/flow-parser.js.map +1 -0
- package/lib/parsers/genai-prompt-parser.d.ts +67 -0
- package/lib/parsers/genai-prompt-parser.js +160 -0
- package/lib/parsers/genai-prompt-parser.js.map +1 -0
- package/lib/parsers/layout-parser.d.ts +64 -0
- package/lib/parsers/layout-parser.js +267 -0
- package/lib/parsers/layout-parser.js.map +1 -0
- package/lib/parsers/lwc-parser.d.ts +60 -0
- package/lib/parsers/lwc-parser.js +264 -0
- package/lib/parsers/lwc-parser.js.map +1 -0
- package/lib/parsers/permission-set-parser.d.ts +86 -0
- package/lib/parsers/permission-set-parser.js +152 -0
- package/lib/parsers/permission-set-parser.js.map +1 -0
- package/lib/parsers/profile-parser.d.ts +81 -0
- package/lib/parsers/profile-parser.js +141 -0
- package/lib/parsers/profile-parser.js.map +1 -0
- package/lib/parsers/visualforce-parser.d.ts +47 -0
- package/lib/parsers/visualforce-parser.js +180 -0
- package/lib/parsers/visualforce-parser.js.map +1 -0
- package/lib/provisioning/data-provisioner.d.ts +88 -0
- package/lib/provisioning/data-provisioner.js +257 -0
- package/lib/provisioning/data-provisioner.js.map +1 -0
- package/lib/scanner/custom-structure-scanner.d.ts +66 -0
- package/lib/scanner/custom-structure-scanner.js +229 -0
- package/lib/scanner/custom-structure-scanner.js.map +1 -0
- package/lib/scanner/forceignore-parser.d.ts +69 -0
- package/lib/scanner/forceignore-parser.js +195 -0
- package/lib/scanner/forceignore-parser.js.map +1 -0
- package/lib/scanner/metadata-format-scanner.d.ts +77 -0
- package/lib/scanner/metadata-format-scanner.js +282 -0
- package/lib/scanner/metadata-format-scanner.js.map +1 -0
- package/lib/scanner/monorepo-scanner.d.ts +71 -0
- package/lib/scanner/monorepo-scanner.js +225 -0
- package/lib/scanner/monorepo-scanner.js.map +1 -0
- package/lib/scanner/project-validator.d.ts +55 -0
- package/lib/scanner/project-validator.js +235 -0
- package/lib/scanner/project-validator.js.map +1 -0
- package/lib/scanner/sfdx-project-detector.d.ts +86 -0
- package/lib/scanner/sfdx-project-detector.js +240 -0
- package/lib/scanner/sfdx-project-detector.js.map +1 -0
- package/lib/scanner/structure-validator.d.ts +64 -0
- package/lib/scanner/structure-validator.js +296 -0
- package/lib/scanner/structure-validator.js.map +1 -0
- package/lib/services/metadata-scanner-service.d.ts +64 -0
- package/lib/services/metadata-scanner-service.js +651 -0
- package/lib/services/metadata-scanner-service.js.map +1 -0
- package/lib/types/agentforce.d.ts +157 -0
- package/lib/types/agentforce.js +2 -0
- package/lib/types/agentforce.js.map +1 -0
- package/lib/types/dependency.d.ts +98 -0
- package/lib/types/dependency.js +5 -0
- package/lib/types/dependency.js.map +1 -0
- package/lib/types/deployment-plan.d.ts +81 -0
- package/lib/types/deployment-plan.js +6 -0
- package/lib/types/deployment-plan.js.map +1 -0
- package/lib/types/deployment.d.ts +88 -0
- package/lib/types/deployment.js +5 -0
- package/lib/types/deployment.js.map +1 -0
- package/lib/types/graph.d.ts +35 -0
- package/lib/types/graph.js +5 -0
- package/lib/types/graph.js.map +1 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.js +17 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/metadata.d.ts +101 -0
- package/lib/types/metadata.js +13 -0
- package/lib/types/metadata.js.map +1 -0
- package/lib/types/project.d.ts +156 -0
- package/lib/types/project.js +56 -0
- package/lib/types/project.js.map +1 -0
- package/lib/types/salesforce/apex.d.ts +94 -0
- package/lib/types/salesforce/apex.js +6 -0
- package/lib/types/salesforce/apex.js.map +1 -0
- package/lib/types/salesforce/aura.d.ts +150 -0
- package/lib/types/salesforce/aura.js +6 -0
- package/lib/types/salesforce/aura.js.map +1 -0
- package/lib/types/salesforce/bot.d.ts +293 -0
- package/lib/types/salesforce/bot.js +6 -0
- package/lib/types/salesforce/bot.js.map +1 -0
- package/lib/types/salesforce/common.d.ts +15 -0
- package/lib/types/salesforce/common.js +5 -0
- package/lib/types/salesforce/common.js.map +1 -0
- package/lib/types/salesforce/custom-metadata.d.ts +92 -0
- package/lib/types/salesforce/custom-metadata.js +6 -0
- package/lib/types/salesforce/custom-metadata.js.map +1 -0
- package/lib/types/salesforce/email.d.ts +56 -0
- package/lib/types/salesforce/email.js +6 -0
- package/lib/types/salesforce/email.js.map +1 -0
- package/lib/types/salesforce/flexipage.d.ts +149 -0
- package/lib/types/salesforce/flexipage.js +6 -0
- package/lib/types/salesforce/flexipage.js.map +1 -0
- package/lib/types/salesforce/flow.d.ts +516 -0
- package/lib/types/salesforce/flow.js +6 -0
- package/lib/types/salesforce/flow.js.map +1 -0
- package/lib/types/salesforce/genai.d.ts +67 -0
- package/lib/types/salesforce/genai.js +6 -0
- package/lib/types/salesforce/genai.js.map +1 -0
- package/lib/types/salesforce/index.d.ts +27 -0
- package/lib/types/salesforce/index.js +43 -0
- package/lib/types/salesforce/index.js.map +1 -0
- package/lib/types/salesforce/layout.d.ts +236 -0
- package/lib/types/salesforce/layout.js +6 -0
- package/lib/types/salesforce/layout.js.map +1 -0
- package/lib/types/salesforce/lwc.d.ts +123 -0
- package/lib/types/salesforce/lwc.js +6 -0
- package/lib/types/salesforce/lwc.js.map +1 -0
- package/lib/types/salesforce/object.d.ts +427 -0
- package/lib/types/salesforce/object.js +6 -0
- package/lib/types/salesforce/object.js.map +1 -0
- package/lib/types/salesforce/parser-types.d.ts +79 -0
- package/lib/types/salesforce/parser-types.js +80 -0
- package/lib/types/salesforce/parser-types.js.map +1 -0
- package/lib/types/salesforce/permission.d.ts +289 -0
- package/lib/types/salesforce/permission.js +6 -0
- package/lib/types/salesforce/permission.js.map +1 -0
- package/lib/types/salesforce/resource.d.ts +93 -0
- package/lib/types/salesforce/resource.js +6 -0
- package/lib/types/salesforce/resource.js.map +1 -0
- package/lib/types/salesforce/visualforce.d.ts +70 -0
- package/lib/types/salesforce/visualforce.js +6 -0
- package/lib/types/salesforce/visualforce.js.map +1 -0
- package/lib/utils/cache-manager.d.ts +158 -0
- package/lib/utils/cache-manager.js +429 -0
- package/lib/utils/cache-manager.js.map +1 -0
- package/lib/utils/deployment-plan-manager.d.ts +40 -0
- package/lib/utils/deployment-plan-manager.js +183 -0
- package/lib/utils/deployment-plan-manager.js.map +1 -0
- package/lib/utils/error-aggregator.d.ts +117 -0
- package/lib/utils/error-aggregator.js +268 -0
- package/lib/utils/error-aggregator.js.map +1 -0
- package/lib/utils/file-system.d.ts +62 -0
- package/lib/utils/file-system.js +167 -0
- package/lib/utils/file-system.js.map +1 -0
- package/lib/utils/functional.d.ts +52 -0
- package/lib/utils/functional.js +61 -0
- package/lib/utils/functional.js.map +1 -0
- package/lib/utils/graph-algorithms.d.ts +53 -0
- package/lib/utils/graph-algorithms.js +177 -0
- package/lib/utils/graph-algorithms.js.map +1 -0
- package/lib/utils/logger.d.ts +154 -0
- package/lib/utils/logger.js +327 -0
- package/lib/utils/logger.js.map +1 -0
- package/lib/utils/network-handler.d.ts +64 -0
- package/lib/utils/network-handler.js +147 -0
- package/lib/utils/network-handler.js.map +1 -0
- package/lib/utils/performance.d.ts +148 -0
- package/lib/utils/performance.js +294 -0
- package/lib/utils/performance.js.map +1 -0
- package/lib/utils/string.d.ts +197 -0
- package/lib/utils/string.js +331 -0
- package/lib/utils/string.js.map +1 -0
- package/lib/utils/xml.d.ts +97 -0
- package/lib/utils/xml.js +227 -0
- package/lib/utils/xml.js.map +1 -0
- package/lib/validators/xml-metadata-validator.d.ts +106 -0
- package/lib/validators/xml-metadata-validator.js +509 -0
- package/lib/validators/xml-metadata-validator.js.map +1 -0
- package/lib/waves/priority-wave-generator-ai.d.ts +85 -0
- package/lib/waves/priority-wave-generator-ai.js +191 -0
- package/lib/waves/priority-wave-generator-ai.js.map +1 -0
- package/lib/waves/priority-wave-generator.d.ts +47 -0
- package/lib/waves/priority-wave-generator.js +88 -0
- package/lib/waves/priority-wave-generator.js.map +1 -0
- package/lib/waves/test-optimizer.d.ts +155 -0
- package/lib/waves/test-optimizer.js +290 -0
- package/lib/waves/test-optimizer.js.map +1 -0
- package/lib/waves/wave-builder.d.ts +147 -0
- package/lib/waves/wave-builder.js +286 -0
- package/lib/waves/wave-builder.js.map +1 -0
- package/lib/waves/wave-diff-generator.d.ts +17 -0
- package/lib/waves/wave-diff-generator.js +6 -0
- package/lib/waves/wave-diff-generator.js.map +1 -0
- package/lib/waves/wave-executor.d.ts +33 -0
- package/lib/waves/wave-executor.js +50 -0
- package/lib/waves/wave-executor.js.map +1 -0
- package/lib/waves/wave-merger.d.ts +96 -0
- package/lib/waves/wave-merger.js +181 -0
- package/lib/waves/wave-merger.js.map +1 -0
- package/lib/waves/wave-metadata-generator.d.ts +13 -0
- package/lib/waves/wave-metadata-generator.js +12 -0
- package/lib/waves/wave-metadata-generator.js.map +1 -0
- package/lib/waves/wave-splitter.d.ts +154 -0
- package/lib/waves/wave-splitter.js +307 -0
- package/lib/waves/wave-splitter.js.map +1 -0
- package/lib/waves/wave-validator.d.ts +17 -0
- package/lib/waves/wave-validator.js +15 -0
- package/lib/waves/wave-validator.js.map +1 -0
- package/messages/analyze.json +18 -0
- package/messages/config.json +29 -0
- package/messages/resume.json +9 -0
- package/messages/start.json +24 -0
- package/messages/status.json +8 -0
- package/messages/validate.json +9 -0
- package/npm-shrinkwrap.json +25676 -0
- package/oclif.lock +11988 -0
- package/oclif.manifest.json +589 -0
- package/package.json +224 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { glob as globAsync } from 'glob';
|
|
3
|
+
import { MetadataScannerService } from '../services/metadata-scanner-service.js';
|
|
4
|
+
import { getLogger } from '../utils/logger.js';
|
|
5
|
+
import { XmlMetadataValidator } from '../validators/xml-metadata-validator.js';
|
|
6
|
+
import { WaveValidationService } from '../ai/wave-validation-service.js';
|
|
7
|
+
import { WaveBuilder } from '../waves/wave-builder.js';
|
|
8
|
+
import { validateWaveOrder } from '../waves/wave-executor.js';
|
|
9
|
+
const logger = getLogger('DeploymentValidationService');
|
|
10
|
+
export class DeploymentValidationService {
|
|
11
|
+
scanner = new MetadataScannerService();
|
|
12
|
+
xmlValidator = new XmlMetadataValidator();
|
|
13
|
+
async validateProject(sourcePath, options = {}) {
|
|
14
|
+
const scanResult = await this.scanner.scan({ sourcePath });
|
|
15
|
+
const waveBuilder = new WaveBuilder({
|
|
16
|
+
maxComponentsPerWave: 10_000,
|
|
17
|
+
respectTypeOrder: true,
|
|
18
|
+
handleCircularDeps: true,
|
|
19
|
+
});
|
|
20
|
+
const waveResult = waveBuilder.generateWaves(scanResult.dependencyResult.graph);
|
|
21
|
+
const issues = [];
|
|
22
|
+
issues.push(...scanResult.errors.map((message) => ({ severity: 'error', message })), ...scanResult.warnings.map((message) => ({ severity: 'warning', message })));
|
|
23
|
+
if (!validateWaveOrder(waveResult.waves)) {
|
|
24
|
+
issues.push({
|
|
25
|
+
severity: 'error',
|
|
26
|
+
message: 'Generated waves are not in strict numerical order.',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (waveResult.circularDependencies.length > 0) {
|
|
30
|
+
issues.push({
|
|
31
|
+
severity: 'error',
|
|
32
|
+
message: `${waveResult.circularDependencies.length} circular dependency cycle(s) detected.`,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (waveResult.unplacedComponents.length > 0) {
|
|
36
|
+
issues.push({
|
|
37
|
+
severity: 'warning',
|
|
38
|
+
message: `${waveResult.unplacedComponents.length} component(s) required manual placement.`,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const xmlFiles = await this.findXmlMetadataFiles(scanResult.projectRoot);
|
|
42
|
+
const xmlResults = await this.xmlValidator.validateFiles(xmlFiles);
|
|
43
|
+
for (const result of xmlResults) {
|
|
44
|
+
for (const error of result.errors) {
|
|
45
|
+
issues.push({
|
|
46
|
+
severity: error.severity,
|
|
47
|
+
message: error.message,
|
|
48
|
+
filePath: result.filePath,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
for (const warning of result.warnings) {
|
|
52
|
+
issues.push({
|
|
53
|
+
severity: 'warning',
|
|
54
|
+
message: warning.message,
|
|
55
|
+
filePath: result.filePath,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let aiAnalyzed = false;
|
|
60
|
+
let overallRisk;
|
|
61
|
+
let aiProvider;
|
|
62
|
+
let aiModel;
|
|
63
|
+
let aiFallback;
|
|
64
|
+
if (options.useAI) {
|
|
65
|
+
const aiValidationService = new WaveValidationService({ baseDir: scanResult.projectRoot });
|
|
66
|
+
const aiValidation = await aiValidationService.validateWaves(waveResult.waves);
|
|
67
|
+
const providerConfig = aiValidationService.getProviderConfig();
|
|
68
|
+
aiAnalyzed = aiValidation.aiAnalyzed;
|
|
69
|
+
overallRisk = aiValidation.overallRisk;
|
|
70
|
+
aiProvider = providerConfig.provider;
|
|
71
|
+
aiModel = providerConfig.model;
|
|
72
|
+
aiFallback = !aiValidation.aiAnalyzed;
|
|
73
|
+
for (const issue of aiValidation.issues) {
|
|
74
|
+
issues.push({
|
|
75
|
+
severity: issue.severity === 'high' || issue.severity === 'critical' ? 'error' : 'warning',
|
|
76
|
+
message: `[AI ${issue.category}] ${issue.message}`,
|
|
77
|
+
waveNumber: issue.waveNumber,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
for (const assessment of aiValidation.riskAssessments) {
|
|
81
|
+
if (assessment.riskLevel === 'high' || assessment.riskLevel === 'critical') {
|
|
82
|
+
issues.push({
|
|
83
|
+
severity: assessment.riskLevel === 'critical' ? 'error' : 'warning',
|
|
84
|
+
message: `[AI risk] Wave ${assessment.waveNumber} assessed as ${assessment.riskLevel}. ${assessment.riskFactors.join(', ') || 'No specific factors reported.'}`,
|
|
85
|
+
waveNumber: assessment.waveNumber,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const valid = issues.every((issue) => issue.severity !== 'error');
|
|
91
|
+
logger.info('Deployment validation completed', {
|
|
92
|
+
components: scanResult.components.length,
|
|
93
|
+
totalWaves: waveResult.waves.length,
|
|
94
|
+
xmlFilesValidated: xmlFiles.length,
|
|
95
|
+
valid,
|
|
96
|
+
issues: issues.length,
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
valid,
|
|
100
|
+
components: scanResult.components.length,
|
|
101
|
+
totalWaves: waveResult.waves.length,
|
|
102
|
+
estimatedTime: waveResult.stats.totalEstimatedTime,
|
|
103
|
+
xmlFilesValidated: xmlFiles.length,
|
|
104
|
+
issues,
|
|
105
|
+
aiAnalyzed,
|
|
106
|
+
overallRisk,
|
|
107
|
+
aiProvider,
|
|
108
|
+
aiModel,
|
|
109
|
+
aiFallback,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
formatSummary(summary) {
|
|
113
|
+
const lines = [
|
|
114
|
+
`Validation: ${summary.valid ? 'PASSED' : 'FAILED'}`,
|
|
115
|
+
`Components: ${summary.components}`,
|
|
116
|
+
`Waves: ${summary.totalWaves}`,
|
|
117
|
+
`Estimated Time: ${summary.estimatedTime}s`,
|
|
118
|
+
`XML Files Validated: ${summary.xmlFilesValidated}`,
|
|
119
|
+
];
|
|
120
|
+
if (summary.aiAnalyzed !== undefined) {
|
|
121
|
+
lines.push(`AI Validation: ${summary.aiAnalyzed ? 'ENABLED' : 'UNAVAILABLE'}`);
|
|
122
|
+
}
|
|
123
|
+
if (summary.aiProvider) {
|
|
124
|
+
lines.push(`AI Provider: ${summary.aiProvider}`);
|
|
125
|
+
}
|
|
126
|
+
if (summary.aiModel) {
|
|
127
|
+
lines.push(`AI Model: ${summary.aiModel}`);
|
|
128
|
+
}
|
|
129
|
+
if (summary.aiFallback !== undefined) {
|
|
130
|
+
lines.push(`AI Fallback: ${summary.aiFallback ? 'YES' : 'NO'}`);
|
|
131
|
+
}
|
|
132
|
+
if (summary.overallRisk) {
|
|
133
|
+
lines.push(`AI Overall Risk: ${summary.overallRisk.toUpperCase()}`);
|
|
134
|
+
}
|
|
135
|
+
if (summary.issues.length > 0) {
|
|
136
|
+
lines.push('');
|
|
137
|
+
lines.push('Issues:');
|
|
138
|
+
for (const issue of summary.issues) {
|
|
139
|
+
const location = issue.filePath
|
|
140
|
+
? ` (${issue.filePath})`
|
|
141
|
+
: issue.waveNumber !== undefined
|
|
142
|
+
? ` (wave ${issue.waveNumber})`
|
|
143
|
+
: '';
|
|
144
|
+
lines.push(`- [${issue.severity}] ${issue.message}${location}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return lines.join('\n');
|
|
148
|
+
}
|
|
149
|
+
async findXmlMetadataFiles(projectRoot) {
|
|
150
|
+
const files = await globAsync('**/*-meta.xml', {
|
|
151
|
+
cwd: projectRoot,
|
|
152
|
+
absolute: true,
|
|
153
|
+
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
154
|
+
});
|
|
155
|
+
return files.filter((filePath) => {
|
|
156
|
+
const normalized = filePath.split(path.sep).join('/');
|
|
157
|
+
return !normalized.includes('/node_modules/') && !normalized.includes('/.git/');
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=deployment-validation-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-validation-service.js","sourceRoot":"","sources":["../../src/deployment/deployment-validation-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Retry Logic - US-088
|
|
3
|
+
* Handles automatic retry on transient failures
|
|
4
|
+
*
|
|
5
|
+
* @ac US-088-AC-1: Detect retryable errors
|
|
6
|
+
* @ac US-088-AC-2: Retry up to 3 times
|
|
7
|
+
* @ac US-088-AC-3: Exponential backoff
|
|
8
|
+
* @ac US-088-AC-4: Retry without tests (sandbox)
|
|
9
|
+
* @ac US-088-AC-5: Report retry attempts
|
|
10
|
+
* @ac US-088-AC-6: Fail after max retries
|
|
11
|
+
* @issue #88
|
|
12
|
+
*/
|
|
13
|
+
export type RetryConfig = {
|
|
14
|
+
maxRetries: number;
|
|
15
|
+
initialDelay: number;
|
|
16
|
+
maxDelay: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* @ac US-088-AC-1: Detect retryable errors
|
|
20
|
+
*/
|
|
21
|
+
export declare class RetryHandler {
|
|
22
|
+
private readonly config;
|
|
23
|
+
constructor(config?: Partial<RetryConfig>);
|
|
24
|
+
isRetryable(error: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* @ac US-088-AC-2: Retry up to 3 times
|
|
27
|
+
* @ac US-088-AC-3: Exponential backoff
|
|
28
|
+
* @ac US-088-AC-5: Report retry attempts
|
|
29
|
+
* @ac US-088-AC-6: Fail after max retries
|
|
30
|
+
*/
|
|
31
|
+
executeWithRetry<T>(fn: () => Promise<T>, context: string): Promise<T>;
|
|
32
|
+
/**
|
|
33
|
+
* @ac US-088-AC-3: Exponential backoff
|
|
34
|
+
*/
|
|
35
|
+
private calculateDelay;
|
|
36
|
+
private sleep;
|
|
37
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Retry Logic - US-088
|
|
3
|
+
* Handles automatic retry on transient failures
|
|
4
|
+
*
|
|
5
|
+
* @ac US-088-AC-1: Detect retryable errors
|
|
6
|
+
* @ac US-088-AC-2: Retry up to 3 times
|
|
7
|
+
* @ac US-088-AC-3: Exponential backoff
|
|
8
|
+
* @ac US-088-AC-4: Retry without tests (sandbox)
|
|
9
|
+
* @ac US-088-AC-5: Report retry attempts
|
|
10
|
+
* @ac US-088-AC-6: Fail after max retries
|
|
11
|
+
* @issue #88
|
|
12
|
+
*/
|
|
13
|
+
import { getLogger } from '../utils/logger.js';
|
|
14
|
+
const logger = getLogger('RetryHandler');
|
|
15
|
+
const RETRYABLE_ERRORS = [
|
|
16
|
+
'UNABLE_TO_LOCK_ROW',
|
|
17
|
+
'REQUEST_LIMIT_EXCEEDED',
|
|
18
|
+
'STORAGE_LIMIT_EXCEEDED',
|
|
19
|
+
'CONNECTION_ERROR',
|
|
20
|
+
'TIMEOUT',
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* @ac US-088-AC-1: Detect retryable errors
|
|
24
|
+
*/
|
|
25
|
+
export class RetryHandler {
|
|
26
|
+
config;
|
|
27
|
+
constructor(config = {}) {
|
|
28
|
+
this.config = {
|
|
29
|
+
maxRetries: config.maxRetries ?? 3,
|
|
30
|
+
initialDelay: config.initialDelay ?? 1000,
|
|
31
|
+
maxDelay: config.maxDelay ?? 30_000,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
isRetryable(error) {
|
|
35
|
+
return RETRYABLE_ERRORS.some((pattern) => error.includes(pattern));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @ac US-088-AC-2: Retry up to 3 times
|
|
39
|
+
* @ac US-088-AC-3: Exponential backoff
|
|
40
|
+
* @ac US-088-AC-5: Report retry attempts
|
|
41
|
+
* @ac US-088-AC-6: Fail after max retries
|
|
42
|
+
*/
|
|
43
|
+
async executeWithRetry(fn, context) {
|
|
44
|
+
let lastError;
|
|
45
|
+
const attemptExecution = async (attempt) => {
|
|
46
|
+
try {
|
|
47
|
+
if (attempt > 0) {
|
|
48
|
+
const delay = this.calculateDelay(attempt);
|
|
49
|
+
logger.info('Retrying operation', { context, attempt, delay });
|
|
50
|
+
await this.sleep(delay);
|
|
51
|
+
}
|
|
52
|
+
return await fn();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
56
|
+
if (!this.isRetryable(lastError.message)) {
|
|
57
|
+
logger.warn('Non-retryable error encountered', { context, error: lastError.message });
|
|
58
|
+
throw lastError;
|
|
59
|
+
}
|
|
60
|
+
if (attempt === this.config.maxRetries) {
|
|
61
|
+
logger.error('Max retries exceeded', { context, attempt, error: lastError.message });
|
|
62
|
+
throw new Error(`Max retries (${this.config.maxRetries}) exceeded: ${lastError.message}`);
|
|
63
|
+
}
|
|
64
|
+
logger.warn('Retryable error, will retry', { context, attempt, error: lastError.message });
|
|
65
|
+
return attemptExecution(attempt + 1);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return attemptExecution(0).catch((error) => {
|
|
69
|
+
if (error instanceof Error) {
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
throw lastError ?? new Error('Retry failed');
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* @ac US-088-AC-3: Exponential backoff
|
|
77
|
+
*/
|
|
78
|
+
calculateDelay(attempt) {
|
|
79
|
+
const delay = this.config.initialDelay * Math.pow(2, attempt - 1);
|
|
80
|
+
return Math.min(delay, this.config.maxDelay);
|
|
81
|
+
}
|
|
82
|
+
sleep(ms) {
|
|
83
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=retry-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-handler.js","sourceRoot":"","sources":["../../src/deployment/retry-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;AAEzC,MAAM,gBAAgB,GAAG;IACvB,oBAAoB;IACpB,wBAAwB;IACxB,wBAAwB;IACxB,kBAAkB;IAClB,SAAS;CACV,CAAC;AAQF;;GAEG;AACH,MAAM,OAAO,YAAY;IACN,MAAM,CAAwB;IAE/C,YAAmB,SAA+B,EAAE;QAClD,IAAI,CAAC,MAAM,GAAG;YACZ,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC;YAClC,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;YACzC,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,MAAM;SACpC,CAAC;IACJ,CAAC;IAEM,WAAW,CAAC,KAAa;QAC9B,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,gBAAgB,CAAI,EAAoB,EAAE,OAAe;QACpE,IAAI,SAA4B,CAAC;QAEjC,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAe,EAAc,EAAE;YAC7D,IAAI,CAAC;gBACH,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAChB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;oBAC3C,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC/D,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;gBAED,OAAO,MAAM,EAAE,EAAE,CAAC;YACpB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAEtE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;oBACzC,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;oBACtF,MAAM,SAAS,CAAC;gBAClB,CAAC;gBAED,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;oBACvC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;oBACrF,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,UAAU,eAAe,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC5F,CAAC;gBAED,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC3F,OAAO,gBAAgB,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;QAEF,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YAClD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,OAAe;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;QAClE,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAEO,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SF CLI Integration - US-085
|
|
3
|
+
* Executes deployments via official Salesforce CLI
|
|
4
|
+
*
|
|
5
|
+
* @ac US-085-AC-1: Execute sf project deploy start
|
|
6
|
+
* @ac US-085-AC-2: Pass manifest file
|
|
7
|
+
* @ac US-085-AC-3: Pass test level
|
|
8
|
+
* @ac US-085-AC-4: Pass target org
|
|
9
|
+
* @ac US-085-AC-5: Capture output
|
|
10
|
+
* @ac US-085-AC-6: Parse deployment results
|
|
11
|
+
* @issue #85
|
|
12
|
+
*/
|
|
13
|
+
export type TestLevel = 'NoTestRun' | 'RunSpecifiedTests' | 'RunLocalTests' | 'RunAllTestsInOrg';
|
|
14
|
+
export type DeploymentOptions = {
|
|
15
|
+
manifestPath: string;
|
|
16
|
+
targetOrg: string;
|
|
17
|
+
testLevel?: TestLevel;
|
|
18
|
+
tests?: string[];
|
|
19
|
+
checkOnly?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type DeploymentResult = {
|
|
22
|
+
success: boolean;
|
|
23
|
+
deploymentId?: string;
|
|
24
|
+
status: string;
|
|
25
|
+
componentSuccesses: number;
|
|
26
|
+
componentFailures: number;
|
|
27
|
+
testsRun?: number;
|
|
28
|
+
testFailures?: number;
|
|
29
|
+
output: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* @ac US-085-AC-1: Execute sf project deploy start
|
|
33
|
+
* @ac US-085-AC-2: Pass manifest file
|
|
34
|
+
* @ac US-085-AC-3: Pass test level
|
|
35
|
+
* @ac US-085-AC-4: Pass target org
|
|
36
|
+
*/
|
|
37
|
+
export declare class SfCliIntegration {
|
|
38
|
+
deploy(options: DeploymentOptions): Promise<DeploymentResult>;
|
|
39
|
+
private buildDeployCommand;
|
|
40
|
+
private parseDeploymentOutput;
|
|
41
|
+
checkDeploymentStatus(deploymentId: string, targetOrg: string): Promise<DeploymentResult>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SF CLI Integration - US-085
|
|
3
|
+
* Executes deployments via official Salesforce CLI
|
|
4
|
+
*
|
|
5
|
+
* @ac US-085-AC-1: Execute sf project deploy start
|
|
6
|
+
* @ac US-085-AC-2: Pass manifest file
|
|
7
|
+
* @ac US-085-AC-3: Pass test level
|
|
8
|
+
* @ac US-085-AC-4: Pass target org
|
|
9
|
+
* @ac US-085-AC-5: Capture output
|
|
10
|
+
* @ac US-085-AC-6: Parse deployment results
|
|
11
|
+
* @issue #85
|
|
12
|
+
*/
|
|
13
|
+
import { exec } from 'node:child_process';
|
|
14
|
+
import { promisify } from 'node:util';
|
|
15
|
+
import { getLogger } from '../utils/logger.js';
|
|
16
|
+
const execAsync = promisify(exec);
|
|
17
|
+
const logger = getLogger('SfCliIntegration');
|
|
18
|
+
/**
|
|
19
|
+
* @ac US-085-AC-1: Execute sf project deploy start
|
|
20
|
+
* @ac US-085-AC-2: Pass manifest file
|
|
21
|
+
* @ac US-085-AC-3: Pass test level
|
|
22
|
+
* @ac US-085-AC-4: Pass target org
|
|
23
|
+
*/
|
|
24
|
+
export class SfCliIntegration {
|
|
25
|
+
async deploy(options) {
|
|
26
|
+
logger.info('Starting deployment', { options });
|
|
27
|
+
const command = this.buildDeployCommand(options);
|
|
28
|
+
try {
|
|
29
|
+
// AC-5: Capture output
|
|
30
|
+
const { stdout, stderr } = await execAsync(command);
|
|
31
|
+
const output = stdout + stderr;
|
|
32
|
+
// AC-6: Parse deployment results
|
|
33
|
+
const result = this.parseDeploymentOutput(output);
|
|
34
|
+
logger.info('Deployment completed', { result });
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
logger.error('Deployment failed', { error });
|
|
39
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
40
|
+
return this.parseDeploymentOutput(output, true);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
buildDeployCommand(options) {
|
|
44
|
+
const parts = [
|
|
45
|
+
'sf project deploy start',
|
|
46
|
+
`--manifest ${options.manifestPath}`,
|
|
47
|
+
`--target-org ${options.targetOrg}`,
|
|
48
|
+
'--json',
|
|
49
|
+
'--wait 60',
|
|
50
|
+
];
|
|
51
|
+
if (options.testLevel) {
|
|
52
|
+
parts.push(`--test-level ${options.testLevel}`);
|
|
53
|
+
}
|
|
54
|
+
if (options.tests && options.tests.length > 0) {
|
|
55
|
+
parts.push(`--tests ${options.tests.join(' ')}`);
|
|
56
|
+
}
|
|
57
|
+
if (options.checkOnly) {
|
|
58
|
+
parts.push('--dry-run');
|
|
59
|
+
}
|
|
60
|
+
return parts.join(' ');
|
|
61
|
+
}
|
|
62
|
+
parseDeploymentOutput(output, failed = false) {
|
|
63
|
+
try {
|
|
64
|
+
// Try to parse JSON output
|
|
65
|
+
const jsonMatch = output.match(/\{[\s\S]*\}/);
|
|
66
|
+
if (jsonMatch) {
|
|
67
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
68
|
+
return {
|
|
69
|
+
success: !failed && (parsed.result?.status === 'Succeeded' || parsed.result?.status === 'Success'),
|
|
70
|
+
deploymentId: parsed.result?.id,
|
|
71
|
+
status: parsed.result?.status ?? 'Unknown',
|
|
72
|
+
componentSuccesses: parsed.result?.numberComponentsDeployed ?? 0,
|
|
73
|
+
componentFailures: parsed.result?.numberComponentErrors ?? 0,
|
|
74
|
+
testsRun: parsed.result?.numberTestsTotal,
|
|
75
|
+
testFailures: parsed.result?.numberTestErrors,
|
|
76
|
+
output,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (parseError) {
|
|
81
|
+
logger.warn('Failed to parse deployment output', { parseError });
|
|
82
|
+
}
|
|
83
|
+
// Fallback for non-JSON output
|
|
84
|
+
return {
|
|
85
|
+
success: !failed,
|
|
86
|
+
status: failed ? 'Failed' : 'Unknown',
|
|
87
|
+
componentSuccesses: 0,
|
|
88
|
+
componentFailures: failed ? 1 : 0,
|
|
89
|
+
output,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async checkDeploymentStatus(deploymentId, targetOrg) {
|
|
93
|
+
const command = `sf project deploy report --job-id ${deploymentId} --target-org ${targetOrg} --json`;
|
|
94
|
+
try {
|
|
95
|
+
const { stdout } = await execAsync(command);
|
|
96
|
+
return this.parseDeploymentOutput(stdout);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
logger.error('Failed to check deployment status', { error, deploymentId });
|
|
100
|
+
const output = error instanceof Error ? error.message : String(error);
|
|
101
|
+
return this.parseDeploymentOutput(output, true);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=sf-cli-integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sf-cli-integration.js","sourceRoot":"","sources":["../../src/deployment/sf-cli-integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment State Persistence - US-089
|
|
3
|
+
* Saves deployment state for resume capability
|
|
4
|
+
*
|
|
5
|
+
* @ac US-089-AC-1: Save state after each wave
|
|
6
|
+
* @ac US-089-AC-2: Include completed waves
|
|
7
|
+
* @ac US-089-AC-3: Include failed wave details
|
|
8
|
+
* @ac US-089-AC-4: Support resume from failure
|
|
9
|
+
* @ac US-089-AC-5: Clean up state on success
|
|
10
|
+
* @ac US-089-AC-6: Include deployment metadata
|
|
11
|
+
* @issue #89
|
|
12
|
+
*/
|
|
13
|
+
import type { CycleSourceEditRecord } from './cycle-source-editor.js';
|
|
14
|
+
export type CycleRemediationState = {
|
|
15
|
+
cycleId: string;
|
|
16
|
+
strategy: 'comment-reference' | 'manual';
|
|
17
|
+
activePhase: 1 | 2;
|
|
18
|
+
startedAt: string;
|
|
19
|
+
completedPhases: Array<1 | 2>;
|
|
20
|
+
editRecords: CycleSourceEditRecord[];
|
|
21
|
+
};
|
|
22
|
+
export type DeploymentState = {
|
|
23
|
+
deploymentId: string;
|
|
24
|
+
targetOrg: string;
|
|
25
|
+
timestamp: string;
|
|
26
|
+
totalWaves: number;
|
|
27
|
+
completedWaves: number[];
|
|
28
|
+
currentWave?: number;
|
|
29
|
+
failedWave?: {
|
|
30
|
+
waveNumber: number;
|
|
31
|
+
error: string;
|
|
32
|
+
timestamp: string;
|
|
33
|
+
};
|
|
34
|
+
cycleRemediation?: CycleRemediationState;
|
|
35
|
+
metadata?: Record<string, unknown>;
|
|
36
|
+
};
|
|
37
|
+
export type StateManagerOptions = {
|
|
38
|
+
baseDir?: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* @ac US-089-AC-1: Save state after each wave
|
|
42
|
+
* @ac US-089-AC-2: Include completed waves
|
|
43
|
+
* @ac US-089-AC-3: Include failed wave details
|
|
44
|
+
*/
|
|
45
|
+
export declare class StateManager {
|
|
46
|
+
private readonly stateDir;
|
|
47
|
+
private readonly stateFile;
|
|
48
|
+
constructor(options?: StateManagerOptions);
|
|
49
|
+
saveState(state: DeploymentState): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* @ac US-089-AC-4: Support resume from failure
|
|
52
|
+
*/
|
|
53
|
+
loadState(): Promise<DeploymentState | null>;
|
|
54
|
+
/**
|
|
55
|
+
* @ac US-089-AC-5: Clean up state on success
|
|
56
|
+
*/
|
|
57
|
+
clearState(): Promise<void>;
|
|
58
|
+
hasFailedDeployment(): Promise<boolean>;
|
|
59
|
+
getStateFilePath(): string;
|
|
60
|
+
private normalizeState;
|
|
61
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment State Persistence - US-089
|
|
3
|
+
* Saves deployment state for resume capability
|
|
4
|
+
*
|
|
5
|
+
* @ac US-089-AC-1: Save state after each wave
|
|
6
|
+
* @ac US-089-AC-2: Include completed waves
|
|
7
|
+
* @ac US-089-AC-3: Include failed wave details
|
|
8
|
+
* @ac US-089-AC-4: Support resume from failure
|
|
9
|
+
* @ac US-089-AC-5: Clean up state on success
|
|
10
|
+
* @ac US-089-AC-6: Include deployment metadata
|
|
11
|
+
* @issue #89
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'node:fs/promises';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import { getLogger } from '../utils/logger.js';
|
|
16
|
+
const logger = getLogger('StateManager');
|
|
17
|
+
/**
|
|
18
|
+
* @ac US-089-AC-1: Save state after each wave
|
|
19
|
+
* @ac US-089-AC-2: Include completed waves
|
|
20
|
+
* @ac US-089-AC-3: Include failed wave details
|
|
21
|
+
*/
|
|
22
|
+
export class StateManager {
|
|
23
|
+
stateDir;
|
|
24
|
+
stateFile;
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
const baseDir = options.baseDir ?? process.cwd();
|
|
27
|
+
this.stateDir = path.join(baseDir, '.smart-deployment');
|
|
28
|
+
this.stateFile = path.join(this.stateDir, 'deployment-state.json');
|
|
29
|
+
}
|
|
30
|
+
async saveState(state) {
|
|
31
|
+
logger.info('Saving deployment state', { state });
|
|
32
|
+
await fs.mkdir(this.stateDir, { recursive: true });
|
|
33
|
+
await fs.writeFile(this.stateFile, JSON.stringify(state, null, 2), 'utf-8');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @ac US-089-AC-4: Support resume from failure
|
|
37
|
+
*/
|
|
38
|
+
async loadState() {
|
|
39
|
+
try {
|
|
40
|
+
const content = await fs.readFile(this.stateFile, 'utf-8');
|
|
41
|
+
const state = JSON.parse(content);
|
|
42
|
+
logger.info('Loaded deployment state', { state });
|
|
43
|
+
return this.normalizeState(state);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
logger.info('No previous deployment state found');
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* @ac US-089-AC-5: Clean up state on success
|
|
52
|
+
*/
|
|
53
|
+
async clearState() {
|
|
54
|
+
try {
|
|
55
|
+
await fs.unlink(this.stateFile);
|
|
56
|
+
logger.info('Cleared deployment state');
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// File doesn't exist, nothing to clear
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async hasFailedDeployment() {
|
|
63
|
+
const state = await this.loadState();
|
|
64
|
+
return state?.failedWave !== undefined;
|
|
65
|
+
}
|
|
66
|
+
getStateFilePath() {
|
|
67
|
+
return this.stateFile;
|
|
68
|
+
}
|
|
69
|
+
normalizeState(state) {
|
|
70
|
+
if (state.cycleRemediation === undefined) {
|
|
71
|
+
return state;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
...state,
|
|
75
|
+
cycleRemediation: {
|
|
76
|
+
...state.cycleRemediation,
|
|
77
|
+
completedPhases: [...state.cycleRemediation.completedPhases],
|
|
78
|
+
editRecords: [...state.cycleRemediation.editRecords],
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=state-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-manager.js","sourceRoot":"","sources":["../../src/deployment/state-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;AA+BzC;;;;GAIG;AACH,MAAM,OAAO,YAAY;IACN,QAAQ,CAAS;IACjB,SAAS,CAAS;IAEnC,YAAmB,UAA+B,EAAE;QAClD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACjD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACxD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;IACrE,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,KAAsB;QAC3C,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAElD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,SAAS;QACpB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,UAAU;QACrB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,mBAAmB;QAC9B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACrC,OAAO,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC;IACzC,CAAC;IAEM,gBAAgB;QACrB,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEO,cAAc,CAAC,KAAsB;QAC3C,IAAI,KAAK,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO;YACL,GAAG,KAAK;YACR,gBAAgB,EAAE;gBAChB,GAAG,KAAK,CAAC,gBAAgB;gBACzB,eAAe,EAAE,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,eAAe,CAAC;gBAC5D,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC;aACrD;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Execution Management - US-087
|
|
3
|
+
* Manages intelligent test execution per wave
|
|
4
|
+
*
|
|
5
|
+
* @ac US-087-AC-1: Run tests only in Apex waves
|
|
6
|
+
* @ac US-087-AC-2: Support RunLocalTests
|
|
7
|
+
* @ac US-087-AC-3: Support RunSpecifiedTests
|
|
8
|
+
* @ac US-087-AC-4: Support NoTestRun (sandbox)
|
|
9
|
+
* @ac US-087-AC-5: Track test results
|
|
10
|
+
* @ac US-087-AC-6: Report coverage
|
|
11
|
+
* @issue #87
|
|
12
|
+
*/
|
|
13
|
+
import type { Wave } from '../waves/wave-builder.js';
|
|
14
|
+
import type { TestLevel } from './sf-cli-integration.js';
|
|
15
|
+
export type TestExecutionPlan = {
|
|
16
|
+
testLevel: TestLevel;
|
|
17
|
+
tests: string[];
|
|
18
|
+
reason: string;
|
|
19
|
+
};
|
|
20
|
+
export type TestResults = {
|
|
21
|
+
testsRun: number;
|
|
22
|
+
testFailures: number;
|
|
23
|
+
coverage?: number;
|
|
24
|
+
failedTests: string[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @ac US-087-AC-1: Run tests only in Apex waves
|
|
28
|
+
* @ac US-087-AC-2: Support RunLocalTests
|
|
29
|
+
* @ac US-087-AC-3: Support RunSpecifiedTests
|
|
30
|
+
* @ac US-087-AC-4: Support NoTestRun (sandbox)
|
|
31
|
+
*/
|
|
32
|
+
export declare class TestExecutor {
|
|
33
|
+
determineTestLevel(wave: Wave, isSandbox: boolean): TestExecutionPlan;
|
|
34
|
+
private findRelatedTests;
|
|
35
|
+
/**
|
|
36
|
+
* @ac US-087-AC-5: Track test results
|
|
37
|
+
* @ac US-087-AC-6: Report coverage
|
|
38
|
+
*/
|
|
39
|
+
analyzeTestResults(testsRun: number, testFailures: number, coverage?: number): TestResults;
|
|
40
|
+
formatTestResults(results: TestResults): string;
|
|
41
|
+
}
|