@fjall/deploy-core 0.89.5 → 0.89.6
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/LICENSE +50 -21
- package/README.md +25 -0
- package/dist/.minified +1 -0
- package/dist/src/__test-utils__/awsMockHelpers.d.ts +20 -0
- package/dist/src/__test-utils__/awsMockHelpers.js +1 -0
- package/dist/src/__test-utils__/index.d.ts +1 -0
- package/dist/src/__test-utils__/index.js +1 -0
- package/dist/src/aws/AwsProvider.js +0 -1
- package/dist/src/aws/SimpleAwsProvider.js +1 -70
- package/dist/src/aws/index.d.ts +4 -2
- package/dist/src/aws/index.js +1 -3
- package/dist/src/aws/organisations/accounts.js +10 -10
- package/dist/src/aws/organisations/backup.js +4 -2
- package/dist/src/aws/organisations/costAllocation.js +4 -2
- package/dist/src/aws/organisations/delegatedAdmin.d.ts +9 -0
- package/dist/src/aws/organisations/delegatedAdmin.js +43 -0
- package/dist/src/aws/organisations/identityCentre.d.ts +1 -1
- package/dist/src/aws/organisations/identityCentre.js +6 -2
- package/dist/src/aws/organisations/index.d.ts +4 -3
- package/dist/src/aws/organisations/index.js +1 -12
- package/dist/src/aws/organisations/ipam.js +4 -2
- package/dist/src/aws/organisations/organisation.js +27 -18
- package/dist/src/aws/organisations/organisationalUnits.d.ts +26 -6
- package/dist/src/aws/organisations/organisationalUnits.js +149 -35
- package/dist/src/aws/organisations/policies.js +4 -3
- package/dist/src/aws/organisations/ram.js +6 -2
- package/dist/src/aws/organisations/serviceAccess.js +12 -6
- package/dist/src/aws/organisations/trustedAccess.js +6 -2
- package/dist/src/aws/organisations/types.d.ts +23 -1
- package/dist/src/aws/organisations/types.js +1 -16
- package/dist/src/aws/utils/__tests__/cloudformationTestHelpers.d.ts +6 -0
- package/dist/src/aws/utils/__tests__/cloudformationTestHelpers.js +1 -0
- package/dist/src/aws/utils/cloudformationEventHelpers.d.ts +48 -0
- package/dist/src/aws/utils/cloudformationEventHelpers.js +1 -0
- package/dist/src/aws/utils/cloudformationEventTypes.d.ts +45 -0
- package/dist/src/aws/utils/cloudformationEventTypes.js +1 -0
- package/dist/src/aws/utils/cloudformationEvents.d.ts +8 -54
- package/dist/src/aws/utils/cloudformationEvents.js +1 -596
- package/dist/src/aws/utils/index.d.ts +5 -0
- package/dist/src/aws/utils/index.js +1 -0
- package/dist/src/aws/utils/stackStatus.js +1 -90
- package/dist/src/events/index.d.ts +13 -0
- package/dist/src/events/index.js +1 -0
- package/dist/src/index.d.ts +34 -17
- package/dist/src/index.js +41 -21
- package/dist/src/orchestration/__tests__/cascadeTestHelpers.d.ts +12 -0
- package/dist/src/orchestration/__tests__/cascadeTestHelpers.js +78 -0
- package/dist/src/orchestration/activeDeploymentGuard.d.ts +10 -0
- package/dist/src/orchestration/activeDeploymentGuard.js +39 -0
- package/dist/src/orchestration/applicationDeploy.js +46 -229
- package/dist/src/orchestration/applicationDeployHelpers.d.ts +39 -0
- package/dist/src/orchestration/applicationDeployHelpers.js +223 -0
- package/dist/src/orchestration/applicationDestroy.d.ts +14 -0
- package/dist/src/orchestration/applicationDestroy.js +131 -0
- package/dist/src/orchestration/builders/dockerBuilder.d.ts +17 -0
- package/dist/src/orchestration/builders/dockerBuilder.js +98 -0
- package/dist/src/orchestration/builders/frameworkRegistry.d.ts +23 -0
- package/dist/src/orchestration/builders/frameworkRegistry.js +1 -0
- package/dist/src/orchestration/builders/index.d.ts +4 -0
- package/dist/src/orchestration/builders/index.js +1 -0
- package/dist/src/orchestration/builders/openNextBuilder.d.ts +21 -0
- package/dist/src/orchestration/builders/openNextBuilder.js +144 -0
- package/dist/src/orchestration/cascadeDestroyHelpers.d.ts +30 -0
- package/dist/src/orchestration/cascadeDestroyHelpers.js +1 -0
- package/dist/src/orchestration/cascadeHelpers.d.ts +46 -0
- package/dist/src/orchestration/cascadeHelpers.js +160 -0
- package/dist/src/orchestration/contextHelpers.d.ts +46 -2
- package/dist/src/orchestration/contextHelpers.js +93 -1
- package/dist/src/orchestration/destroy.d.ts +13 -0
- package/dist/src/orchestration/destroy.js +67 -0
- package/dist/src/orchestration/detectionPipeline.d.ts +2 -11
- package/dist/src/orchestration/detectionPipeline.js +29 -10
- package/dist/src/orchestration/dockerBuildHelper.d.ts +10 -0
- package/dist/src/orchestration/dockerBuildHelper.js +49 -0
- package/dist/src/orchestration/dockerInterface.d.ts +4 -2
- package/dist/src/orchestration/index.d.ts +8 -1
- package/dist/src/orchestration/index.js +1 -3
- package/dist/src/orchestration/manifestSecretParser.d.ts +11 -0
- package/dist/src/orchestration/manifestSecretParser.js +1 -0
- package/dist/src/orchestration/openNextBuild.d.ts +28 -0
- package/dist/src/orchestration/openNextBuild.js +243 -0
- package/dist/src/orchestration/organisationDeploy.js +110 -233
- package/dist/src/orchestration/organisationDestroy.d.ts +24 -0
- package/dist/src/orchestration/organisationDestroy.js +189 -0
- package/dist/src/orchestration/organisationSetup.d.ts +6 -4
- package/dist/src/orchestration/organisationSetup.js +28 -8
- package/dist/src/orchestration/resolveOperation.js +68 -6
- package/dist/src/orchestration/serviceFactory.d.ts +4 -0
- package/dist/src/orchestration/serviceFactory.js +1 -16
- package/dist/src/orchestration/spawnHelpers.d.ts +47 -0
- package/dist/src/orchestration/spawnHelpers.js +1 -0
- package/dist/src/orchestration/stackCleanup.d.ts +39 -0
- package/dist/src/orchestration/stackCleanup.js +1 -0
- package/dist/src/orchestration/welcomeImageHelper.d.ts +15 -0
- package/dist/src/orchestration/welcomeImageHelper.js +64 -0
- package/dist/src/services/application/ApplicationStackService.d.ts +21 -30
- package/dist/src/services/application/ApplicationStackService.js +16 -234
- package/dist/src/services/application/applicationStackHelpers.d.ts +46 -0
- package/dist/src/services/application/applicationStackHelpers.js +248 -0
- package/dist/src/services/application/index.d.ts +1 -0
- package/dist/src/services/application/index.js +1 -1
- package/dist/src/services/index.d.ts +6 -0
- package/dist/src/services/index.js +1 -0
- package/dist/src/services/infrastructure/CdkArgumentBuilder.js +1 -67
- package/dist/src/services/infrastructure/CdkCommandRunner.d.ts +10 -2
- package/dist/src/services/infrastructure/CdkCommandRunner.js +18 -15
- package/dist/src/services/infrastructure/CdkErrorFormatter.js +16 -194
- package/dist/src/services/infrastructure/CdkEventMonitoring.js +1 -41
- package/dist/src/services/infrastructure/CdkOutputAnalyser.js +1 -1
- package/dist/src/services/infrastructure/CdkOutputParser.js +2 -33
- package/dist/src/services/infrastructure/CdkProcessManager.d.ts +5 -0
- package/dist/src/services/infrastructure/CdkProcessManager.js +81 -47
- package/dist/src/services/infrastructure/CdkService.d.ts +7 -53
- package/dist/src/services/infrastructure/CdkService.js +41 -83
- package/dist/src/services/infrastructure/CdkServiceTypes.d.ts +50 -0
- package/dist/src/services/infrastructure/CdkServiceTypes.js +0 -0
- package/dist/src/services/infrastructure/CloudFormationService.js +9 -10
- package/dist/src/services/infrastructure/ICdkProcessManager.d.ts +27 -0
- package/dist/src/services/infrastructure/ICdkProcessManager.js +1 -0
- package/dist/src/services/infrastructure/__tests__/cloudFormationTestHelpers.d.ts +9 -0
- package/dist/src/services/infrastructure/__tests__/cloudFormationTestHelpers.js +1 -0
- package/dist/src/services/infrastructure/cdkServiceHelpers.d.ts +9 -0
- package/dist/src/services/infrastructure/cdkServiceHelpers.js +1 -0
- package/dist/src/services/infrastructure/constructMapEnrichment.d.ts +7 -0
- package/dist/src/services/infrastructure/constructMapEnrichment.js +1 -0
- package/dist/src/services/infrastructure/index.d.ts +3 -1
- package/dist/src/services/infrastructure/index.js +1 -7
- package/dist/src/services/supporting/TemplateHashService.js +1 -1
- package/dist/src/services/supporting/helpers.js +1 -81
- package/dist/src/services/supporting/index.js +1 -3
- package/dist/src/steps/index.d.ts +1 -0
- package/dist/src/steps/index.js +1 -0
- package/dist/src/steps/stepRegistry.d.ts +71 -0
- package/dist/src/steps/stepRegistry.js +505 -0
- package/dist/src/types/FjallState.js +1 -118
- package/dist/src/types/ProgressEvent.js +1 -48
- package/dist/src/types/application/ApplicationServiceTypes.js +1 -30
- package/dist/src/types/application/index.js +1 -1
- package/dist/src/types/callbacks.d.ts +76 -4
- package/dist/src/types/callbacks.js +0 -1
- package/dist/src/types/constants.d.ts +2 -0
- package/dist/src/types/constants.js +1 -6
- package/dist/src/types/credentials.js +0 -1
- package/dist/src/types/deployment/DeploymentServiceTypes.d.ts +5 -2
- package/dist/src/types/deployment/DeploymentServiceTypes.js +1 -1
- package/dist/src/types/deployment/DeploymentTypes.js +0 -1
- package/dist/src/types/deployment/cloudformation.js +0 -1
- package/dist/src/types/deployment/index.d.ts +3 -1
- package/dist/src/types/deployment/index.js +1 -1
- package/dist/src/types/deployment/parallel.js +1 -10
- package/dist/src/types/deploymentEventSchema.d.ts +158 -0
- package/dist/src/types/deploymentEventSchema.js +1 -0
- package/dist/src/types/detection.d.ts +22 -0
- package/dist/src/types/detection.js +1 -0
- package/dist/src/types/entitlements.d.ts +31 -0
- package/dist/src/types/entitlements.js +0 -0
- package/dist/src/types/errors/CdkError.js +1 -20
- package/dist/src/types/errors/ServiceError.d.ts +2 -1
- package/dist/src/types/errors/ServiceError.js +1 -119
- package/dist/src/types/errors/index.d.ts +2 -0
- package/dist/src/types/errors/index.js +1 -0
- package/dist/src/types/events.d.ts +3 -9
- package/dist/src/types/events.js +0 -5
- package/dist/src/types/frameworkBuilder.d.ts +96 -0
- package/dist/src/types/frameworkBuilder.js +8 -0
- package/dist/src/types/index.d.ts +19 -4
- package/dist/src/types/index.js +1 -9
- package/dist/src/types/operations.d.ts +3 -2
- package/dist/src/types/operations.js +1 -285
- package/dist/src/types/orgConfig.d.ts +2 -10
- package/dist/src/types/orgConfig.js +0 -11
- package/dist/src/types/params.d.ts +60 -1
- package/dist/src/types/patternDetection.d.ts +14 -16
- package/dist/src/types/patternDetection.js +14 -18
- package/dist/src/types/patternTypes.d.ts +19 -0
- package/dist/src/types/patternTypes.js +1 -0
- package/dist/src/types/stepDefinitions.d.ts +163 -0
- package/dist/src/types/stepDefinitions.js +98 -0
- package/dist/src/types/validation.js +0 -1
- package/dist/src/util/dockerfileDetection.d.ts +5 -0
- package/dist/src/util/dockerfileDetection.js +1 -0
- package/dist/src/util/index.d.ts +4 -3
- package/dist/src/util/index.js +1 -3
- package/dist/src/util/sequencedCallbacks.d.ts +44 -0
- package/dist/src/util/sequencedCallbacks.js +1 -0
- package/package.json +49 -8
- package/dist/src/aws/utils/CloudFormationFailureAnalyser.d.ts +0 -32
- package/dist/src/aws/utils/CloudFormationFailureAnalyser.js +0 -228
- package/dist/src/aws/utils/errors.d.ts +0 -26
- package/dist/src/aws/utils/errors.js +0 -59
- package/dist/src/util/fsHelpers.d.ts +0 -4
- package/dist/src/util/fsHelpers.js +0 -16
- package/dist/src/util/securityHelpers.d.ts +0 -31
- package/dist/src/util/securityHelpers.js +0 -124
- package/dist/src/util/singleton.d.ts +0 -2
- package/dist/src/util/singleton.js +0 -9
- package/dist/src/util/sleep.d.ts +0 -4
- package/dist/src/util/sleep.js +0 -4
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { success, failure } from "@fjall/generator";
|
|
2
|
-
import { logger } from "@fjall/util";
|
|
3
|
-
import {
|
|
2
|
+
import { logger } from "@fjall/util/logger";
|
|
3
|
+
import { stubCallerIdentity } from "../types/deployment/index.js";
|
|
4
|
+
import { getApplicationDeployOrder, getApplicationStackName, getApplicationStepName, getApplicationStepId } from "../types/operations.js";
|
|
4
5
|
import { CdkContextBuilder } from "../services/supporting/CdkContextBuilder.js";
|
|
5
|
-
import {
|
|
6
|
-
import { buildParamsContext } from "./contextHelpers.js";
|
|
6
|
+
import { buildParamsContext, bootstrapOrFail } from "./contextHelpers.js";
|
|
7
7
|
import { runDetectionPipeline } from "./detectionPipeline.js";
|
|
8
|
-
import {
|
|
8
|
+
import { getParallelPhase2Stacks, deployParallelPhase, deployStackSequential, runDockerPreCompute, deployAllStacks, createBuildCallbacks } from "./applicationDeployHelpers.js";
|
|
9
9
|
/**
|
|
10
10
|
* Core application deployment orchestration.
|
|
11
11
|
*
|
|
@@ -21,20 +21,34 @@ export async function deployApplication(params, services, operation) {
|
|
|
21
21
|
target: operation.appName,
|
|
22
22
|
path: operation.path,
|
|
23
23
|
region: services.awsProvider.getRegion(),
|
|
24
|
-
callerIdentity:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
callerIdentity: stubCallerIdentity(services.awsProvider.getAccountId()),
|
|
25
|
+
...buildParamsContext({
|
|
26
|
+
orgConfig: params.orgConfig,
|
|
27
|
+
identity: params.identity,
|
|
28
|
+
skipOidc: params.options?.skipOidc
|
|
29
|
+
})
|
|
30
30
|
}, {
|
|
31
31
|
verbose: options?.verbose,
|
|
32
32
|
infraOnly: options?.infraOnly
|
|
33
33
|
}, params.orgConfig);
|
|
34
|
+
// 1b. Resolve framework builder and run build (if applicable — runs before detection)
|
|
35
|
+
const resolved = services.frameworkRegistry.resolve({
|
|
36
|
+
appPath: operation.path
|
|
37
|
+
});
|
|
38
|
+
let plan;
|
|
39
|
+
if (resolved) {
|
|
40
|
+
plan = resolved.builder.plan({ appPath: operation.path }, resolved.detection);
|
|
41
|
+
const buildCallbacks = createBuildCallbacks(callbacks);
|
|
42
|
+
const buildResult = await resolved.builder.build(operation.path, plan, buildCallbacks, { skipBuild: options?.skipBuild, infraOnly: options?.infraOnly });
|
|
43
|
+
if (!buildResult.success) {
|
|
44
|
+
callbacks.onError?.(buildResult.error);
|
|
45
|
+
return failure(buildResult.error);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
34
48
|
// deployOnly: skip detection pipeline, deploy all stacks unconditionally
|
|
35
49
|
if (options?.deployOnly) {
|
|
36
50
|
callbacks.onLog?.("Deploy-only mode — skipping change detection", "info");
|
|
37
|
-
return deployAllStacks(params, services, operation, context, startTime);
|
|
51
|
+
return deployAllStacks(params, services, operation, context, startTime, plan);
|
|
38
52
|
}
|
|
39
53
|
// 2. Run detection pipeline
|
|
40
54
|
callbacks.onLog?.("Analysing infrastructure…", "info");
|
|
@@ -44,6 +58,12 @@ export async function deployApplication(params, services, operation) {
|
|
|
44
58
|
return failure(detectionResult.error);
|
|
45
59
|
}
|
|
46
60
|
const detection = detectionResult.data;
|
|
61
|
+
// 2b. Notify callers of detection results (resource flags, pattern, etc.)
|
|
62
|
+
// Awaited so callers can run post-detection hooks (e.g. secrets validation).
|
|
63
|
+
await callbacks.onDetectionComplete?.({
|
|
64
|
+
...detection,
|
|
65
|
+
builderName: resolved?.builder.name ?? "unknown"
|
|
66
|
+
});
|
|
47
67
|
// 3. Early exit if no differences
|
|
48
68
|
if (!detection.hasDifferences && !options?.force) {
|
|
49
69
|
callbacks.onLog?.("No infrastructure changes detected", "info");
|
|
@@ -54,20 +74,16 @@ export async function deployApplication(params, services, operation) {
|
|
|
54
74
|
});
|
|
55
75
|
}
|
|
56
76
|
// 4. Bootstrap AWS environment
|
|
57
|
-
callbacks
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const deployOrder = getApplicationDeployOrder({
|
|
68
|
-
pattern: detection.pattern,
|
|
69
|
-
resources: detection.resources
|
|
70
|
-
});
|
|
77
|
+
const bsResult = await bootstrapOrFail(services, context, callbacks);
|
|
78
|
+
if (!bsResult.success)
|
|
79
|
+
return bsResult;
|
|
80
|
+
// 5. Determine deploy order (prefer plan from registry, fall back to legacy)
|
|
81
|
+
const deployOrder = plan
|
|
82
|
+
? plan.deployOrder
|
|
83
|
+
: getApplicationDeployOrder({
|
|
84
|
+
pattern: detection.pattern,
|
|
85
|
+
resources: detection.resources
|
|
86
|
+
});
|
|
71
87
|
const totalSteps = deployOrder.length;
|
|
72
88
|
// 6. Deploy stacks
|
|
73
89
|
const allOutputs = {};
|
|
@@ -95,14 +111,10 @@ export async function deployApplication(params, services, operation) {
|
|
|
95
111
|
i += parallelStacks.length - 1;
|
|
96
112
|
continue;
|
|
97
113
|
}
|
|
98
|
-
// Docker
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const dockerResult = await runDockerBuild(params, services, operation, callbacks);
|
|
103
|
-
if (!dockerResult.success)
|
|
104
|
-
return failure(dockerResult.error);
|
|
105
|
-
}
|
|
114
|
+
// Docker operations before Compute stack
|
|
115
|
+
const dockerFailed = await runDockerPreCompute(stack, params, services, operation, callbacks, detection.hasDockerfile);
|
|
116
|
+
if (dockerFailed)
|
|
117
|
+
return dockerFailed;
|
|
106
118
|
// Sequential deployment
|
|
107
119
|
const deployResult = await deployStackSequential(stack, services, context, callbacks, i, totalSteps, allOutputs);
|
|
108
120
|
if (!deployResult.success)
|
|
@@ -135,198 +147,3 @@ export async function deployApplication(params, services, operation) {
|
|
|
135
147
|
durationMs: Date.now() - startTime
|
|
136
148
|
});
|
|
137
149
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Identify Phase 2 stacks (Storage, Messaging, Database) that are consecutive
|
|
140
|
-
* in the deploy order and have changes. Returns them for parallel deployment
|
|
141
|
-
* only if there are at least 2.
|
|
142
|
-
*/
|
|
143
|
-
function getParallelPhase2Stacks(deployOrder, currentIndex, stackChanges, force) {
|
|
144
|
-
const phase2Set = new Set(PARALLEL_DEPLOY_GROUPS.PHASE_2.stacks);
|
|
145
|
-
const candidates = [];
|
|
146
|
-
for (let j = currentIndex; j < deployOrder.length; j++) {
|
|
147
|
-
if (phase2Set.has(deployOrder[j])) {
|
|
148
|
-
candidates.push(deployOrder[j]);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (candidates.length < 2)
|
|
155
|
-
return [];
|
|
156
|
-
// Only include stacks that actually have changes (unless forced)
|
|
157
|
-
if (!force) {
|
|
158
|
-
const withChanges = candidates.filter((stack) => {
|
|
159
|
-
// stackChanges is keyed by full stack name but we only have the type here;
|
|
160
|
-
// since we don't know the app name, check all entries ending with the stack type
|
|
161
|
-
for (const [key, changed] of stackChanges) {
|
|
162
|
-
if (key.endsWith(stack) && !changed)
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
return true;
|
|
166
|
-
});
|
|
167
|
-
return withChanges.length >= 2 ? withChanges : [];
|
|
168
|
-
}
|
|
169
|
-
return candidates;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Deploy a group of stacks in parallel, reporting step events for each.
|
|
173
|
-
*/
|
|
174
|
-
async function deployParallelPhase(stacks, operation, services, context, callbacks, startIndex, totalSteps, detection, allOutputs, deployedHashes) {
|
|
175
|
-
// Emit step start for each parallel stack
|
|
176
|
-
for (let k = 0; k < stacks.length; k++) {
|
|
177
|
-
const stack = stacks[k];
|
|
178
|
-
const stepId = getApplicationStepId(stack, "deploy");
|
|
179
|
-
const stepName = getApplicationStepName(stack, "deploy");
|
|
180
|
-
callbacks.onStepStart?.(stepId, stepName, startIndex + k, totalSteps);
|
|
181
|
-
}
|
|
182
|
-
emitProgress(callbacks, "Deploying infrastructure in parallel…");
|
|
183
|
-
const parallelResult = await services.stackService.deployStacksInParallel(stacks, context, {
|
|
184
|
-
onOutput: (chunk) => callbacks.onOutput?.(chunk),
|
|
185
|
-
onResourceProgress: (event) => callbacks.onResourceProgress?.(event),
|
|
186
|
-
onStackComplete: (stack, stackSuccess, _duration, error) => {
|
|
187
|
-
const stepId = getApplicationStepId(stack, "deploy");
|
|
188
|
-
const stepName = getApplicationStepName(stack, "deploy");
|
|
189
|
-
const idx = startIndex + stacks.indexOf(stack);
|
|
190
|
-
callbacks.onStepComplete?.(stepId, stepName, stackSuccess ? "completed" : "error", idx, totalSteps);
|
|
191
|
-
if (!stackSuccess && error) {
|
|
192
|
-
callbacks.onError?.(error);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
if (!parallelResult.success) {
|
|
197
|
-
return failure(parallelResult.error);
|
|
198
|
-
}
|
|
199
|
-
// Check for any failures
|
|
200
|
-
const failures = parallelResult.data.filter((r) => !r.success);
|
|
201
|
-
if (failures.length > 0) {
|
|
202
|
-
const failedStacks = failures.map((f) => f.stack).join(", ");
|
|
203
|
-
const errorDetails = failures
|
|
204
|
-
.map((f) => `${f.stack}: ${f.error?.message ?? "Unknown error"}`)
|
|
205
|
-
.join("\n");
|
|
206
|
-
return failure(new Error(`Failed to deploy stacks: ${failedStacks}\n\n${errorDetails}`));
|
|
207
|
-
}
|
|
208
|
-
// Collect outputs and track hashes for successful parallel stacks
|
|
209
|
-
for (const result of parallelResult.data) {
|
|
210
|
-
if (result.success && result.outputs) {
|
|
211
|
-
for (const [key, value] of Object.entries(result.outputs)) {
|
|
212
|
-
allOutputs[key] = String(value);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
const stackName = getApplicationStackName(operation.appName, result.stack);
|
|
216
|
-
const hash = detection.currentHashes.get(stackName);
|
|
217
|
-
if (hash) {
|
|
218
|
-
deployedHashes.set(stackName, hash);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return success(undefined);
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Run Docker build and push before deploying the Compute stack.
|
|
225
|
-
* Initialises ECR if needed, then builds and pushes the image.
|
|
226
|
-
*/
|
|
227
|
-
async function runDockerBuild(params, services, operation, callbacks) {
|
|
228
|
-
const dockerProvider = params.dockerProvider;
|
|
229
|
-
if (!dockerProvider)
|
|
230
|
-
return success(undefined);
|
|
231
|
-
const accountId = services.awsProvider.getAccountId();
|
|
232
|
-
if (!accountId) {
|
|
233
|
-
callbacks.onLog?.("Skipping Docker build — account ID not available", "warn");
|
|
234
|
-
return success(undefined);
|
|
235
|
-
}
|
|
236
|
-
const region = services.awsProvider.getRegion();
|
|
237
|
-
// Initialise ECR repository (non-fatal — CDK creates it if needed)
|
|
238
|
-
callbacks.onLog?.("Initialising ECR repository…", "info");
|
|
239
|
-
const ecrResult = await dockerProvider.initialiseECR({
|
|
240
|
-
appName: operation.appName,
|
|
241
|
-
region,
|
|
242
|
-
accountId
|
|
243
|
-
});
|
|
244
|
-
if (!ecrResult.success) {
|
|
245
|
-
callbacks.onLog?.(`ECR initialisation failed: ${ecrResult.error.message}`, "warn");
|
|
246
|
-
}
|
|
247
|
-
// Build and push Docker image
|
|
248
|
-
callbacks.onLog?.("Building and pushing Docker image…", "info");
|
|
249
|
-
const buildResult = await dockerProvider.buildAndPush({
|
|
250
|
-
appName: operation.appName,
|
|
251
|
-
appPath: operation.path,
|
|
252
|
-
region,
|
|
253
|
-
accountId
|
|
254
|
-
});
|
|
255
|
-
if (!buildResult.success) {
|
|
256
|
-
callbacks.onError?.(buildResult.error);
|
|
257
|
-
return failure(buildResult.error);
|
|
258
|
-
}
|
|
259
|
-
callbacks.onLog?.(`Docker image pushed: ${buildResult.data.imageUri}`, "info");
|
|
260
|
-
return success(undefined);
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Deploy a single stack with step lifecycle events and output collection.
|
|
264
|
-
*/
|
|
265
|
-
async function deployStackSequential(stack, services, context, callbacks, stepIndex, totalSteps, allOutputs) {
|
|
266
|
-
const stepId = getApplicationStepId(stack, "deploy");
|
|
267
|
-
const stepName = getApplicationStepName(stack, "deploy");
|
|
268
|
-
callbacks.onStepStart?.(stepId, stepName, stepIndex, totalSteps);
|
|
269
|
-
const result = await services.stackService.deployStack(stack, context, {
|
|
270
|
-
onOutput: (chunk) => callbacks.onOutput?.(chunk),
|
|
271
|
-
onResourceProgress: (event) => callbacks.onResourceProgress?.(event)
|
|
272
|
-
});
|
|
273
|
-
if (!result.success) {
|
|
274
|
-
callbacks.onStepComplete?.(stepId, stepName, "error", stepIndex, totalSteps);
|
|
275
|
-
callbacks.onError?.(result.error);
|
|
276
|
-
return failure(result.error);
|
|
277
|
-
}
|
|
278
|
-
callbacks.onStepComplete?.(stepId, stepName, "completed", stepIndex, totalSteps);
|
|
279
|
-
if (result.data.outputs) {
|
|
280
|
-
for (const [key, value] of Object.entries(result.data.outputs)) {
|
|
281
|
-
allOutputs[key] = String(value);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return success(undefined);
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Deploy all stacks unconditionally (deployOnly mode).
|
|
288
|
-
* Skips CDK synth/hash comparison — uses filesystem pattern detection only
|
|
289
|
-
* to determine deploy order, then deploys every stack sequentially.
|
|
290
|
-
*/
|
|
291
|
-
async function deployAllStacks(params, services, operation, context, startTime) {
|
|
292
|
-
const { callbacks } = params;
|
|
293
|
-
// Lightweight pattern detection (filesystem only, no CDK synth)
|
|
294
|
-
const { pattern } = detectPattern(operation.path);
|
|
295
|
-
const deployOrder = getApplicationDeployOrder({ pattern });
|
|
296
|
-
const totalSteps = deployOrder.length;
|
|
297
|
-
// Bootstrap
|
|
298
|
-
callbacks.onCDKBootstrap?.("bootstrapping");
|
|
299
|
-
const bootstrapResult = await services.cdkService.runCdkBootstrap(context, (chunk) => callbacks.onOutput?.(chunk));
|
|
300
|
-
if (!bootstrapResult.success) {
|
|
301
|
-
callbacks.onCDKBootstrap?.("failed");
|
|
302
|
-
const error = new Error(`Bootstrap failed: ${bootstrapResult.error}`);
|
|
303
|
-
callbacks.onError?.(error);
|
|
304
|
-
return failure(error);
|
|
305
|
-
}
|
|
306
|
-
callbacks.onCDKBootstrap?.("complete");
|
|
307
|
-
// Deploy all stacks sequentially
|
|
308
|
-
const allOutputs = {};
|
|
309
|
-
for (let i = 0; i < deployOrder.length; i++) {
|
|
310
|
-
const stack = deployOrder[i];
|
|
311
|
-
// Docker build before Compute stack
|
|
312
|
-
if (stack === APPLICATION_STACKS.COMPUTE && params.dockerProvider) {
|
|
313
|
-
const dockerResult = await runDockerBuild(params, services, operation, callbacks);
|
|
314
|
-
if (!dockerResult.success)
|
|
315
|
-
return failure(dockerResult.error);
|
|
316
|
-
}
|
|
317
|
-
const deployResult = await deployStackSequential(stack, services, context, callbacks, i, totalSteps, allOutputs);
|
|
318
|
-
if (!deployResult.success)
|
|
319
|
-
return failure(deployResult.error);
|
|
320
|
-
}
|
|
321
|
-
// Resolve website URL
|
|
322
|
-
const websiteUrl = await services.stackService.resolveWebsiteUrl(operation.appName);
|
|
323
|
-
if (websiteUrl) {
|
|
324
|
-
allOutputs.websiteUrl = websiteUrl;
|
|
325
|
-
}
|
|
326
|
-
return success({
|
|
327
|
-
target: operation.appName,
|
|
328
|
-
deploymentType: "application",
|
|
329
|
-
outputs: Object.keys(allOutputs).length > 0 ? allOutputs : undefined,
|
|
330
|
-
durationMs: Date.now() - startTime
|
|
331
|
-
});
|
|
332
|
-
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type Result } from "@fjall/generator";
|
|
2
|
+
import type { DeployParams, DeployResult } from "../types/params.js";
|
|
3
|
+
import type { DeploymentContext } from "../types/deployment/DeploymentTypes.js";
|
|
4
|
+
import type { DeployCallbacks } from "../types/callbacks.js";
|
|
5
|
+
import type { ApplicationOperation, ApplicationStack } from "../types/operations.js";
|
|
6
|
+
import type { DeployServices } from "./serviceFactory.js";
|
|
7
|
+
import type { DetectionResult } from "./detectionPipeline.js";
|
|
8
|
+
import type { BuildCallbacks, BuildPlan } from "../types/frameworkBuilder.js";
|
|
9
|
+
/**
|
|
10
|
+
* Identify Phase 2 stacks (Storage, Messaging, Database) that are consecutive
|
|
11
|
+
* in the deploy order and have changes. Returns them for parallel deployment
|
|
12
|
+
* only if there are at least 2.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getParallelPhase2Stacks(deployOrder: readonly ApplicationStack[], currentIndex: number, stackChanges: Map<string, boolean>, force?: boolean): ApplicationStack[];
|
|
15
|
+
/**
|
|
16
|
+
* Deploy a group of stacks in parallel, reporting step events for each.
|
|
17
|
+
*/
|
|
18
|
+
export declare function deployParallelPhase(stacks: ApplicationStack[], operation: ApplicationOperation, services: DeployServices, context: DeploymentContext, callbacks: DeployCallbacks, startIndex: number, totalSteps: number, detection: DetectionResult, allOutputs: Record<string, string>, deployedHashes: Map<string, string>): Promise<Result<void>>;
|
|
19
|
+
/**
|
|
20
|
+
* Deploy a single stack with step lifecycle events and output collection.
|
|
21
|
+
*/
|
|
22
|
+
export declare function deployStackSequential(stack: ApplicationStack, services: DeployServices, context: DeploymentContext, callbacks: DeployCallbacks, stepIndex: number, totalSteps: number, allOutputs: Record<string, string>): Promise<Result<void>>;
|
|
23
|
+
/**
|
|
24
|
+
* Run Docker build/push or welcome image setup before the Compute stack.
|
|
25
|
+
* Returns a failure Result if Docker operations fail, or null if not applicable/successful.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runDockerPreCompute(stack: ApplicationStack, params: DeployParams, services: DeployServices, operation: ApplicationOperation, callbacks: DeployCallbacks, hasDockerfileOnDisk: boolean): Promise<Result<DeployResult> | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Deploy all stacks unconditionally (deployOnly mode).
|
|
30
|
+
* Skips CDK synth/hash comparison — uses the framework registry to determine
|
|
31
|
+
* deploy order, then deploys every stack sequentially.
|
|
32
|
+
*/
|
|
33
|
+
export declare function deployAllStacks(params: DeployParams, services: DeployServices, operation: ApplicationOperation, context: DeploymentContext, startTime: number, plan?: BuildPlan): Promise<Result<DeployResult>>;
|
|
34
|
+
/**
|
|
35
|
+
* Bridge DeployCallbacks to BuildCallbacks.
|
|
36
|
+
* Fires both legacy OpenNext-specific callbacks and generic build callbacks
|
|
37
|
+
* for backwards compatibility during the transition period.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createBuildCallbacks(callbacks: DeployCallbacks): BuildCallbacks;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { success, failure } from "@fjall/generator";
|
|
2
|
+
import { APPLICATION_STACKS, getApplicationDeployOrder, getApplicationStackName, getApplicationStepName, getApplicationStepId, PARALLEL_DEPLOY_GROUPS } from "../types/operations.js";
|
|
3
|
+
import { emitProgress } from "../services/supporting/helpers.js";
|
|
4
|
+
import { bootstrapOrFail, forwardOutput, forwardResourceProgress } from "./contextHelpers.js";
|
|
5
|
+
import { hasDockerfile } from "../util/dockerfileDetection.js";
|
|
6
|
+
import { runDockerBuild } from "./dockerBuildHelper.js";
|
|
7
|
+
import { runWelcomeImageSetup } from "./welcomeImageHelper.js";
|
|
8
|
+
/**
|
|
9
|
+
* Identify Phase 2 stacks (Storage, Messaging, Database) that are consecutive
|
|
10
|
+
* in the deploy order and have changes. Returns them for parallel deployment
|
|
11
|
+
* only if there are at least 2.
|
|
12
|
+
*/
|
|
13
|
+
export function getParallelPhase2Stacks(deployOrder, currentIndex, stackChanges, force) {
|
|
14
|
+
const phase2Set = new Set(PARALLEL_DEPLOY_GROUPS.PHASE_2.stacks);
|
|
15
|
+
const candidates = [];
|
|
16
|
+
for (let j = currentIndex; j < deployOrder.length; j++) {
|
|
17
|
+
if (phase2Set.has(deployOrder[j])) {
|
|
18
|
+
candidates.push(deployOrder[j]);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (candidates.length < 2)
|
|
25
|
+
return [];
|
|
26
|
+
// Only include stacks that actually have changes (unless forced)
|
|
27
|
+
if (!force) {
|
|
28
|
+
const withChanges = candidates.filter((stack) => {
|
|
29
|
+
// stackChanges is keyed by full stack name but we only have the type here;
|
|
30
|
+
// since we don't know the app name, check all entries ending with the stack type
|
|
31
|
+
for (const [key, changed] of stackChanges) {
|
|
32
|
+
if (key.endsWith(stack) && !changed)
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
return withChanges.length >= 2 ? withChanges : [];
|
|
38
|
+
}
|
|
39
|
+
return candidates;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Deploy a group of stacks in parallel, reporting step events for each.
|
|
43
|
+
*/
|
|
44
|
+
export async function deployParallelPhase(stacks, operation, services, context, callbacks, startIndex, totalSteps, detection, allOutputs, deployedHashes) {
|
|
45
|
+
// Emit step start for each parallel stack
|
|
46
|
+
for (let k = 0; k < stacks.length; k++) {
|
|
47
|
+
const stack = stacks[k];
|
|
48
|
+
const stepId = getApplicationStepId(stack, "deploy");
|
|
49
|
+
const stepName = getApplicationStepName(stack, "deploy");
|
|
50
|
+
callbacks.onStepStart?.(stepId, stepName, startIndex + k, totalSteps);
|
|
51
|
+
}
|
|
52
|
+
emitProgress(callbacks, "Deploying infrastructure in parallel…");
|
|
53
|
+
callbacks.onParallelPhaseStart?.(stacks, "Storage and database resources (parallel)");
|
|
54
|
+
const parallelResult = await services.stackService.deployStacksInParallel(stacks, context, {
|
|
55
|
+
onOutput: forwardOutput(callbacks),
|
|
56
|
+
onResourceProgress: (event, stackId) => {
|
|
57
|
+
callbacks.onResourceProgress?.(event);
|
|
58
|
+
if (stackId) {
|
|
59
|
+
callbacks.onParallelStackResourceProgress?.(stackId, event);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
onStackComplete: (stack, stackSuccess, _duration, error) => {
|
|
63
|
+
const stepId = getApplicationStepId(stack, "deploy");
|
|
64
|
+
const stepName = getApplicationStepName(stack, "deploy");
|
|
65
|
+
const idx = startIndex + stacks.indexOf(stack);
|
|
66
|
+
callbacks.onStepComplete?.(stepId, stepName, stackSuccess ? "completed" : "error", idx, totalSteps);
|
|
67
|
+
if (!stackSuccess && error) {
|
|
68
|
+
callbacks.onError?.(error);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
if (!parallelResult.success) {
|
|
73
|
+
callbacks.onParallelPhaseComplete?.([]);
|
|
74
|
+
return failure(parallelResult.error);
|
|
75
|
+
}
|
|
76
|
+
// Check for any failures
|
|
77
|
+
const failures = parallelResult.data.filter((r) => !r.success);
|
|
78
|
+
callbacks.onParallelPhaseComplete?.(parallelResult.data.map((r) => ({
|
|
79
|
+
stack: r.stack,
|
|
80
|
+
success: r.success,
|
|
81
|
+
error: r.error
|
|
82
|
+
})));
|
|
83
|
+
if (failures.length > 0) {
|
|
84
|
+
const failedStacks = failures.map((f) => f.stack).join(", ");
|
|
85
|
+
const errorDetails = failures
|
|
86
|
+
.map((f) => `${f.stack}: ${f.error?.message ?? "Unknown error"}`)
|
|
87
|
+
.join("\n");
|
|
88
|
+
return failure(new Error(`Failed to deploy stacks: ${failedStacks}\n\n${errorDetails}`));
|
|
89
|
+
}
|
|
90
|
+
// Collect outputs and track hashes for successful parallel stacks
|
|
91
|
+
for (const result of parallelResult.data) {
|
|
92
|
+
if (result.success && result.outputs) {
|
|
93
|
+
for (const [key, value] of Object.entries(result.outputs)) {
|
|
94
|
+
allOutputs[key] = String(value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const stackName = getApplicationStackName(operation.appName, result.stack);
|
|
98
|
+
const hash = detection.currentHashes.get(stackName);
|
|
99
|
+
if (hash) {
|
|
100
|
+
deployedHashes.set(stackName, hash);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return success(undefined);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Deploy a single stack with step lifecycle events and output collection.
|
|
107
|
+
*/
|
|
108
|
+
export async function deployStackSequential(stack, services, context, callbacks, stepIndex, totalSteps, allOutputs) {
|
|
109
|
+
const stepId = getApplicationStepId(stack, "deploy");
|
|
110
|
+
const stepName = getApplicationStepName(stack, "deploy");
|
|
111
|
+
callbacks.onStepStart?.(stepId, stepName, stepIndex, totalSteps);
|
|
112
|
+
const result = await services.stackService.deployStack(stack, context, {
|
|
113
|
+
onOutput: forwardOutput(callbacks),
|
|
114
|
+
onResourceProgress: forwardResourceProgress(callbacks)
|
|
115
|
+
});
|
|
116
|
+
if (!result.success) {
|
|
117
|
+
callbacks.onStepComplete?.(stepId, stepName, "error", stepIndex, totalSteps);
|
|
118
|
+
callbacks.onError?.(result.error);
|
|
119
|
+
return failure(result.error);
|
|
120
|
+
}
|
|
121
|
+
callbacks.onStepComplete?.(stepId, stepName, "completed", stepIndex, totalSteps);
|
|
122
|
+
if (result.data.outputs) {
|
|
123
|
+
for (const [key, value] of Object.entries(result.data.outputs)) {
|
|
124
|
+
allOutputs[key] = String(value);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return success(undefined);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Run Docker build/push or welcome image setup before the Compute stack.
|
|
131
|
+
* Returns a failure Result if Docker operations fail, or null if not applicable/successful.
|
|
132
|
+
*/
|
|
133
|
+
export async function runDockerPreCompute(stack, params, services, operation, callbacks, hasDockerfileOnDisk) {
|
|
134
|
+
if (stack !== APPLICATION_STACKS.COMPUTE || !params.dockerProvider)
|
|
135
|
+
return null;
|
|
136
|
+
if (hasDockerfileOnDisk) {
|
|
137
|
+
const dockerResult = await runDockerBuild(params, services, operation, callbacks);
|
|
138
|
+
if (!dockerResult.success)
|
|
139
|
+
return failure(dockerResult.error);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const ecrInitResult = await runWelcomeImageSetup(params, services, operation, callbacks);
|
|
143
|
+
if (!ecrInitResult.success)
|
|
144
|
+
return failure(ecrInitResult.error);
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Deploy all stacks unconditionally (deployOnly mode).
|
|
150
|
+
* Skips CDK synth/hash comparison — uses the framework registry to determine
|
|
151
|
+
* deploy order, then deploys every stack sequentially.
|
|
152
|
+
*/
|
|
153
|
+
export async function deployAllStacks(params, services, operation, context, startTime, plan) {
|
|
154
|
+
const { callbacks } = params;
|
|
155
|
+
// Use plan from registry if available, otherwise resolve now
|
|
156
|
+
let deployOrder;
|
|
157
|
+
if (plan) {
|
|
158
|
+
deployOrder = plan.deployOrder;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const resolved = services.frameworkRegistry.resolve({
|
|
162
|
+
appPath: operation.path
|
|
163
|
+
});
|
|
164
|
+
if (resolved) {
|
|
165
|
+
const freshPlan = resolved.builder.plan({ appPath: operation.path }, resolved.detection);
|
|
166
|
+
deployOrder = freshPlan.deployOrder;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
deployOrder = getApplicationDeployOrder();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const totalSteps = deployOrder.length;
|
|
173
|
+
// Bootstrap
|
|
174
|
+
const bsResult = await bootstrapOrFail(services, context, callbacks);
|
|
175
|
+
if (!bsResult.success)
|
|
176
|
+
return bsResult;
|
|
177
|
+
// Deploy all stacks sequentially
|
|
178
|
+
const allOutputs = {};
|
|
179
|
+
for (let i = 0; i < deployOrder.length; i++) {
|
|
180
|
+
const stack = deployOrder[i];
|
|
181
|
+
// Docker operations before Compute stack
|
|
182
|
+
const dockerFailed = await runDockerPreCompute(stack, params, services, operation, callbacks, hasDockerfile(operation.path));
|
|
183
|
+
if (dockerFailed)
|
|
184
|
+
return dockerFailed;
|
|
185
|
+
const deployResult = await deployStackSequential(stack, services, context, callbacks, i, totalSteps, allOutputs);
|
|
186
|
+
if (!deployResult.success)
|
|
187
|
+
return failure(deployResult.error);
|
|
188
|
+
}
|
|
189
|
+
// Resolve website URL
|
|
190
|
+
const websiteUrl = await services.stackService.resolveWebsiteUrl(operation.appName);
|
|
191
|
+
if (websiteUrl) {
|
|
192
|
+
allOutputs.websiteUrl = websiteUrl;
|
|
193
|
+
}
|
|
194
|
+
return success({
|
|
195
|
+
target: operation.appName,
|
|
196
|
+
deploymentType: "application",
|
|
197
|
+
outputs: Object.keys(allOutputs).length > 0 ? allOutputs : undefined,
|
|
198
|
+
durationMs: Date.now() - startTime
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Bridge DeployCallbacks to BuildCallbacks.
|
|
203
|
+
* Fires both legacy OpenNext-specific callbacks and generic build callbacks
|
|
204
|
+
* for backwards compatibility during the transition period.
|
|
205
|
+
*/
|
|
206
|
+
export function createBuildCallbacks(callbacks) {
|
|
207
|
+
return {
|
|
208
|
+
onBuildStart: (builderName) => {
|
|
209
|
+
callbacks.onOpenNextBuildStart?.();
|
|
210
|
+
callbacks.onLog?.(`${builderName} build started`, "info");
|
|
211
|
+
},
|
|
212
|
+
onBuildProgress: (_builderName, message) => {
|
|
213
|
+
callbacks.onOpenNextProgress?.(message);
|
|
214
|
+
},
|
|
215
|
+
onBuildComplete: (builderName) => {
|
|
216
|
+
callbacks.onOpenNextBuildComplete?.();
|
|
217
|
+
callbacks.onLog?.(`${builderName} build complete`, "info");
|
|
218
|
+
},
|
|
219
|
+
onBuildError: (_builderName, error) => {
|
|
220
|
+
callbacks.onOpenNextBuildError?.(error);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Result } from "@fjall/generator";
|
|
2
|
+
import type { DestroyParams, DestroyResult } from "../types/params.js";
|
|
3
|
+
import type { ApplicationOperation } from "../types/operations.js";
|
|
4
|
+
import type { DeployServices } from "./serviceFactory.js";
|
|
5
|
+
/**
|
|
6
|
+
* Core application destruction orchestration.
|
|
7
|
+
*
|
|
8
|
+
* Detects application pattern, determines destroy order (reverse of deploy),
|
|
9
|
+
* then destroys stacks sequentially or in parallel groups. Delegates all
|
|
10
|
+
* CDK operations to the ApplicationStackService.destroyAllStacks() method,
|
|
11
|
+
* which handles "stack doesn't exist" → success conversion and parallel
|
|
12
|
+
* phase orchestration for OpenNext patterns.
|
|
13
|
+
*/
|
|
14
|
+
export declare function destroyApplication(params: DestroyParams, services: DeployServices, operation: ApplicationOperation): Promise<Result<DestroyResult>>;
|