@jterrats/smart-deployment 1.3.1 → 1.4.0
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 +38 -0
- package/lib/analysis/metadata-capability-definitions.d.ts +2 -0
- package/lib/analysis/metadata-capability-definitions.js +260 -0
- package/lib/analysis/metadata-capability-definitions.js.map +1 -0
- package/lib/analysis/metadata-capability-registry.d.ts +11 -0
- package/lib/analysis/metadata-capability-registry.js +142 -0
- package/lib/analysis/metadata-capability-registry.js.map +1 -0
- package/lib/analysis/metadata-gap-analysis-service.d.ts +51 -0
- package/lib/analysis/metadata-gap-analysis-service.js +277 -0
- package/lib/analysis/metadata-gap-analysis-service.js.map +1 -0
- package/lib/commands/ci-publish.d.ts +6 -2
- package/lib/commands/ci-publish.js +23 -8
- package/lib/commands/ci-publish.js.map +1 -1
- package/lib/commands/metadata/gaps.d.ts +15 -0
- package/lib/commands/metadata/gaps.js +84 -0
- package/lib/commands/metadata/gaps.js.map +1 -0
- package/lib/commands/resume.js +5 -4
- package/lib/commands/resume.js.map +1 -1
- package/lib/commands/start.d.ts +6 -0
- package/lib/commands/start.js +43 -14
- package/lib/commands/start.js.map +1 -1
- package/lib/commands/status.js +5 -2
- package/lib/commands/status.js.map +1 -1
- package/lib/commands/validate.d.ts +7 -0
- package/lib/commands/validate.js +24 -2
- package/lib/commands/validate.js.map +1 -1
- package/lib/constants/deployment-order.js +1 -0
- package/lib/constants/deployment-order.js.map +1 -1
- package/lib/deployment/commit-scope-service.d.ts +7 -0
- package/lib/deployment/commit-scope-service.js +104 -21
- package/lib/deployment/commit-scope-service.js.map +1 -1
- package/lib/deployment/deployment-runner.d.ts +1 -1
- package/lib/deployment/deployment-runner.js +23 -22
- package/lib/deployment/deployment-runner.js.map +1 -1
- package/lib/deployment/deployment-status-service.d.ts +8 -7
- package/lib/deployment/deployment-status-service.js +45 -27
- package/lib/deployment/deployment-status-service.js.map +1 -1
- package/lib/deployment/deployment-validation-service.d.ts +2 -0
- package/lib/deployment/deployment-validation-service.js +2 -0
- package/lib/deployment/deployment-validation-service.js.map +1 -1
- package/lib/deployment/resume-deployment-service.d.ts +5 -4
- package/lib/deployment/resume-deployment-service.js +18 -21
- package/lib/deployment/resume-deployment-service.js.map +1 -1
- package/lib/deployment/sf-cli-integration.d.ts +5 -2
- package/lib/deployment/sf-cli-integration.js +26 -14
- package/lib/deployment/sf-cli-integration.js.map +1 -1
- package/lib/deployment/special-deployment-plan.js +36 -49
- package/lib/deployment/special-deployment-plan.js.map +1 -1
- package/lib/deployment/start-execution-service.js +1 -1
- package/lib/deployment/start-execution-service.js.map +1 -1
- package/lib/presentation/release-report-presenter.d.ts +10 -0
- package/lib/presentation/release-report-presenter.js +35 -0
- package/lib/presentation/release-report-presenter.js.map +1 -0
- package/lib/presentation/validate-command-presenter.js +13 -0
- package/lib/presentation/validate-command-presenter.js.map +1 -1
- package/lib/reports/release-report-builder.d.ts +6 -0
- package/lib/reports/release-report-builder.js +115 -0
- package/lib/reports/release-report-builder.js.map +1 -0
- package/lib/reports/release-report-command-adapter.d.ts +14 -0
- package/lib/reports/release-report-command-adapter.js +28 -0
- package/lib/reports/release-report-command-adapter.js.map +1 -0
- package/lib/reports/release-report-facts-factory.d.ts +14 -0
- package/lib/reports/release-report-facts-factory.js +140 -0
- package/lib/reports/release-report-facts-factory.js.map +1 -0
- package/lib/reports/release-report-sanitizer.d.ts +5 -0
- package/lib/reports/release-report-sanitizer.js +120 -0
- package/lib/reports/release-report-sanitizer.js.map +1 -0
- package/lib/reports/release-report-service.d.ts +43 -0
- package/lib/reports/release-report-service.js +80 -0
- package/lib/reports/release-report-service.js.map +1 -0
- package/lib/reports/release-report-store.d.ts +30 -0
- package/lib/reports/release-report-store.js +57 -0
- package/lib/reports/release-report-store.js.map +1 -0
- package/lib/reports/start-release-report-coordinator.d.ts +15 -0
- package/lib/reports/start-release-report-coordinator.js +23 -0
- package/lib/reports/start-release-report-coordinator.js.map +1 -0
- package/lib/services/metadata-scanner-service.js +12 -2
- package/lib/services/metadata-scanner-service.js.map +1 -1
- package/lib/services/scanners/automation-ai-metadata-scanner.d.ts +2 -1
- package/lib/services/scanners/automation-ai-metadata-scanner.js +48 -0
- package/lib/services/scanners/automation-ai-metadata-scanner.js.map +1 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -1
- package/lib/types/metadata-capability.d.ts +39 -0
- package/lib/types/metadata-capability.js +2 -0
- package/lib/types/metadata-capability.js.map +1 -0
- package/lib/types/metadata.d.ts +7 -1
- package/lib/types/release-report.d.ts +89 -0
- package/lib/types/release-report.js +42 -0
- package/lib/types/release-report.js.map +1 -0
- package/messages/metadata.gaps.json +12 -0
- package/messages/start.json +2 -0
- package/messages/validate.json +3 -1
- package/npm-shrinkwrap.json +417 -901
- package/oclif.lock +415 -718
- package/oclif.manifest.json +93 -10
- package/package.json +18 -14
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DeploymentValidationSummary } from '../deployment/deployment-validation-service.js';
|
|
2
|
+
import type { DeploymentContext } from '../deployment/deployment-context-service.js';
|
|
3
|
+
import type { SpecialDeploymentExecutionResult } from '../deployment/special-deployment-executor.js';
|
|
4
|
+
import type { SpecialDeploymentPlan } from '../deployment/special-deployment-plan.js';
|
|
5
|
+
import type { ReleaseReportFacts } from '../types/release-report.js';
|
|
6
|
+
export declare function buildCiPublishReportFacts(plan: SpecialDeploymentPlan, execution?: SpecialDeploymentExecutionResult): ReleaseReportFacts;
|
|
7
|
+
export declare function buildValidationReportFacts(summary: DeploymentValidationSummary, targetOrg: string | undefined, useAI: boolean): ReleaseReportFacts;
|
|
8
|
+
export declare function buildStartReportFacts(context: DeploymentContext, options: {
|
|
9
|
+
targetOrg?: string;
|
|
10
|
+
dryRun: boolean;
|
|
11
|
+
validateOnly: boolean;
|
|
12
|
+
failed?: boolean;
|
|
13
|
+
warning?: string;
|
|
14
|
+
}): ReleaseReportFacts;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export function buildCiPublishReportFacts(plan, execution) {
|
|
2
|
+
const phases = plan.phases.map((phase) => toSpecialPhaseFact(phase, plan, execution));
|
|
3
|
+
const statusByPhase = new Map(phases.map((phase) => [phase.id, phase.status]));
|
|
4
|
+
return {
|
|
5
|
+
command: 'smart-deployment ci-publish',
|
|
6
|
+
targetOrg: plan.targetOrg,
|
|
7
|
+
analysisMode: 'deterministic',
|
|
8
|
+
enrichment: { status: 'skipped' },
|
|
9
|
+
outcome: execution ? (execution.success ? 'succeeded' : 'failed') : plan.success ? 'skipped' : 'failed',
|
|
10
|
+
phases,
|
|
11
|
+
items: plan.phases.flatMap((phase) => phase.components.map((component) => toItem(component, phase.kind, operationForPhase(phase.kind), routeForPhase(phase.kind), statusByPhase.get(phase.kind), plan.targetOrg))),
|
|
12
|
+
reportWarnings: [...plan.warnings, ...plan.errors],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function buildValidationReportFacts(summary, targetOrg, useAI) {
|
|
16
|
+
const status = summary.valid ? 'succeeded' : 'needs_review';
|
|
17
|
+
return {
|
|
18
|
+
command: 'smart-deployment validate',
|
|
19
|
+
targetOrg,
|
|
20
|
+
analysisMode: summary.aiAnalyzed ? 'ai_enriched' : 'deterministic',
|
|
21
|
+
enrichment: {
|
|
22
|
+
status: summary.aiAnalyzed ? 'available' : useAI ? 'unavailable' : 'skipped',
|
|
23
|
+
warnings: useAI && !summary.aiAnalyzed
|
|
24
|
+
? ['AI validation unavailable; deterministic validation was retained.']
|
|
25
|
+
: undefined,
|
|
26
|
+
},
|
|
27
|
+
outcome: summary.valid ? 'succeeded' : 'failed',
|
|
28
|
+
phases: [
|
|
29
|
+
{
|
|
30
|
+
id: 'validation',
|
|
31
|
+
route: 'validation',
|
|
32
|
+
operation: 'validate',
|
|
33
|
+
status,
|
|
34
|
+
remediation: summary.issues.map((issue) => issue.message),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
items: summary.componentIds.map((component) => toItem(component, 'validation', 'validate', 'validation', status, targetOrg)),
|
|
38
|
+
reportWarnings: summary.issues.map((issue) => issue.message),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function buildStartReportFacts(context, options) {
|
|
42
|
+
const operation = options.validateOnly ? 'validate' : 'deploy';
|
|
43
|
+
const status = options.failed ? 'failed' : options.dryRun ? 'skipped' : 'succeeded';
|
|
44
|
+
const phaseId = options.validateOnly ? 'validation' : 'core-metadata';
|
|
45
|
+
const route = options.validateOnly ? 'validation' : 'salesforce-metadata';
|
|
46
|
+
const aiContext = context.aiContext;
|
|
47
|
+
const isAIEnriched = aiContext?.enabled === true && aiContext.fallback !== true && aiContext.inferenceFallback !== true;
|
|
48
|
+
return {
|
|
49
|
+
command: 'smart-deployment start',
|
|
50
|
+
targetOrg: options.targetOrg,
|
|
51
|
+
analysisMode: isAIEnriched ? 'ai_enriched' : 'deterministic',
|
|
52
|
+
enrichment: {
|
|
53
|
+
status: isAIEnriched ? 'available' : aiContext?.enabled ? 'partial' : 'skipped',
|
|
54
|
+
warnings: aiContext?.enabled && !isAIEnriched
|
|
55
|
+
? ['AI enrichment was partial; deterministic planning was retained.']
|
|
56
|
+
: undefined,
|
|
57
|
+
},
|
|
58
|
+
outcome: options.failed ? 'failed' : options.dryRun ? 'skipped' : 'succeeded',
|
|
59
|
+
phases: [
|
|
60
|
+
{
|
|
61
|
+
id: phaseId,
|
|
62
|
+
route,
|
|
63
|
+
operation,
|
|
64
|
+
status,
|
|
65
|
+
remediation: options.warning ? [options.warning] : undefined,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
items: context.scanResult.components.map((component) => ({
|
|
69
|
+
phaseId,
|
|
70
|
+
metadataType: component.type,
|
|
71
|
+
fullName: component.name,
|
|
72
|
+
route,
|
|
73
|
+
operation,
|
|
74
|
+
status,
|
|
75
|
+
targetOrg: options.targetOrg,
|
|
76
|
+
})),
|
|
77
|
+
reportWarnings: options.warning ? [options.warning] : undefined,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function toSpecialPhaseFact(phase, plan, execution) {
|
|
81
|
+
const status = specialPhaseStatus(phase, plan, execution);
|
|
82
|
+
const commandResults = execution?.commands.filter((result) => result.phaseKind === phase.kind) ?? [];
|
|
83
|
+
return {
|
|
84
|
+
id: phase.kind,
|
|
85
|
+
route: routeForPhase(phase.kind),
|
|
86
|
+
operation: operationForPhase(phase.kind),
|
|
87
|
+
status,
|
|
88
|
+
evidence: phase.commands.map((command, index) => {
|
|
89
|
+
const result = commandResults[index];
|
|
90
|
+
return {
|
|
91
|
+
tool: command.tool,
|
|
92
|
+
operationId: `${phase.kind}:${index + 1}`,
|
|
93
|
+
exitCode: result?.exitCode ?? (result?.success ? 0 : undefined),
|
|
94
|
+
};
|
|
95
|
+
}),
|
|
96
|
+
remediation: [...(phase.errors ?? []), ...(phase.warnings ?? []), ...(phase.skipReason ? [phase.skipReason] : [])],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function specialPhaseStatus(phase, plan, execution) {
|
|
100
|
+
if ((phase.errors?.length ?? 0) > 0 || execution?.failedPhase === phase.kind)
|
|
101
|
+
return 'failed';
|
|
102
|
+
if (phase.skipped || execution?.skippedPhases.includes(phase.kind))
|
|
103
|
+
return 'skipped';
|
|
104
|
+
if (!execution)
|
|
105
|
+
return plan.dryRun ? 'skipped' : 'unknown';
|
|
106
|
+
if (execution.completedPhases.includes(phase.kind))
|
|
107
|
+
return 'succeeded';
|
|
108
|
+
return execution.success ? 'succeeded' : 'skipped';
|
|
109
|
+
}
|
|
110
|
+
function routeForPhase(kind) {
|
|
111
|
+
const routes = {
|
|
112
|
+
'core-metadata': 'salesforce-metadata',
|
|
113
|
+
'agentforce-publish': 'agentforce',
|
|
114
|
+
'agentforce-activate': 'agentforce',
|
|
115
|
+
'ai-evaluations': 'ai-evaluation',
|
|
116
|
+
'community-publish': 'experience-cloud',
|
|
117
|
+
'omnistudio-vlocity': 'omnistudio',
|
|
118
|
+
};
|
|
119
|
+
return routes[kind];
|
|
120
|
+
}
|
|
121
|
+
function operationForPhase(kind) {
|
|
122
|
+
if (kind === 'agentforce-activate')
|
|
123
|
+
return 'activate';
|
|
124
|
+
if (kind === 'agentforce-publish' || kind === 'community-publish' || kind === 'omnistudio-vlocity')
|
|
125
|
+
return 'publish';
|
|
126
|
+
return 'deploy';
|
|
127
|
+
}
|
|
128
|
+
function toItem(component, phaseId, operation, route, status, targetOrg) {
|
|
129
|
+
const separator = component.indexOf(':');
|
|
130
|
+
return {
|
|
131
|
+
phaseId,
|
|
132
|
+
metadataType: separator > 0 ? component.slice(0, separator) : 'Unknown',
|
|
133
|
+
fullName: separator > 0 ? component.slice(separator + 1) : component,
|
|
134
|
+
route,
|
|
135
|
+
operation,
|
|
136
|
+
status: status ?? 'unknown',
|
|
137
|
+
targetOrg,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=release-report-facts-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-report-facts-factory.js","sourceRoot":"","sources":["../../src/reports/release-report-facts-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReleaseReportV1 } from '../types/release-report.js';
|
|
2
|
+
export type ReleaseReportSanitizerOptions = {
|
|
3
|
+
projectRoot?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function sanitizeReleaseReport(report: ReleaseReportV1, options?: ReleaseReportSanitizerOptions): ReleaseReportV1;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
const ANSI_SEQUENCE = new RegExp(`${String.fromCharCode(27)}(?:\\][^${String.fromCharCode(7)}]*(?:${String.fromCharCode(7)}|${String.fromCharCode(27)}\\\\)|\\[[0-?]*[ -/]*[@-~])`, 'gu');
|
|
3
|
+
const CONTROL_CHARACTER = new RegExp(`[${String.fromCharCode(0)}-${String.fromCharCode(8)}${String.fromCharCode(11)}${String.fromCharCode(12)}${String.fromCharCode(14)}-${String.fromCharCode(31)}${String.fromCharCode(127)}-${String.fromCharCode(159)}]`, 'gu');
|
|
4
|
+
const AUTH_URL = /\b(?:force|sfdx):\/\/[^\s]+/giu;
|
|
5
|
+
const BEARER_TOKEN = /\bBearer\s+[A-Za-z0-9._~+/-]+=*/giu;
|
|
6
|
+
const CREDENTIAL_ASSIGNMENT = /\b(access[_-]?token|auth(?:orization)?|client[_-]?secret|password|refresh[_-]?token|secret|token)\s*[:=]\s*[^\s,;]+/giu;
|
|
7
|
+
export function sanitizeReleaseReport(report, options = {}) {
|
|
8
|
+
return {
|
|
9
|
+
schemaVersion: report.schemaVersion,
|
|
10
|
+
generatedAt: report.generatedAt,
|
|
11
|
+
command: sanitizeText(report.command, 128),
|
|
12
|
+
targetOrg: optionalText(report.targetOrg, 256),
|
|
13
|
+
analysisMode: report.analysisMode,
|
|
14
|
+
enrichment: {
|
|
15
|
+
status: report.enrichment.status,
|
|
16
|
+
warnings: sanitizeList(report.enrichment.warnings, 1000),
|
|
17
|
+
},
|
|
18
|
+
outcome: report.outcome,
|
|
19
|
+
summary: { ...report.summary },
|
|
20
|
+
phases: report.phases.map((phase) => sanitizePhase(phase, options)),
|
|
21
|
+
items: report.items.map((item) => sanitizeItem(item, options)),
|
|
22
|
+
reportWarnings: sanitizeList(report.reportWarnings, 1000) ?? [],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function sanitizePhase(phase, options) {
|
|
26
|
+
return {
|
|
27
|
+
id: phase.id,
|
|
28
|
+
route: phase.route,
|
|
29
|
+
operation: phase.operation,
|
|
30
|
+
status: phase.status,
|
|
31
|
+
evidence: phase.evidence?.map((entry) => sanitizeEvidence(entry, options)),
|
|
32
|
+
remediation: sanitizeList(phase.remediation, 1000),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function sanitizeItem(item, options) {
|
|
36
|
+
return {
|
|
37
|
+
phaseId: item.phaseId,
|
|
38
|
+
metadataType: sanitizeText(item.metadataType, 256),
|
|
39
|
+
fullName: sanitizeText(item.fullName, 512),
|
|
40
|
+
route: item.route,
|
|
41
|
+
operation: item.operation,
|
|
42
|
+
status: item.status,
|
|
43
|
+
targetOrg: optionalText(item.targetOrg, 256),
|
|
44
|
+
evidenceReferences: sanitizeReferences(item.evidenceReferences, options.projectRoot),
|
|
45
|
+
remediation: sanitizeList(item.remediation, 1000),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function sanitizeEvidence(evidence, options) {
|
|
49
|
+
return {
|
|
50
|
+
tool: evidence.tool,
|
|
51
|
+
operationId: sanitizeText(evidence.operationId, 256),
|
|
52
|
+
exitCode: Number.isSafeInteger(evidence.exitCode) ? evidence.exitCode : undefined,
|
|
53
|
+
deploymentId: optionalText(evidence.deploymentId, 256),
|
|
54
|
+
artifact: sanitizeReference(evidence.artifact, options.projectRoot),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function sanitizeReferences(references, projectRoot) {
|
|
58
|
+
if (!references)
|
|
59
|
+
return undefined;
|
|
60
|
+
const safe = references
|
|
61
|
+
.map((reference) => sanitizeReference(reference, projectRoot))
|
|
62
|
+
.filter((reference) => reference !== undefined);
|
|
63
|
+
return safe.length > 0 ? [...new Set(safe)].sort() : undefined;
|
|
64
|
+
}
|
|
65
|
+
function sanitizeReference(reference, projectRoot) {
|
|
66
|
+
if (!reference)
|
|
67
|
+
return undefined;
|
|
68
|
+
const clean = sanitizeText(reference, 1024);
|
|
69
|
+
const pathApi = isWindowsPath(clean) || (projectRoot ? isWindowsPath(projectRoot) : false) ? path.win32 : path;
|
|
70
|
+
const resolvedRoot = projectRoot ? pathApi.resolve(projectRoot) : undefined;
|
|
71
|
+
const candidate = pathApi.isAbsolute(clean) ? pathApi.resolve(clean) : pathApi.resolve(resolvedRoot ?? '.', clean);
|
|
72
|
+
if (pathApi.isAbsolute(clean)) {
|
|
73
|
+
if (!resolvedRoot)
|
|
74
|
+
return undefined;
|
|
75
|
+
const relative = pathApi.relative(resolvedRoot, candidate);
|
|
76
|
+
if (!isSafeRelativePath(relative, pathApi))
|
|
77
|
+
return undefined;
|
|
78
|
+
return normalizeReference(relative);
|
|
79
|
+
}
|
|
80
|
+
if (!isSafeRelativePath(clean, pathApi))
|
|
81
|
+
return undefined;
|
|
82
|
+
return normalizeReference(clean);
|
|
83
|
+
}
|
|
84
|
+
function isSafeRelativePath(reference, pathApi) {
|
|
85
|
+
return (reference.length > 0 &&
|
|
86
|
+
!pathApi.isAbsolute(reference) &&
|
|
87
|
+
reference !== '..' &&
|
|
88
|
+
!reference.startsWith('../') &&
|
|
89
|
+
!reference.startsWith('..\\'));
|
|
90
|
+
}
|
|
91
|
+
function isWindowsPath(reference) {
|
|
92
|
+
return /^[A-Za-z]:[\\/]/u.test(reference) || reference.startsWith('\\\\');
|
|
93
|
+
}
|
|
94
|
+
function normalizeReference(reference) {
|
|
95
|
+
return reference.replaceAll('\\', '/').split(path.sep).join('/');
|
|
96
|
+
}
|
|
97
|
+
function sanitizeList(values, maxLength) {
|
|
98
|
+
if (!values)
|
|
99
|
+
return undefined;
|
|
100
|
+
const safe = values.map((value) => sanitizeText(value, maxLength)).filter((value) => value.length > 0);
|
|
101
|
+
return safe.length > 0 ? [...new Set(safe)].sort() : undefined;
|
|
102
|
+
}
|
|
103
|
+
function optionalText(value, maxLength) {
|
|
104
|
+
if (value === undefined)
|
|
105
|
+
return undefined;
|
|
106
|
+
const safe = sanitizeText(value, maxLength);
|
|
107
|
+
return safe.length > 0 ? safe : undefined;
|
|
108
|
+
}
|
|
109
|
+
function sanitizeText(value, maxLength) {
|
|
110
|
+
const redacted = value
|
|
111
|
+
.replace(ANSI_SEQUENCE, '')
|
|
112
|
+
.replace(CONTROL_CHARACTER, '')
|
|
113
|
+
.replace(AUTH_URL, '[REDACTED]')
|
|
114
|
+
.replace(BEARER_TOKEN, 'Bearer [REDACTED]')
|
|
115
|
+
.replace(CREDENTIAL_ASSIGNMENT, '$1=[REDACTED]')
|
|
116
|
+
.replace(/\s+/gu, ' ')
|
|
117
|
+
.trim();
|
|
118
|
+
return redacted.length <= maxLength ? redacted : `${redacted.slice(0, maxLength - 3)}...`;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=release-report-sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-report-sanitizer.js","sourceRoot":"","sources":["../../src/reports/release-report-sanitizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ReleaseReportFacts, ReleaseReportV1 } from '../types/release-report.js';
|
|
2
|
+
import { type ReleaseReportSanitizerOptions } from './release-report-sanitizer.js';
|
|
3
|
+
import { type ReleaseReportStoreOptions } from './release-report-store.js';
|
|
4
|
+
export type UnderlyingOperationResult<T> = {
|
|
5
|
+
kind: 'succeeded';
|
|
6
|
+
value: T;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'failed';
|
|
9
|
+
error: unknown;
|
|
10
|
+
};
|
|
11
|
+
export type ReleaseReportFailureStage = 'build' | 'sanitize' | 'serialize' | 'persist';
|
|
12
|
+
export type ReleaseReportFinalization = {
|
|
13
|
+
kind: 'written';
|
|
14
|
+
report: ReleaseReportV1;
|
|
15
|
+
path: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'unavailable';
|
|
18
|
+
stage: ReleaseReportFailureStage;
|
|
19
|
+
warning: string;
|
|
20
|
+
report?: ReleaseReportV1;
|
|
21
|
+
};
|
|
22
|
+
export type ReleaseReportServiceResult<T> = {
|
|
23
|
+
underlying: UnderlyingOperationResult<T>;
|
|
24
|
+
report: ReleaseReportFinalization;
|
|
25
|
+
};
|
|
26
|
+
export type ReleaseReportServiceOptions = ReleaseReportStoreOptions & ReleaseReportSanitizerOptions;
|
|
27
|
+
export type ReleaseReportServiceDependencies = {
|
|
28
|
+
build: (facts: ReleaseReportFacts) => ReleaseReportV1;
|
|
29
|
+
sanitize: (report: ReleaseReportV1, options: ReleaseReportSanitizerOptions) => ReleaseReportV1;
|
|
30
|
+
serialize: (report: ReleaseReportV1) => string;
|
|
31
|
+
store: (serializedReport: string, options: ReleaseReportStoreOptions) => Promise<{
|
|
32
|
+
kind: 'written';
|
|
33
|
+
path: string;
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'unavailable';
|
|
36
|
+
warning: string;
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
39
|
+
export declare class ReleaseReportService {
|
|
40
|
+
private readonly dependencies;
|
|
41
|
+
constructor(dependencies?: Partial<ReleaseReportServiceDependencies>);
|
|
42
|
+
finalize<T>(underlying: UnderlyingOperationResult<T>, facts: ReleaseReportFacts, options: ReleaseReportServiceOptions): Promise<ReleaseReportServiceResult<T>>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ReleaseReportBuilder } from './release-report-builder.js';
|
|
2
|
+
import { sanitizeReleaseReport } from './release-report-sanitizer.js';
|
|
3
|
+
import { ReleaseReportStore } from './release-report-store.js';
|
|
4
|
+
export class ReleaseReportService {
|
|
5
|
+
dependencies;
|
|
6
|
+
constructor(dependencies) {
|
|
7
|
+
const builder = new ReleaseReportBuilder();
|
|
8
|
+
const store = new ReleaseReportStore();
|
|
9
|
+
this.dependencies = {
|
|
10
|
+
build: (facts) => builder.build(facts),
|
|
11
|
+
sanitize: sanitizeReleaseReport,
|
|
12
|
+
serialize: serializeReleaseReport,
|
|
13
|
+
store: async (serializedReport, options) => store.write(serializedReport, options),
|
|
14
|
+
...dependencies,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async finalize(underlying, facts, options) {
|
|
18
|
+
const built = attempt('build', () => this.dependencies.build(facts));
|
|
19
|
+
if (built.kind === 'unavailable')
|
|
20
|
+
return { underlying, report: built };
|
|
21
|
+
const sanitized = attempt('sanitize', () => this.dependencies.sanitize(built.report, options));
|
|
22
|
+
if (sanitized.kind === 'unavailable')
|
|
23
|
+
return { underlying, report: sanitized };
|
|
24
|
+
const serialized = attemptSerialization(() => this.dependencies.serialize(sanitized.report), sanitized.report);
|
|
25
|
+
if (serialized.kind === 'unavailable')
|
|
26
|
+
return { underlying, report: serialized };
|
|
27
|
+
try {
|
|
28
|
+
const persistence = await this.dependencies.store(serialized.content, options);
|
|
29
|
+
if (persistence.kind === 'unavailable') {
|
|
30
|
+
return {
|
|
31
|
+
underlying,
|
|
32
|
+
report: {
|
|
33
|
+
kind: 'unavailable',
|
|
34
|
+
stage: 'persist',
|
|
35
|
+
warning: persistence.warning,
|
|
36
|
+
report: sanitized.report,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
underlying,
|
|
42
|
+
report: { kind: 'written', report: sanitized.report, path: persistence.path },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return {
|
|
47
|
+
underlying,
|
|
48
|
+
report: {
|
|
49
|
+
kind: 'unavailable',
|
|
50
|
+
stage: 'persist',
|
|
51
|
+
warning: warningFor('persist'),
|
|
52
|
+
report: sanitized.report,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function attempt(stage, operation) {
|
|
59
|
+
try {
|
|
60
|
+
return { kind: 'available', report: operation() };
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return { kind: 'unavailable', stage, warning: warningFor(stage) };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function attemptSerialization(operation, report) {
|
|
67
|
+
try {
|
|
68
|
+
return { kind: 'serialized', content: operation() };
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return { kind: 'unavailable', stage: 'serialize', warning: warningFor('serialize'), report };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function serializeReleaseReport(report) {
|
|
75
|
+
return `${JSON.stringify(report, null, 2)}\n`;
|
|
76
|
+
}
|
|
77
|
+
function warningFor(stage) {
|
|
78
|
+
return `Release report ${stage} is unavailable; the underlying operation result is unchanged.`;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=release-report-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-report-service.js","sourceRoot":"","sources":["../../src/reports/release-report-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type ReleaseReportStoreResult = {
|
|
2
|
+
kind: 'written';
|
|
3
|
+
path: string;
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'unavailable';
|
|
6
|
+
warning: string;
|
|
7
|
+
};
|
|
8
|
+
export type ReleaseReportStoreOptions = {
|
|
9
|
+
projectRoot: string;
|
|
10
|
+
reportDir?: string;
|
|
11
|
+
};
|
|
12
|
+
type AtomicFileHandle = {
|
|
13
|
+
writeFile: (content: string, encoding: BufferEncoding) => Promise<void>;
|
|
14
|
+
sync: () => Promise<void>;
|
|
15
|
+
close: () => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
export type ReleaseReportFileSystem = {
|
|
18
|
+
mkdir: (directory: string) => Promise<void>;
|
|
19
|
+
openExclusive: (filePath: string) => Promise<AtomicFileHandle>;
|
|
20
|
+
rename: (source: string, destination: string) => Promise<void>;
|
|
21
|
+
unlink: (filePath: string) => Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
export declare class ReleaseReportStore {
|
|
24
|
+
private readonly fileSystem;
|
|
25
|
+
private readonly temporaryPathFactory;
|
|
26
|
+
constructor(fileSystem?: ReleaseReportFileSystem, temporaryPathFactory?: (finalPath: string) => string);
|
|
27
|
+
resolvePath(options: ReleaseReportStoreOptions): string;
|
|
28
|
+
write(serializedReport: string, options: ReleaseReportStoreOptions): Promise<ReleaseReportStoreResult>;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { mkdir, open, rename, unlink } from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
const DEFAULT_REPORT_DIRECTORY = '.smart-deployment/reports';
|
|
4
|
+
const RELEASE_REPORT_FILE_NAME = 'release-report.json';
|
|
5
|
+
let temporarySequence = 0;
|
|
6
|
+
const NODE_FILE_SYSTEM = {
|
|
7
|
+
mkdir: async (directory) => mkdir(directory, { recursive: true }).then(() => undefined),
|
|
8
|
+
openExclusive: async (filePath) => open(filePath, 'wx'),
|
|
9
|
+
rename,
|
|
10
|
+
unlink,
|
|
11
|
+
};
|
|
12
|
+
export class ReleaseReportStore {
|
|
13
|
+
fileSystem;
|
|
14
|
+
temporaryPathFactory;
|
|
15
|
+
constructor(fileSystem = NODE_FILE_SYSTEM, temporaryPathFactory = defaultTemporaryPath) {
|
|
16
|
+
this.fileSystem = fileSystem;
|
|
17
|
+
this.temporaryPathFactory = temporaryPathFactory;
|
|
18
|
+
}
|
|
19
|
+
resolvePath(options) {
|
|
20
|
+
const directory = options.reportDir
|
|
21
|
+
? path.resolve(options.projectRoot, options.reportDir)
|
|
22
|
+
: path.resolve(options.projectRoot, DEFAULT_REPORT_DIRECTORY);
|
|
23
|
+
return path.join(directory, RELEASE_REPORT_FILE_NAME);
|
|
24
|
+
}
|
|
25
|
+
async write(serializedReport, options) {
|
|
26
|
+
const finalPath = this.resolvePath(options);
|
|
27
|
+
const temporaryPath = this.temporaryPathFactory(finalPath);
|
|
28
|
+
let handle;
|
|
29
|
+
try {
|
|
30
|
+
await this.fileSystem.mkdir(path.dirname(finalPath));
|
|
31
|
+
handle = await this.fileSystem.openExclusive(temporaryPath);
|
|
32
|
+
await handle.writeFile(serializedReport, 'utf8');
|
|
33
|
+
await handle.sync();
|
|
34
|
+
await handle.close();
|
|
35
|
+
handle = undefined;
|
|
36
|
+
await this.fileSystem.rename(temporaryPath, finalPath);
|
|
37
|
+
return { kind: 'written', path: finalPath };
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
await closeBestEffort(handle);
|
|
41
|
+
await this.fileSystem.unlink(temporaryPath).catch(() => undefined);
|
|
42
|
+
return {
|
|
43
|
+
kind: 'unavailable',
|
|
44
|
+
warning: 'Release report persistence is unavailable; the underlying operation result is unchanged.',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function closeBestEffort(handle) {
|
|
50
|
+
if (handle)
|
|
51
|
+
await handle.close().catch(() => undefined);
|
|
52
|
+
}
|
|
53
|
+
function defaultTemporaryPath(finalPath) {
|
|
54
|
+
temporarySequence += 1;
|
|
55
|
+
return `${finalPath}.${process.pid}.${temporarySequence}.tmp`;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=release-report-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-report-store.js","sourceRoot":"","sources":["../../src/reports/release-report-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DeploymentContext } from '../deployment/deployment-context-service.js';
|
|
2
|
+
import type { ReleaseReportPresenterIO } from '../presentation/release-report-presenter.js';
|
|
3
|
+
import { ReleaseReportCommandAdapter, type ReleaseReportCommandOutput } from './release-report-command-adapter.js';
|
|
4
|
+
export type StartReleaseReportOptions = {
|
|
5
|
+
targetOrg?: string;
|
|
6
|
+
dryRun: boolean;
|
|
7
|
+
validateOnly: boolean;
|
|
8
|
+
reportDir?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare class StartReleaseReportCoordinator {
|
|
11
|
+
private readonly adapter;
|
|
12
|
+
constructor(adapter?: ReleaseReportCommandAdapter);
|
|
13
|
+
finalizeSuccess<T>(io: ReleaseReportPresenterIO, result: T, context: DeploymentContext, options: StartReleaseReportOptions): Promise<T & ReleaseReportCommandOutput>;
|
|
14
|
+
finalizeFailure(io: ReleaseReportPresenterIO, error: unknown, context: DeploymentContext, options: StartReleaseReportOptions): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ReleaseReportCommandAdapter } from './release-report-command-adapter.js';
|
|
2
|
+
import { buildStartReportFacts } from './release-report-facts-factory.js';
|
|
3
|
+
export class StartReleaseReportCoordinator {
|
|
4
|
+
adapter;
|
|
5
|
+
constructor(adapter = new ReleaseReportCommandAdapter()) {
|
|
6
|
+
this.adapter = adapter;
|
|
7
|
+
}
|
|
8
|
+
async finalizeSuccess(io, result, context, options) {
|
|
9
|
+
const releaseReport = await this.adapter.finalize(io, { kind: 'succeeded', value: result }, buildStartReportFacts(context, options), {
|
|
10
|
+
projectRoot: context.scanResult.projectRoot,
|
|
11
|
+
reportDir: options.reportDir,
|
|
12
|
+
});
|
|
13
|
+
return { ...result, ...releaseReport };
|
|
14
|
+
}
|
|
15
|
+
async finalizeFailure(io, error, context, options) {
|
|
16
|
+
const warning = error instanceof Error ? error.message : String(error);
|
|
17
|
+
await this.adapter.finalize(io, { kind: 'failed', error }, buildStartReportFacts(context, { ...options, failed: true, warning }), {
|
|
18
|
+
projectRoot: context.scanResult.projectRoot,
|
|
19
|
+
reportDir: options.reportDir,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=start-release-report-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-release-report-coordinator.js","sourceRoot":"","sources":["../../src/reports/start-release-report-coordinator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAmC,MAAM,qCAAqC,CAAC;AACnH,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAS1E,MAAM,OAAO,6BAA6B;IACJ;IAApC,YAAoC,UAAU,IAAI,2BAA2B,EAAE;QAA3C,YAAO,GAAP,OAAO,CAAoC;IAAG,CAAC;IAE5E,KAAK,CAAC,eAAe,CAC1B,EAA4B,EAC5B,MAAS,EACT,OAA0B,EAC1B,OAAkC;QAElC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAC/C,EAAE,EACF,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,EACpC,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,EACvC;YACE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,WAAW;YAC3C,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CACF,CAAC;QACF,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;IACzC,CAAC;IAEM,KAAK,CAAC,eAAe,CAC1B,EAA4B,EAC5B,KAAc,EACd,OAA0B,EAC1B,OAAkC;QAElC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CACzB,EAAE,EACF,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EACzB,qBAAqB,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACrE;YACE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,WAAW;YAC3C,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -13,7 +13,7 @@ import { DependencyGraphBuilder } from '../dependencies/dependency-graph-builder
|
|
|
13
13
|
import { ForceIgnoreParser } from '../scanner/forceignore-parser.js';
|
|
14
14
|
import { SfdxProjectDetector } from '../scanner/sfdx-project-detector.js';
|
|
15
15
|
import { getLogger } from '../utils/logger.js';
|
|
16
|
-
import { parseAiAuthoringBundleComponent, parseBotComponent, parseFlowComponent, parseGenAiPlannerBundleComponent, parseGenAiPromptComponent, } from './scanners/automation-ai-metadata-scanner.js';
|
|
16
|
+
import { parseAiEvaluationDefinitionComponent, parseAiAuthoringBundleComponent, parseBotComponent, parseFlowComponent, parseGenAiPlannerBundleComponent, parseGenAiPromptComponent, } from './scanners/automation-ai-metadata-scanner.js';
|
|
17
17
|
import { CODE_DIRECTORY_SCANNERS, CODE_FILE_SCANNERS } from './scanners/code-metadata-scanner.js';
|
|
18
18
|
import { parseCustomMetadataComponents, parseCustomObjectComponent } from './scanners/data-metadata-scanner.js';
|
|
19
19
|
import { parseEmailTemplateComponent, parseFlexiPageComponent, parseLayoutComponent, parseVisualforceComponent, } from './scanners/experience-metadata-scanner.js';
|
|
@@ -156,9 +156,16 @@ export class MetadataScannerService {
|
|
|
156
156
|
const botComponents = await scanMetadataFiles(packagePath, '**/bots/**/*.bot-meta.xml', errors, 'Bot', this.shouldIgnorePath, parseBotComponent);
|
|
157
157
|
const genAiPromptComponents = await scanMetadataFiles(packagePath, '**/genaiPromptTemplates/**/*.genAiPromptTemplate-meta.xml', errors, 'GenAI Prompt', this.shouldIgnorePath, parseGenAiPromptComponent);
|
|
158
158
|
const aiAuthoringBundleComponents = await scanMetadataFiles(packagePath, '**/aiAuthoringBundles/**/*.agent', errors, 'AiAuthoringBundle', this.shouldIgnorePath, (filePath) => Promise.resolve(parseAiAuthoringBundleComponent(filePath)));
|
|
159
|
+
const aiEvaluationDefinitionComponents = (await scanMetadataFiles(packagePath, '**/aiEvaluationDefinitions/**/*.aiEvaluationDefinition-meta.xml', errors, 'AiEvaluationDefinition', this.shouldIgnorePath, parseAiEvaluationDefinitionComponent)).sort((left, right) => normalizePath(left.filePath).localeCompare(normalizePath(right.filePath)));
|
|
159
160
|
const authoringBundleNames = new Set(aiAuthoringBundleComponents.map((component) => component.name));
|
|
160
161
|
const genAiPlannerBundleComponents = (await scanMetadataDirectories(packagePath, '**/genAiPlannerBundles/*', errors, 'GenAiPlannerBundle', this.shouldIgnorePath, parseGenAiPlannerBundleComponent)).filter((component) => !authoringBundleNames.has(component.name));
|
|
161
|
-
return [
|
|
162
|
+
return [
|
|
163
|
+
...botComponents,
|
|
164
|
+
...genAiPromptComponents,
|
|
165
|
+
...aiAuthoringBundleComponents,
|
|
166
|
+
...aiEvaluationDefinitionComponents,
|
|
167
|
+
...genAiPlannerBundleComponents,
|
|
168
|
+
];
|
|
162
169
|
}
|
|
163
170
|
async scanAdditionalMetadata(packagePath, errors) {
|
|
164
171
|
return scanAdditionalMetadata(packagePath, errors, this.shouldIgnorePath);
|
|
@@ -179,4 +186,7 @@ export class MetadataScannerService {
|
|
|
179
186
|
return this.forceIgnoreParser.isIgnored(filePath);
|
|
180
187
|
}
|
|
181
188
|
}
|
|
189
|
+
function normalizePath(filePath) {
|
|
190
|
+
return filePath.split(path.sep).join('/');
|
|
191
|
+
}
|
|
182
192
|
//# sourceMappingURL=metadata-scanner-service.js.map
|