@fjall/deploy-core 9.0.0 → 10.1.1
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/dist/.build-source-hash +27 -23
- package/dist/.minified +1 -1
- package/dist/src/index.d.ts +5 -2
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/application/applicationDeploy.js +1 -1
- package/dist/src/orchestration/application/applicationDeployHelpers.js +3 -3
- package/dist/src/orchestration/application/deploySessionPolicy.js +1 -1
- package/dist/src/orchestration/application/ecsDeploymentTail.d.ts +48 -0
- package/dist/src/orchestration/application/ecsDeploymentTail.js +3 -0
- package/dist/src/orchestration/application/schemaGateImage.d.ts +32 -0
- package/dist/src/orchestration/application/schemaGateImage.js +1 -0
- package/dist/src/orchestration/deploy.js +1 -1
- package/dist/src/orchestration/failure/classifyFailure.d.ts +58 -0
- package/dist/src/orchestration/failure/classifyFailure.js +1 -0
- package/dist/src/orchestration/failure/deploymentFailureAttachment.d.ts +18 -0
- package/dist/src/orchestration/failure/deploymentFailureAttachment.js +1 -0
- package/dist/src/orchestration/index.d.ts +2 -2
- package/dist/src/orchestration/index.js +1 -1
- package/dist/src/orchestration/organisation/reconcileProviderAccounts.js +1 -1
- package/dist/src/orchestration/restart/restartApplication.d.ts +34 -0
- package/dist/src/orchestration/restart/restartApplication.js +1 -1
- package/dist/src/services/infrastructure/EcsService.d.ts +35 -0
- package/dist/src/services/infrastructure/EcsService.js +1 -1
- package/dist/src/types/callbackKeys.d.ts +1 -1
- package/dist/src/types/callbackKeys.js +1 -1
- package/dist/src/types/callbacks.d.ts +11 -0
- package/dist/src/types/config/FjallState.js +1 -1
- package/dist/src/types/events.d.ts +15 -0
- package/package.json +4 -4
package/dist/.build-source-hash
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"package.json",
|
|
10
10
|
"tsconfig.json"
|
|
11
11
|
],
|
|
12
|
-
"hash": "
|
|
12
|
+
"hash": "2c11b6ffb0cf61420ceefdf5ed71b69f9a10d2a7d5f745cefd5599b4e056bb79",
|
|
13
13
|
"files": {
|
|
14
14
|
"src/__test-utils__/awsMockHelpers.ts": "fea371c1b1869678",
|
|
15
15
|
"src/__test-utils__/index.ts": "e03cf35821157dc4",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"src/aws/utils/regions.ts": "3a5191f4d2242a60",
|
|
53
53
|
"src/aws/utils/stackStatus.ts": "55fb23ba5514bc13",
|
|
54
54
|
"src/events/index.ts": "e55c022f0d9013e6",
|
|
55
|
-
"src/index.ts": "
|
|
55
|
+
"src/index.ts": "28221a2c59ab861d",
|
|
56
56
|
"src/orchestration/activeDeploymentGuard.ts": "e8dde742c00ea728",
|
|
57
|
-
"src/orchestration/application/applicationDeploy.ts": "
|
|
58
|
-
"src/orchestration/application/applicationDeployHelpers.ts": "
|
|
57
|
+
"src/orchestration/application/applicationDeploy.ts": "867232cbc981906c",
|
|
58
|
+
"src/orchestration/application/applicationDeployHelpers.ts": "bca833cc04f0b4c5",
|
|
59
59
|
"src/orchestration/application/applicationDestroy.ts": "38b8ecf69c85d884",
|
|
60
60
|
"src/orchestration/application/approvalGate.ts": "e4dee819c94fd15c",
|
|
61
61
|
"src/orchestration/application/artefactCollection.ts": "b77848c922765d30",
|
|
@@ -66,12 +66,13 @@
|
|
|
66
66
|
"src/orchestration/application/buildSecretSession.ts": "b45265140a3a781a",
|
|
67
67
|
"src/orchestration/application/codeOnlyDeploy.ts": "062b0acdad1dcf08",
|
|
68
68
|
"src/orchestration/application/databaseEndpointReconcile.ts": "27b14ee41524c632",
|
|
69
|
-
"src/orchestration/application/deploySessionPolicy.ts": "
|
|
69
|
+
"src/orchestration/application/deploySessionPolicy.ts": "8052c64ce050c2b8",
|
|
70
70
|
"src/orchestration/application/destroyPreFlight.ts": "cc4978dec60b033e",
|
|
71
71
|
"src/orchestration/application/destructionGate.ts": "3b64832555e15887",
|
|
72
72
|
"src/orchestration/application/detectionPipeline.ts": "580a62c8093f96ce",
|
|
73
73
|
"src/orchestration/application/dockerBuildHelper.ts": "e7a7259e987d93be",
|
|
74
74
|
"src/orchestration/application/ecrCacheRepository.ts": "d7a5602ccabde493",
|
|
75
|
+
"src/orchestration/application/ecsDeploymentTail.ts": "d9ff18631984b2e5",
|
|
75
76
|
"src/orchestration/application/engineCompat.ts": "d3e1cbf906bc785d",
|
|
76
77
|
"src/orchestration/application/lambdaCodeOnlyRollout.ts": "fc347b90ff55c1fd",
|
|
77
78
|
"src/orchestration/application/leaseGate.ts": "26be2e119b32bef4",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"src/orchestration/application/plan/renameDetection.ts": "a4a96ad3c175dd5a",
|
|
90
91
|
"src/orchestration/application/plan/renderDeployPlan.ts": "13a01fc9b11e1cf7",
|
|
91
92
|
"src/orchestration/application/plan/types.ts": "45c3bf684cd90f9f",
|
|
93
|
+
"src/orchestration/application/schemaGateImage.ts": "587a115432c6678e",
|
|
92
94
|
"src/orchestration/application/serviceImageTagsRollback.ts": "55e23a493545511c",
|
|
93
95
|
"src/orchestration/application/taskDefinitionRoll.ts": "d9378c509c7ec287",
|
|
94
96
|
"src/orchestration/application/welcomeImageHelper.ts": "1721ea7edc37a96e",
|
|
@@ -99,7 +101,7 @@
|
|
|
99
101
|
"src/orchestration/builders/openNextBuilder.ts": "7416a37e19380660",
|
|
100
102
|
"src/orchestration/builders/staticSiteBuilder.ts": "a0403be58052310f",
|
|
101
103
|
"src/orchestration/contextHelpers.ts": "b38af2503a974f16",
|
|
102
|
-
"src/orchestration/deploy.ts": "
|
|
104
|
+
"src/orchestration/deploy.ts": "5cbdc229366ea1e6",
|
|
103
105
|
"src/orchestration/deployEnvironment.ts": "acfddd575949b7ca",
|
|
104
106
|
"src/orchestration/destroy.ts": "b6da154984e63a8d",
|
|
105
107
|
"src/orchestration/dockerBuildParamsKeys.ts": "ac3d6ecd24d68792",
|
|
@@ -115,13 +117,15 @@
|
|
|
115
117
|
"src/orchestration/domainInterface.ts": "2187279bbd26144d",
|
|
116
118
|
"src/orchestration/drift/classifyDriftFailure.ts": "4426ecc6545b0472",
|
|
117
119
|
"src/orchestration/drift/detectStackDrift.ts": "cc38b12162e08fac",
|
|
118
|
-
"src/orchestration/drift/driftPreFlight.ts": "
|
|
120
|
+
"src/orchestration/drift/driftPreFlight.ts": "87c6176636655ad7",
|
|
119
121
|
"src/orchestration/drift/driftProbe.ts": "970ccb185c6efe83",
|
|
120
122
|
"src/orchestration/drift/driftSuspectJournal.ts": "d0189a53a7b7cb7e",
|
|
121
123
|
"src/orchestration/drift/preFlightGate.ts": "8067a3f474fba0b5",
|
|
122
124
|
"src/orchestration/drift/route53Names.ts": "1ac53cc30ac3260e",
|
|
123
125
|
"src/orchestration/drift/route53RecordPreflight.ts": "f4db16a6c0e69ac9",
|
|
124
|
-
"src/orchestration/
|
|
126
|
+
"src/orchestration/failure/classifyFailure.ts": "bfb80731bc7d6b95",
|
|
127
|
+
"src/orchestration/failure/deploymentFailureAttachment.ts": "358d9e4d88390cfd",
|
|
128
|
+
"src/orchestration/index.ts": "0b230a38e1ef50d2",
|
|
125
129
|
"src/orchestration/manifestSecretParser.ts": "c5576bd88a3652f8",
|
|
126
130
|
"src/orchestration/organisation/accountsConfig.ts": "a55a3306564e7b2f",
|
|
127
131
|
"src/orchestration/organisation/cascadeDestroyHelpers.ts": "46ca8e144ea76db2",
|
|
@@ -130,7 +134,7 @@
|
|
|
130
134
|
"src/orchestration/organisation/organisationDeploy.ts": "f3fad626230d8a16",
|
|
131
135
|
"src/orchestration/organisation/organisationDestroy.ts": "06076a7e76345854",
|
|
132
136
|
"src/orchestration/organisation/organisationSetup.ts": "3f3415b762a83a47",
|
|
133
|
-
"src/orchestration/organisation/reconcileProviderAccounts.ts": "
|
|
137
|
+
"src/orchestration/organisation/reconcileProviderAccounts.ts": "91920b2ed61dd811",
|
|
134
138
|
"src/orchestration/organisationDeploy/cascadeExecution.ts": "ebc32ef8857d8037",
|
|
135
139
|
"src/orchestration/organisationDeploy/infraSteps.ts": "53880cef5020dd04",
|
|
136
140
|
"src/orchestration/organisationDeploy/orgCascadeDeploy.ts": "97a85277580be283",
|
|
@@ -148,11 +152,11 @@
|
|
|
148
152
|
"src/orchestration/remediation/postFailureRepairOffer.ts": "934b3fbd1c4d34d1",
|
|
149
153
|
"src/orchestration/remediation/recreatePreFlight.ts": "654ef18cabe97777",
|
|
150
154
|
"src/orchestration/remediation/recreateResource.ts": "a9d97c47e0af68a7",
|
|
151
|
-
"src/orchestration/remediation/remediationJournal.ts": "
|
|
155
|
+
"src/orchestration/remediation/remediationJournal.ts": "5ebb14e618fde1c1",
|
|
152
156
|
"src/orchestration/remediation/removalUpdate.ts": "805be54eb0ac1623",
|
|
153
|
-
"src/orchestration/remediation/retainFlip.ts": "
|
|
157
|
+
"src/orchestration/remediation/retainFlip.ts": "80e7b47e87251db5",
|
|
154
158
|
"src/orchestration/resolveOperation.ts": "84a9f425939fad63",
|
|
155
|
-
"src/orchestration/restart/restartApplication.ts": "
|
|
159
|
+
"src/orchestration/restart/restartApplication.ts": "3320b6aef19da793",
|
|
156
160
|
"src/orchestration/restart/secretsDrift.ts": "53b91db6f8f7f04d",
|
|
157
161
|
"src/orchestration/secretArnResolver.ts": "20041aca6eb7e762",
|
|
158
162
|
"src/orchestration/serviceFactory.ts": "ec35c9eb8015d540",
|
|
@@ -173,7 +177,7 @@
|
|
|
173
177
|
"src/orchestration/unlock/restoreAndReconcileQuarantinedBucket.ts": "c534511ed49952ad",
|
|
174
178
|
"src/orchestration/unlock/restoreBucketPolicy.ts": "f266285ffacf3cf6",
|
|
175
179
|
"src/orchestration/unlock/scpRemediation.ts": "c5d425c850abe455",
|
|
176
|
-
"src/orchestration/unlock/toResourcePolicyStatements.ts": "
|
|
180
|
+
"src/orchestration/unlock/toResourcePolicyStatements.ts": "b3d91460e2d31457",
|
|
177
181
|
"src/orchestration/unlock/unlockBucket.ts": "d08d7cb6243d7cec",
|
|
178
182
|
"src/orchestration/unlock/unlockQueue.ts": "f7e8eccc258d763d",
|
|
179
183
|
"src/services/application/ApplicationStackService.ts": "45f697f7f884af0a",
|
|
@@ -192,7 +196,7 @@
|
|
|
192
196
|
"src/services/infrastructure/CfnRegistryService.ts": "bd4f57d97982cdda",
|
|
193
197
|
"src/services/infrastructure/CloudFormationService.ts": "82ce03614feae2db",
|
|
194
198
|
"src/services/infrastructure/EcrImageInspectorService.ts": "e784440b5680df74",
|
|
195
|
-
"src/services/infrastructure/EcsService.ts": "
|
|
199
|
+
"src/services/infrastructure/EcsService.ts": "8a3b6e921bf06c60",
|
|
196
200
|
"src/services/infrastructure/EcsServiceResolver.ts": "4d548cd42e746feb",
|
|
197
201
|
"src/services/infrastructure/ICdkProcessManager.ts": "7e7bfe7dacc999f6",
|
|
198
202
|
"src/services/infrastructure/LambdaService.ts": "5b21e34185e77a4c",
|
|
@@ -203,7 +207,7 @@
|
|
|
203
207
|
"src/services/infrastructure/cfnRegistrySeed.ts": "b1232b66883d6f90",
|
|
204
208
|
"src/services/infrastructure/changeSetProbe.ts": "5f3e100db396cf9b",
|
|
205
209
|
"src/services/infrastructure/constructMapEnrichment.ts": "7400af9bcfaa0da3",
|
|
206
|
-
"src/services/infrastructure/dependencyIntegrityGate.ts": "
|
|
210
|
+
"src/services/infrastructure/dependencyIntegrityGate.ts": "063a3539a0fa9a86",
|
|
207
211
|
"src/services/infrastructure/index.ts": "c45e43711bf64fa9",
|
|
208
212
|
"src/services/infrastructure/infraTypecheckPreflight.ts": "09e423a8283e3b8b",
|
|
209
213
|
"src/services/infrastructure/transientNetworkRecovery.ts": "264b9a16fea86869",
|
|
@@ -218,10 +222,10 @@
|
|
|
218
222
|
"src/types/application/ApplicationServiceTypes.ts": "e5185e9ef24a1625",
|
|
219
223
|
"src/types/application/index.ts": "c44d78d2209c4b09",
|
|
220
224
|
"src/types/approval.ts": "d5b7741f677d5f21",
|
|
221
|
-
"src/types/callbackKeys.ts": "
|
|
222
|
-
"src/types/callbacks.ts": "
|
|
223
|
-
"src/types/config/DomainState.ts": "
|
|
224
|
-
"src/types/config/FjallState.ts": "
|
|
225
|
+
"src/types/callbackKeys.ts": "6122dbe3502abd97",
|
|
226
|
+
"src/types/callbacks.ts": "195275d1eb5dfb5e",
|
|
227
|
+
"src/types/config/DomainState.ts": "76a076a1735ac6cd",
|
|
228
|
+
"src/types/config/FjallState.ts": "e586d9c72c177dea",
|
|
225
229
|
"src/types/config/entitlements.ts": "f69ad28847b67e9a",
|
|
226
230
|
"src/types/config/orgConfig.ts": "452866f049cbd71d",
|
|
227
231
|
"src/types/constants.ts": "4d77e1ab4925b9a6",
|
|
@@ -244,7 +248,7 @@
|
|
|
244
248
|
"src/types/errors/CdkError.ts": "6bda32540c93bac9",
|
|
245
249
|
"src/types/errors/ServiceError.ts": "06d269a22c2a05d6",
|
|
246
250
|
"src/types/errors/index.ts": "e3bf5e08988d1182",
|
|
247
|
-
"src/types/events.ts": "
|
|
251
|
+
"src/types/events.ts": "5f0e756e98914442",
|
|
248
252
|
"src/types/frameworkBuilder.ts": "41198a0b446f60b6",
|
|
249
253
|
"src/types/index.ts": "eb45188ded4c08b4",
|
|
250
254
|
"src/types/operations.ts": "57a6c9e22a3f37ca",
|
|
@@ -258,9 +262,9 @@
|
|
|
258
262
|
"src/util/sleepAbortable.ts": "f9cac3bf8a79a476",
|
|
259
263
|
"src/version.ts": "1811a4475823b27e",
|
|
260
264
|
"../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
|
|
261
|
-
"package.json": "
|
|
265
|
+
"package.json": "4f4fa1478ced177c",
|
|
262
266
|
"tsconfig.json": "1929cf3f99fe9b1e"
|
|
263
267
|
},
|
|
264
|
-
"outputHash": "
|
|
265
|
-
"outputFileCount":
|
|
268
|
+
"outputHash": "fe73823703703c13648f60288dcf3b3064f0814b24d460adbaf1188ae62bf266",
|
|
269
|
+
"outputFileCount": 493
|
|
266
270
|
}
|
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
246 files minified at 2026-08-11T21:57:14.597Z
|
package/dist/src/index.d.ts
CHANGED
|
@@ -54,8 +54,8 @@ export { type Result, success, failure, isSuccess, isFailure } from "@fjall/gene
|
|
|
54
54
|
export { deploy } from "./orchestration/index.js";
|
|
55
55
|
export { destroy } from "./orchestration/index.js";
|
|
56
56
|
export { buildParamsContext } from "./orchestration/contextHelpers.js";
|
|
57
|
-
export { restart, probeSecretsDrift, computeSecretsDrift, deriveStaleParameters, extractConsumedSsmParameters } from "./orchestration/index.js";
|
|
58
|
-
export type { RestartParams, RestartResult, SecretsDriftProbeParams, ApplicationSecretsDrift, ServiceSecretsDrift, StaleParameter } from "./orchestration/index.js";
|
|
57
|
+
export { restart, probeSecretsDrift, probeServiceDeploymentStatus, computeSecretsDrift, deriveStaleParameters, extractConsumedSsmParameters } from "./orchestration/index.js";
|
|
58
|
+
export type { RestartParams, RestartResult, SecretsDriftProbeParams, ServiceDeploymentStatus, ApplicationServiceStatus, ApplicationSecretsDrift, ServiceSecretsDrift, StaleParameter } from "./orchestration/index.js";
|
|
59
59
|
export { partitionAccounts } from "./orchestration/index.js";
|
|
60
60
|
export { buildRegionList, buildAccountRegionPairs, cascadeHomeRegion, cascadeOperationKey } from "./orchestration/index.js";
|
|
61
61
|
export type { AccountRegionPair } from "./orchestration/index.js";
|
|
@@ -96,3 +96,6 @@ export { buildDeployPlan, computeDeployPlan, computeAssemblyDigest, digestHead,
|
|
|
96
96
|
export type { DeployPlan, DeployPlanResourceChange, StackTemplatePair, CfnTemplateReader, ComputeDeployPlanParams, ComputeDeployPlanStack, ImpactClassification, DeployScope, SignApprovalTokenOptions, SignedApprovalToken, VerifyApprovalTokenOptions, VerifyApprovalTokenResult, RunApprovalGateParams, ApprovalGateOutcome } from "./orchestration/index.js";
|
|
97
97
|
export { runDestructionGate, buildDestructionTicket, evaluateDestructionConsents, computeTicketDigest, legalRemediationVerbs, executableRemediationVerbs, advertisableRemediationVerbs, renderDestructionTicketLines, renderConsentVerdictLines, loadDeployPlan, createMemoisedPlanLoader } from "./orchestration/index.js";
|
|
98
98
|
export type { RunDestructionGateParams, DestructionGateOutcome, EvaluateDestructionConsentsParams, LoadDeployPlanParams, DeployPlanLoader } from "./orchestration/index.js";
|
|
99
|
+
export { DEPLOYMENT_FAILURE_CLASSIFIER_VERSION, classifyDeployFailure, classifyFromEcsCompletion, classifyFromFailureAnalysis, classifyUnclassified } from "./orchestration/failure/classifyFailure.js";
|
|
100
|
+
export type { ClassifyDeployFailureInput, ClassifyUnclassifiedOptions } from "./orchestration/failure/classifyFailure.js";
|
|
101
|
+
export { attachDeploymentFailure, getDeploymentFailure } from "./orchestration/failure/deploymentFailureAttachment.js";
|
package/dist/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEPLOY_CORE_VERSION_GLOBAL as t}from"./version.js";import{DeploymentEventSchema as i,DEPLOYMENT_EVENT_TYPES as a,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as n,DEPLOYMENT_EVENT_STATUS_REASON_MAX as s,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as E,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as c,DEPLOYMENT_ERROR_MESSAGE_MAX as S,CASCADE_PHASES as l,CASCADE_ACCOUNT_STATUSES as T,clampDeploymentEventStrings as _,truncateUtf16Safe as A}from"./types/index.js";import{DeployEventSchema as p,StepProgressSchema as m,DeployResourceSchema as d,PlanChangeSchema as u,PlanPropertyChangeSchema as P,ChangeCountsSchema as D,DEPLOY_EVENT_CONTRACT as O,DEPLOY_EVENT_CONTRACT_MAJOR as f,DEPLOY_EVENT_CONTRACT_MINOR as C,SUPPORTED_CONTRACT_MARKERS as N,DEPLOY_EVENT_ID_MAX as L,DEPLOY_EVENT_NAME_MAX as g,DEPLOY_EVENT_MESSAGE_MAX as I,DEPLOY_EVENT_STATUS_REASON_MAX as y,DEPLOY_EVENT_ERROR_MESSAGE_MAX as h,DEPLOY_EVENT_TRAIL_DETAIL_MAX as M,DEPLOY_EVENT_OUTPUT_MAX as x,DEPLOY_EVENT_ARN_MAX as v,DEPLOY_EVENT_URL_MAX as U,STEP_COMPLETE_STATUSES as F,LOG_LEVELS as b,STACK_CLEANUP_PHASES as k,CASCADE_ACCOUNT_PHASES as Y,DEPLOY_RESULTS as V,DETECTION_PHASES as G,PHASE_STATUSES as B,BUILDERS as K,CASCADE_OUTCOME_RESULTS as X,PLAN_ACTIONS as H,REPLACEMENT_MODES as w,APPROVAL_KINDS as J,APPROVAL_DECISIONS as Q,ALL_PROGRESS_KINDS as j,createDeployEmitter as W,parseDeployEvent as Z,parseDeployContractVersion as q}from"./types/index.js";import{SimpleAwsProvider as $}from"./aws/index.js";import{checkTargetReadiness as re,describeTargetReadinessReason as te,buildTargetUnreadyAdvisory as oe,buildTargetSetUnreadyAdvisory as ie,probeAccountStackExists as ae}from"./aws/index.js";import{checkRegionEnabled as se,regionDisabledMessage as Ee}from"./aws/index.js";import{ensureOrganisationExists as Se,describeOrganisation as le,enablePolicyTypes as Te,enableServiceAccess as _e,SERVICE_PRINCIPALS as Ae,enableRamSharing as Re,activateTrustedAccess as pe,enableIpamDelegatedAdmin as me,updateBackupGlobalSettings as de,listAccounts as ue,findAccount as Pe,createAccount as De,ensureOrganisationalUnitsExist as Oe,placeAccountsInOUs as fe,buildAccountToOUMap as Ce,findDevelopmentOuId as Ne,activateCostAllocationTags as Le,checkIdentityCentreStatus as ge,snapshotIdentityCentre as Ie,composeSdkAbortSignal as ye,extractErrorName as he,isAborted as Me,DEFAULT_MAX_PAGES as xe,IDENTITY_STORE_PAGE_SIZE as ve,drainPages as Ue,isOULeaf as Fe,registerSecurityDelegates as be,SECURITY_SERVICE_PRINCIPALS as ke,enableCentralisedRootAccess as Ye,ROOT_ACCESS_FEATURES as Ve,RootAccessEnablementError as Ge}from"./aws/index.js";import{STEP_IDS as Ke,STEP_NAMES as Xe,INFRASTRUCTURE_STEP_NAMES as He,INFRA_STEP_NAME as we}from"./types/index.js";import{RemediationVerbSchema as Qe,REMEDIATION_VERB_GLOSS as je,IDENTITY_PIN_SLOT_SWAP_GLOSS as We,DestructionFindingSchema as Ze,DestructionTicketResourceSchema as qe,DestructionTicketSchema as ze,DestructionConsentSchema as $e,DestructionOutcomeSchema as er,DESTRUCTION_FINDINGS as rr,CONSENT_VERDICTS as tr,TICKET_VERDICT_SOURCES as or,TicketVerdictSourceSchema as ir}from"./types/index.js";import{DRIFT_VERDICTS as nr,DriftVerdictSchema as sr,DriftSuspectSchema as Er,DriftFindingSchema as cr,DriftJournalRecordSchema as Sr,verbsForDriftVerdict as lr}from"./types/index.js";import{REMEDIATION_PHASES as _r,RemediationPhaseSchema as Ar,RemediationTargetSchema as Rr,RemediationFlipProofSchema as pr,RemediationJournalRecordSchema as mr,RemediationVerbWithSurgerySchema as dr,remediationPhaseRank as ur,remediationPlaceholderPhysicalId as Pr,isRemediationPlaceholderPhysicalId as Dr}from"./types/index.js";import{ProgressReporter as fr,APPLICATION_STACKS as Cr,ORGANISATION_TYPES as Nr,APPLICATION_DEPLOY_ORDER as Lr,APPLICATION_DESTROY_ORDER as gr,OPENNEXT_DEPLOY_ORDER as Ir,OPENNEXT_DESTROY_ORDER as yr,PARALLEL_DEPLOY_GROUPS as hr,PARALLEL_DESTROY_GROUPS as Mr,OPENNEXT_PARALLEL_GROUPS as xr,PARALLEL_OPERATION_TYPES as vr,isApplicationOperation as Ur,isOrganisationOperation as Fr,getParallelDeployGroups as br,getParallelDestroyGroups as kr,getApplicationDeployOrder as Yr,getApplicationDestroyOrder as Vr,getApplicationStackName as Gr,getOrganisationStackName as Br,isApplicationStack as Kr,isQuarantineDetail as Xr,isRetainedBucketsDetail as Hr,getApplicationStepName as wr,getApplicationStepId as Jr,toPascalCase as Qr,isOpenNextPattern as jr,OPENNEXT_PATTERNS as Wr,STACK_NOT_FOUND_PATTERN as Zr,STACK_FAILED_STATE_PATTERN as qr,CDK_NO_STACKS_MATCH as zr,INFRASTRUCTURE_FILENAME as $r,ApplicationError as et,wrapApplicationError as rt,stubCallerIdentity as tt}from"./types/index.js";import{deriveResourcesFromManifestStacks as it}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as nt,readStateFile as st,writeStateFile as Et,createEmptyState as ct,deleteStateFile as St,updateTemplateHash as lt,getStateFilePath as Tt,regionSuffix as _t}from"./types/config/FjallState.js";import{readDomainState as Rt,writeDomainState as pt,recordDomainDeployState as mt,deleteDomainState as dt,hashDomainDirectory as ut,LEGACY_DOMAIN_STATE_FILENAME as Pt}from"./types/config/DomainState.js";import{CloudFormationEventMonitor as Ot}from"./aws/index.js";import{CdkService as Ct,CdkArgumentBuilder as Nt,CdkProcessManager as Lt,ensureDependencyIntegrity as gt,clearDependencyIntegrityCache as It,DEPENDENCY_SYNC_TIMEOUT_MS as yt,CdkEventMonitor as ht,startStackMonitoring as Mt,DEFAULT_DEPLOY_TIMEOUT_MS as xt,isCdkError as vt,formatInfrastructureError as Ut,getStructuralHint as Ft,getSourceContext as bt,hasCdkDifferences as kt,parseDiffOutput as Yt,CloudFormationService as Vt,CloudFormationError as Gt,EcsService as Bt,EcsError as Kt,EcsServiceResolver as Xt,TemplateHashService as Ht,TemplateHashError as wt,CdkContextBuilder as Jt,emitProgress as Qt,PROGRESS_MESSAGES as jt,parseBuildPhase as Wt,buildStepContextBuildConfig as Zt,convertCloudFormationOutputsToRecord as qt,ApplicationStackService as zt}from"./services/index.js";import{CdkError as eo}from"./types/errors/index.js";import{BaseServiceError as to,ValidationError as oo,AuthError as io,AwsError as ao,DeploymentError as no,NetworkError as so,FileSystemError as Eo,ConfigError as co,toServiceError as So}from"./types/errors/index.js";import{filterDangerousEnvVars as To,maskSensitiveOutput as _o,parseShellArgs as Ao,sleep as Ro}from"@fjall/util";import{artefactOutputKey as mo,DeployModeSchema as uo,ServiceArtefactSchema as Po,ServiceArtefactsSchema as Do}from"@fjall/util";import{hasDockerfile as fo}from"./util/dockerfileDetection.js";import{sleepAbortable as No}from"./util/sleepAbortable.js";import{createSequencedCallbacks as go}from"./util/sequencedCallbacks.js";import{fileExists as yo}from"@fjall/util/fsHelpers";import{success as Mo,failure as xo,isSuccess as vo,isFailure as Uo}from"@fjall/generator";import{deploy as bo}from"./orchestration/index.js";import{destroy as Yo}from"./orchestration/index.js";import{buildParamsContext as Go}from"./orchestration/contextHelpers.js";import{restart as Ko,probeSecretsDrift as Xo,computeSecretsDrift as Ho,deriveStaleParameters as wo,extractConsumedSsmParameters as Jo}from"./orchestration/index.js";import{partitionAccounts as jo}from"./orchestration/index.js";import{buildRegionList as Zo,buildAccountRegionPairs as qo,cascadeHomeRegion as zo,cascadeOperationKey as $o}from"./orchestration/index.js";import{projectScalarSummary as ri,projectAccountRows as ti}from"./orchestration/index.js";import{reconcileProviderAccounts as ii,mergeReconciledProviderAccounts as ai}from"./orchestration/index.js";import{decideNextTransition as si,reconcileTrailMigration as Ei,decommissionMemberTrailStorage as ci,ORG_TRAIL_BUCKET_OUTPUT_KEY as Si,TRAIL_BUCKET_OUTPUT_KEY as li,TRAIL_KEY_ARN_OUTPUT_KEY as Ti}from"./orchestration/index.js";import{classifyDriftFailure as Ai,fetchLastOperationEvents as Ri,DriftProbe as pi,clearDriftSuspects as mi,defaultDriftJournalDir as di,readDriftSuspects as ui,recordDriftSuspects as Pi,detectStackDrift as Di,runDriftPreFlight as Oi,formatDriftPreFlightBlock as fi,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Ci,DRIFT_PREFLIGHT_BUDGET_MS as Ni,runRoute53RecordPreflight as Li}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as Ii,computeRemediationOpId as yi,defaultRemediationJournalDir as hi,findRemediationJournalByOpId as Mi,listActiveRemediationOps as xi,listActiveRemediationOpsForContext as vi,readRemediationJournal as Ui,sweepExpiredRemediationJournals as Fi,writeRemediationJournal as bi,REMEDIATION_JOURNAL_RETENTION_DAYS as ki,captureRemediationForensics as Yi,defaultRemediationForensicsDir as Vi,applyRetainFlip as Gi,composeFlipCapabilities as Bi,computeTemplateDigest as Ki,deriveRetainFlipTemplate as Xi,findMarkedResourcesByOpId as Hi,proveFlipMetadataOnly as wi,readRetainFlipState as Ji,verifyRetainFlipDiff as Qi,FORGET_MARKER_KEY as ji,FORGET_FLIP_SPEC as Wi,RECREATE_MARKER_KEY as Zi,assessForgetResumability as qi,completeForgetAfterConverge as zi,completeForgetAfterDeploy as $i,formatRecreateInFlightCures as ea,partitionPreFlightByRemediation as ra,runForgetSurgery as ta,synthTemplateDeclaresResource as oa,runRecreateSurgery as ia,snapshotPolicyForType as aa,SNAPSHOT_CAPABLE_RESOURCE_TYPES as na,runRecreatePreFlight as sa,deriveRemovalTemplate as Ea,findRemovalDeletionFailures as ca,findResourcesPresent as Sa,proveRemovalTargetsOnly as la,advertisableDriftVerbs as Ta,buildDriftRepairTicket as _a,runDriftRepairGate as Aa,formatPinOutcomeDetail as Ra,pinProbeCoverage as pa,renderPinReportLines as ma,runPinRemediation as da,captureLegacySurfaces as ua,decodeLegacyAnchor as Pa,runIdentitySurfaceGate as Da,collectIdentityPinCandidates as Oa,degradedIdentityPinOutcomes as fa,renderIdentityPinReportLines as Ca,runIdentityPinMigration as Na,composePostFailureRepairOffer as La,formatDriftRepairOffer as ga,DriftRepairAvailableError as Ia,checkDeployPathStackAvailability as ya,isDeployPathBlockingStatus as ha,StackUnavailableError as Ma,assertLeaseBeforeStack as xa,LeaseDeniedError as va}from"./orchestration/index.js";import{unlockBucket as Fa,unlockQueue as ba}from"./orchestration/index.js";import{triageBucketPolicy as Ya,isEnforceSslStatement as Va,toResourcePolicyStatements as Ga,restoreBucketPolicy as Ba,synthesiseEnforceSslDocument as Ka,ensureEnforceSsl as Xa,restoreAndReconcileQuarantinedBucket as Ha}from"./orchestration/index.js";import{verifyOrgTrailDelivery as Ja}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as ja,isRootTaskPolicyArn as Wa,ROOT_TASK_POLICY_ARNS as Za,MAX_ROOT_SESSION_SECONDS as qa}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as $a,flattenAccountsToEnvironments as en,extractAllAccountNames as rn,accountsConfigToOUTree as tn,isStringArray as on,isAccountsConfig as an,isOuOnlyAccountBucket as nn,OU_ONLY_ACCOUNT_BUCKETS as sn}from"./orchestration/index.js";import{runOpenNextBuild as cn}from"./orchestration/index.js";import{runOrganisationSetup as ln,ORG_SETUP_PHASES as Tn}from"./orchestration/index.js";import{DOMAIN_DELEGATION_ERROR_TYPES as An,DomainDelegationError as Rn,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as pn,PUBLIC_DNS_QUERY_TIMEOUT_MS as mn,createPublicResolvers as dn,NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as un,NS_PROPAGATION_DEFAULT_INTERVAL_MS as Pn,waitForNsPropagation as Dn,ACM_CAA_ISSUERS as On,runCaaPreflight as fn,deployDelegatedDomain as Cn,CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as Nn,templateOwnsDelegationRecord as Ln,deleteChildNsFromParent as gn,nsDelegationPhysicalName as In,runDelegatedDomainDestroy as yn}from"./orchestration/index.js";import{classifyZoneRecords as Mn,buildSatelliteRecordIndex as xn,createSystemDnsNameProbe as vn,systemDnsNameProbe as Un,normaliseRecordName as Fn,isRoute53NameServer as bn,isDelegatedToRoute53 as kn}from"./orchestration/index.js";import{resolveBuildSecrets as Vn,resolveSecretRefValue as Gn,resolveBuildSecretSessionProvider as Bn,sourcedRefsFromBuildArgs as Kn,resolveBuildArgs as Xn,buildBuildSecretSessionPolicy as Hn,buildDeploySessionPolicy as wn,partitionForRegion as Jn,validateBuildGroup as Qn}from"./orchestration/index.js";import{FrameworkRegistry as Wn}from"./orchestration/index.js";import{openNextBuilder as qn,staticSiteBuilder as zn,dockerBuilder as $n}from"./orchestration/index.js";import{StepRegistry as rs,getDestroyStepId as ts}from"./steps/index.js";import{buildDeployPlan as is,computeDeployPlan as as,computeAssemblyDigest as ns,digestHead as ss,classifyImpact as Es,derivePropertyChanges as cs,isDataLoss as Ss,isStatefulResourceType as ls,renderPlanSummary as Ts,renderPlanLines as _s,toWirePlanChanges as As,signApprovalToken as Rs,verifyApprovalToken as ps,DEFAULT_APPROVAL_TTL_MS as ms,APPROVAL_TOKEN_PATTERN as ds,runApprovalGate as us,approvalRefusalReason as Ps}from"./orchestration/index.js";import{runDestructionGate as Os,buildDestructionTicket as fs,evaluateDestructionConsents as Cs,computeTicketDigest as Ns,legalRemediationVerbs as Ls,executableRemediationVerbs as gs,advertisableRemediationVerbs as Is,renderDestructionTicketLines as ys,renderConsentVerdictLines as hs,loadDeployPlan as Ms,createMemoisedPlanLoader as xs}from"./orchestration/index.js";export{On as ACM_CAA_ISSUERS,j as ALL_PROGRESS_KINDS,Lr as APPLICATION_DEPLOY_ORDER,gr as APPLICATION_DESTROY_ORDER,Cr as APPLICATION_STACKS,Q as APPROVAL_DECISIONS,J as APPROVAL_KINDS,ds as APPROVAL_TOKEN_PATTERN,et as ApplicationError,zt as ApplicationStackService,io as AuthError,ao as AwsError,K as BUILDERS,to as BaseServiceError,Y as CASCADE_ACCOUNT_PHASES,T as CASCADE_ACCOUNT_STATUSES,X as CASCADE_OUTCOME_RESULTS,l as CASCADE_PHASES,zr as CDK_NO_STACKS_MATCH,tr as CONSENT_VERDICTS,Nn as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,Nt as CdkArgumentBuilder,Jt as CdkContextBuilder,eo as CdkError,ht as CdkEventMonitor,Lt as CdkProcessManager,Ct as CdkService,D as ChangeCountsSchema,Gt as CloudFormationError,Ot as CloudFormationEventMonitor,Vt as CloudFormationService,co as ConfigError,ms as DEFAULT_APPROVAL_TTL_MS,xt as DEFAULT_DEPLOY_TIMEOUT_MS,xe as DEFAULT_MAX_PAGES,pn as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,yt as DEPENDENCY_SYNC_TIMEOUT_MS,S as DEPLOYMENT_ERROR_MESSAGE_MAX,E as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,n as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,s as DEPLOYMENT_EVENT_STATUS_REASON_MAX,c as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,a as DEPLOYMENT_EVENT_TYPES,t as DEPLOY_CORE_VERSION_GLOBAL,v as DEPLOY_EVENT_ARN_MAX,O as DEPLOY_EVENT_CONTRACT,f as DEPLOY_EVENT_CONTRACT_MAJOR,C as DEPLOY_EVENT_CONTRACT_MINOR,h as DEPLOY_EVENT_ERROR_MESSAGE_MAX,L as DEPLOY_EVENT_ID_MAX,I as DEPLOY_EVENT_MESSAGE_MAX,g as DEPLOY_EVENT_NAME_MAX,x as DEPLOY_EVENT_OUTPUT_MAX,y as DEPLOY_EVENT_STATUS_REASON_MAX,M as DEPLOY_EVENT_TRAIL_DETAIL_MAX,U as DEPLOY_EVENT_URL_MAX,V as DEPLOY_RESULTS,rr as DESTRUCTION_FINDINGS,G as DETECTION_PHASES,An as DOMAIN_DELEGATION_ERROR_TYPES,Ni as DRIFT_PREFLIGHT_BUDGET_MS,Ci as DRIFT_PREFLIGHT_TRIGGER_STATUSES,nr as DRIFT_VERDICTS,p as DeployEventSchema,uo as DeployModeSchema,d as DeployResourceSchema,no as DeploymentError,i as DeploymentEventSchema,$e as DestructionConsentSchema,Ze as DestructionFindingSchema,er as DestructionOutcomeSchema,qe as DestructionTicketResourceSchema,ze as DestructionTicketSchema,Rn as DomainDelegationError,cr as DriftFindingSchema,Sr as DriftJournalRecordSchema,pi as DriftProbe,Ia as DriftRepairAvailableError,Er as DriftSuspectSchema,sr as DriftVerdictSchema,Kt as EcsError,Bt as EcsService,Xt as EcsServiceResolver,Wi as FORGET_FLIP_SPEC,ji as FORGET_MARKER_KEY,Eo as FileSystemError,nt as FjallStateFileSchema,Wn as FrameworkRegistry,We as IDENTITY_PIN_SLOT_SWAP_GLOSS,ve as IDENTITY_STORE_PAGE_SIZE,$r as INFRASTRUCTURE_FILENAME,He as INFRASTRUCTURE_STEP_NAMES,we as INFRA_STEP_NAME,Pt as LEGACY_DOMAIN_STATE_FILENAME,b as LOG_LEVELS,va as LeaseDeniedError,qa as MAX_ROOT_SESSION_SECONDS,Pn as NS_PROPAGATION_DEFAULT_INTERVAL_MS,un as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,so as NetworkError,Ir as OPENNEXT_DEPLOY_ORDER,yr as OPENNEXT_DESTROY_ORDER,xr as OPENNEXT_PARALLEL_GROUPS,Wr as OPENNEXT_PATTERNS,Nr as ORGANISATION_TYPES,Tn as ORG_SETUP_PHASES,Si as ORG_TRAIL_BUCKET_OUTPUT_KEY,sn as OU_ONLY_ACCOUNT_BUCKETS,hr as PARALLEL_DEPLOY_GROUPS,Mr as PARALLEL_DESTROY_GROUPS,vr as PARALLEL_OPERATION_TYPES,B as PHASE_STATUSES,H as PLAN_ACTIONS,jt as PROGRESS_MESSAGES,mn as PUBLIC_DNS_QUERY_TIMEOUT_MS,u as PlanChangeSchema,P as PlanPropertyChangeSchema,fr as ProgressReporter,Zi as RECREATE_MARKER_KEY,ki as REMEDIATION_JOURNAL_RETENTION_DAYS,_r as REMEDIATION_PHASES,je as REMEDIATION_VERB_GLOSS,w as REPLACEMENT_MODES,Ve as ROOT_ACCESS_FEATURES,Za as ROOT_TASK_POLICY_ARNS,pr as RemediationFlipProofSchema,mr as RemediationJournalRecordSchema,Ar as RemediationPhaseSchema,Rr as RemediationTargetSchema,Qe as RemediationVerbSchema,dr as RemediationVerbWithSurgerySchema,Ge as RootAccessEnablementError,ke as SECURITY_SERVICE_PRINCIPALS,Ae as SERVICE_PRINCIPALS,na as SNAPSHOT_CAPABLE_RESOURCE_TYPES,k as STACK_CLEANUP_PHASES,qr as STACK_FAILED_STATE_PATTERN,Zr as STACK_NOT_FOUND_PATTERN,F as STEP_COMPLETE_STATUSES,Ke as STEP_IDS,Xe as STEP_NAMES,N as SUPPORTED_CONTRACT_MARKERS,Po as ServiceArtefactSchema,Do as ServiceArtefactsSchema,$ as SimpleAwsProvider,Ma as StackUnavailableError,m as StepProgressSchema,rs as StepRegistry,or as TICKET_VERDICT_SOURCES,li as TRAIL_BUCKET_OUTPUT_KEY,Ti as TRAIL_KEY_ARN_OUTPUT_KEY,wt as TemplateHashError,Ht as TemplateHashService,ir as TicketVerdictSourceSchema,oo as ValidationError,tn as accountsConfigToOUTree,Le as activateCostAllocationTags,pe as activateTrustedAccess,Ta as advertisableDriftVerbs,Is as advertisableRemediationVerbs,Gi as applyRetainFlip,Ps as approvalRefusalReason,Ii as archiveCompletedRemediationJournal,mo as artefactOutputKey,xa as assertLeaseBeforeStack,qi as assessForgetResumability,ja as assumeRootForTask,qo as buildAccountRegionPairs,Ce as buildAccountToOUMap,Hn as buildBuildSecretSessionPolicy,is as buildDeployPlan,wn as buildDeploySessionPolicy,fs as buildDestructionTicket,_a as buildDriftRepairTicket,Go as buildParamsContext,Zo as buildRegionList,xn as buildSatelliteRecordIndex,Zt as buildStepContextBuildConfig,ie as buildTargetSetUnreadyAdvisory,oe as buildTargetUnreadyAdvisory,ua as captureLegacySurfaces,Yi as captureRemediationForensics,zo as cascadeHomeRegion,$o as cascadeOperationKey,ya as checkDeployPathStackAvailability,ge as checkIdentityCentreStatus,se as checkRegionEnabled,re as checkTargetReadiness,_ as clampDeploymentEventStrings,Ai as classifyDriftFailure,Es as classifyImpact,Mn as classifyZoneRecords,It as clearDependencyIntegrityCache,mi as clearDriftSuspects,Oa as collectIdentityPinCandidates,zi as completeForgetAfterConverge,$i as completeForgetAfterDeploy,Bi as composeFlipCapabilities,La as composePostFailureRepairOffer,ye as composeSdkAbortSignal,ns as computeAssemblyDigest,as as computeDeployPlan,yi as computeRemediationOpId,Ho as computeSecretsDrift,Ki as computeTemplateDigest,Ns as computeTicketDigest,qt as convertCloudFormationOutputsToRecord,De as createAccount,W as createDeployEmitter,ct as createEmptyState,xs as createMemoisedPlanLoader,dn as createPublicResolvers,go as createSequencedCallbacks,vn as createSystemDnsNameProbe,si as decideNextTransition,Pa as decodeLegacyAnchor,ci as decommissionMemberTrailStorage,di as defaultDriftJournalDir,Vi as defaultRemediationForensicsDir,hi as defaultRemediationJournalDir,fa as degradedIdentityPinOutcomes,gn as deleteChildNsFromParent,dt as deleteDomainState,St as deleteStateFile,bo as deploy,Cn as deployDelegatedDomain,cs as derivePropertyChanges,Ea as deriveRemovalTemplate,it as deriveResourcesFromManifestStacks,Xi as deriveRetainFlipTemplate,wo as deriveStaleParameters,le as describeOrganisation,te as describeTargetReadinessReason,Yo as destroy,Di as detectStackDrift,ss as digestHead,$n as dockerBuilder,Ue as drainPages,Qt as emitProgress,Ye as enableCentralisedRootAccess,me as enableIpamDelegatedAdmin,Te as enablePolicyTypes,Re as enableRamSharing,_e as enableServiceAccess,gt as ensureDependencyIntegrity,Xa as ensureEnforceSsl,Se as ensureOrganisationExists,Oe as ensureOrganisationalUnitsExist,Cs as evaluateDestructionConsents,gs as executableRemediationVerbs,rn as extractAllAccountNames,Jo as extractConsumedSsmParameters,he as extractErrorName,xo as failure,Ri as fetchLastOperationEvents,yo as fileExists,To as filterDangerousEnvVars,Pe as findAccount,Ne as findDevelopmentOuId,Hi as findMarkedResourcesByOpId,Mi as findRemediationJournalByOpId,ca as findRemovalDeletionFailures,Sa as findResourcesPresent,en as flattenAccountsToEnvironments,fi as formatDriftPreFlightBlock,ga as formatDriftRepairOffer,Ut as formatInfrastructureError,Ra as formatPinOutcomeDetail,ea as formatRecreateInFlightCures,Yr as getApplicationDeployOrder,Vr as getApplicationDestroyOrder,Gr as getApplicationStackName,Jr as getApplicationStepId,wr as getApplicationStepName,ts as getDestroyStepId,Br as getOrganisationStackName,br as getParallelDeployGroups,kr as getParallelDestroyGroups,bt as getSourceContext,Tt as getStateFilePath,Ft as getStructuralHint,kt as hasCdkDifferences,fo as hasDockerfile,ut as hashDomainDirectory,Me as isAborted,an as isAccountsConfig,Ur as isApplicationOperation,Kr as isApplicationStack,vt as isCdkError,Ss as isDataLoss,kn as isDelegatedToRoute53,ha as isDeployPathBlockingStatus,Va as isEnforceSslStatement,Uo as isFailure,Fe as isOULeaf,jr as isOpenNextPattern,Fr as isOrganisationOperation,nn as isOuOnlyAccountBucket,Xr as isQuarantineDetail,Dr as isRemediationPlaceholderPhysicalId,Hr as isRetainedBucketsDetail,Wa as isRootTaskPolicyArn,bn as isRoute53NameServer,ls as isStatefulResourceType,on as isStringArray,vo as isSuccess,Ls as legalRemediationVerbs,ue as listAccounts,xi as listActiveRemediationOps,vi as listActiveRemediationOpsForContext,Ms as loadDeployPlan,_o as maskSensitiveOutput,ai as mergeReconciledProviderAccounts,Fn as normaliseRecordName,In as nsDelegationPhysicalName,qn as openNextBuilder,$a as parseAccountsConfiguration,Wt as parseBuildPhase,q as parseDeployContractVersion,Z as parseDeployEvent,Yt as parseDiffOutput,Ao as parseShellArgs,jo as partitionAccounts,Jn as partitionForRegion,ra as partitionPreFlightByRemediation,pa as pinProbeCoverage,fe as placeAccountsInOUs,ae as probeAccountStackExists,Xo as probeSecretsDrift,ti as projectAccountRows,ri as projectScalarSummary,wi as proveFlipMetadataOnly,la as proveRemovalTargetsOnly,Rt as readDomainState,ui as readDriftSuspects,Ui as readRemediationJournal,Ji as readRetainFlipState,st as readStateFile,ii as reconcileProviderAccounts,Ei as reconcileTrailMigration,mt as recordDomainDeployState,Pi as recordDriftSuspects,Ee as regionDisabledMessage,_t as regionSuffix,be as registerSecurityDelegates,ur as remediationPhaseRank,Pr as remediationPlaceholderPhysicalId,hs as renderConsentVerdictLines,ys as renderDestructionTicketLines,Ca as renderIdentityPinReportLines,ma as renderPinReportLines,_s as renderPlanLines,Ts as renderPlanSummary,Xn as resolveBuildArgs,Bn as resolveBuildSecretSessionProvider,Vn as resolveBuildSecrets,Gn as resolveSecretRefValue,Ko as restart,Ha as restoreAndReconcileQuarantinedBucket,Ba as restoreBucketPolicy,us as runApprovalGate,fn as runCaaPreflight,yn as runDelegatedDomainDestroy,Os as runDestructionGate,Oi as runDriftPreFlight,Aa as runDriftRepairGate,ta as runForgetSurgery,Na as runIdentityPinMigration,Da as runIdentitySurfaceGate,cn as runOpenNextBuild,ln as runOrganisationSetup,da as runPinRemediation,sa as runRecreatePreFlight,ia as runRecreateSurgery,Li as runRoute53RecordPreflight,Rs as signApprovalToken,Ro as sleep,No as sleepAbortable,Ie as snapshotIdentityCentre,aa as snapshotPolicyForType,Kn as sourcedRefsFromBuildArgs,Mt as startStackMonitoring,zn as staticSiteBuilder,tt as stubCallerIdentity,Mo as success,Fi as sweepExpiredRemediationJournals,oa as synthTemplateDeclaresResource,Ka as synthesiseEnforceSslDocument,Un as systemDnsNameProbe,Ln as templateOwnsDelegationRecord,Qr as toPascalCase,Ga as toResourcePolicyStatements,So as toServiceError,As as toWirePlanChanges,Ya as triageBucketPolicy,A as truncateUtf16Safe,Fa as unlockBucket,ba as unlockQueue,de as updateBackupGlobalSettings,lt as updateTemplateHash,Qn as validateBuildGroup,lr as verbsForDriftVerdict,ps as verifyApprovalToken,Ja as verifyOrgTrailDelivery,Qi as verifyRetainFlipDiff,Dn as waitForNsPropagation,rt as wrapApplicationError,pt as writeDomainState,bi as writeRemediationJournal,Et as writeStateFile};
|
|
1
|
+
import{DEPLOY_CORE_VERSION_GLOBAL as t}from"./version.js";import{DeploymentEventSchema as i,DEPLOYMENT_EVENT_TYPES as a,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as n,DEPLOYMENT_EVENT_STATUS_REASON_MAX as s,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as E,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as c,DEPLOYMENT_ERROR_MESSAGE_MAX as S,CASCADE_PHASES as l,CASCADE_ACCOUNT_STATUSES as _,clampDeploymentEventStrings as A,truncateUtf16Safe as p}from"./types/index.js";import{DeployEventSchema as T,StepProgressSchema as m,DeployResourceSchema as d,PlanChangeSchema as u,PlanPropertyChangeSchema as D,ChangeCountsSchema as P,DEPLOY_EVENT_CONTRACT as O,DEPLOY_EVENT_CONTRACT_MAJOR as f,DEPLOY_EVENT_CONTRACT_MINOR as C,SUPPORTED_CONTRACT_MARKERS as N,DEPLOY_EVENT_ID_MAX as I,DEPLOY_EVENT_NAME_MAX as L,DEPLOY_EVENT_MESSAGE_MAX as g,DEPLOY_EVENT_STATUS_REASON_MAX as y,DEPLOY_EVENT_ERROR_MESSAGE_MAX as F,DEPLOY_EVENT_TRAIL_DETAIL_MAX as h,DEPLOY_EVENT_OUTPUT_MAX as x,DEPLOY_EVENT_ARN_MAX as M,DEPLOY_EVENT_URL_MAX as U,STEP_COMPLETE_STATUSES as v,LOG_LEVELS as b,STACK_CLEANUP_PHASES as k,CASCADE_ACCOUNT_PHASES as Y,DEPLOY_RESULTS as V,DETECTION_PHASES as G,PHASE_STATUSES as B,BUILDERS as K,CASCADE_OUTCOME_RESULTS as X,PLAN_ACTIONS as H,REPLACEMENT_MODES as w,APPROVAL_KINDS as J,APPROVAL_DECISIONS as Q,ALL_PROGRESS_KINDS as j,createDeployEmitter as W,parseDeployEvent as Z,parseDeployContractVersion as q}from"./types/index.js";import{SimpleAwsProvider as $}from"./aws/index.js";import{checkTargetReadiness as re,describeTargetReadinessReason as te,buildTargetUnreadyAdvisory as oe,buildTargetSetUnreadyAdvisory as ie,probeAccountStackExists as ae}from"./aws/index.js";import{checkRegionEnabled as se,regionDisabledMessage as Ee}from"./aws/index.js";import{ensureOrganisationExists as Se,describeOrganisation as le,enablePolicyTypes as _e,enableServiceAccess as Ae,SERVICE_PRINCIPALS as pe,enableRamSharing as Re,activateTrustedAccess as Te,enableIpamDelegatedAdmin as me,updateBackupGlobalSettings as de,listAccounts as ue,findAccount as De,createAccount as Pe,ensureOrganisationalUnitsExist as Oe,placeAccountsInOUs as fe,buildAccountToOUMap as Ce,findDevelopmentOuId as Ne,activateCostAllocationTags as Ie,checkIdentityCentreStatus as Le,snapshotIdentityCentre as ge,composeSdkAbortSignal as ye,extractErrorName as Fe,isAborted as he,DEFAULT_MAX_PAGES as xe,IDENTITY_STORE_PAGE_SIZE as Me,drainPages as Ue,isOULeaf as ve,registerSecurityDelegates as be,SECURITY_SERVICE_PRINCIPALS as ke,enableCentralisedRootAccess as Ye,ROOT_ACCESS_FEATURES as Ve,RootAccessEnablementError as Ge}from"./aws/index.js";import{STEP_IDS as Ke,STEP_NAMES as Xe,INFRASTRUCTURE_STEP_NAMES as He,INFRA_STEP_NAME as we}from"./types/index.js";import{RemediationVerbSchema as Qe,REMEDIATION_VERB_GLOSS as je,IDENTITY_PIN_SLOT_SWAP_GLOSS as We,DestructionFindingSchema as Ze,DestructionTicketResourceSchema as qe,DestructionTicketSchema as ze,DestructionConsentSchema as $e,DestructionOutcomeSchema as er,DESTRUCTION_FINDINGS as rr,CONSENT_VERDICTS as tr,TICKET_VERDICT_SOURCES as or,TicketVerdictSourceSchema as ir}from"./types/index.js";import{DRIFT_VERDICTS as nr,DriftVerdictSchema as sr,DriftSuspectSchema as Er,DriftFindingSchema as cr,DriftJournalRecordSchema as Sr,verbsForDriftVerdict as lr}from"./types/index.js";import{REMEDIATION_PHASES as Ar,RemediationPhaseSchema as pr,RemediationTargetSchema as Rr,RemediationFlipProofSchema as Tr,RemediationJournalRecordSchema as mr,RemediationVerbWithSurgerySchema as dr,remediationPhaseRank as ur,remediationPlaceholderPhysicalId as Dr,isRemediationPlaceholderPhysicalId as Pr}from"./types/index.js";import{ProgressReporter as fr,APPLICATION_STACKS as Cr,ORGANISATION_TYPES as Nr,APPLICATION_DEPLOY_ORDER as Ir,APPLICATION_DESTROY_ORDER as Lr,OPENNEXT_DEPLOY_ORDER as gr,OPENNEXT_DESTROY_ORDER as yr,PARALLEL_DEPLOY_GROUPS as Fr,PARALLEL_DESTROY_GROUPS as hr,OPENNEXT_PARALLEL_GROUPS as xr,PARALLEL_OPERATION_TYPES as Mr,isApplicationOperation as Ur,isOrganisationOperation as vr,getParallelDeployGroups as br,getParallelDestroyGroups as kr,getApplicationDeployOrder as Yr,getApplicationDestroyOrder as Vr,getApplicationStackName as Gr,getOrganisationStackName as Br,isApplicationStack as Kr,isQuarantineDetail as Xr,isRetainedBucketsDetail as Hr,getApplicationStepName as wr,getApplicationStepId as Jr,toPascalCase as Qr,isOpenNextPattern as jr,OPENNEXT_PATTERNS as Wr,STACK_NOT_FOUND_PATTERN as Zr,STACK_FAILED_STATE_PATTERN as qr,CDK_NO_STACKS_MATCH as zr,INFRASTRUCTURE_FILENAME as $r,ApplicationError as et,wrapApplicationError as rt,stubCallerIdentity as tt}from"./types/index.js";import{deriveResourcesFromManifestStacks as it}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as nt,readStateFile as st,writeStateFile as Et,createEmptyState as ct,deleteStateFile as St,updateTemplateHash as lt,getStateFilePath as _t,regionSuffix as At}from"./types/config/FjallState.js";import{readDomainState as Rt,writeDomainState as Tt,recordDomainDeployState as mt,deleteDomainState as dt,hashDomainDirectory as ut,LEGACY_DOMAIN_STATE_FILENAME as Dt}from"./types/config/DomainState.js";import{CloudFormationEventMonitor as Ot}from"./aws/index.js";import{CdkService as Ct,CdkArgumentBuilder as Nt,CdkProcessManager as It,ensureDependencyIntegrity as Lt,clearDependencyIntegrityCache as gt,DEPENDENCY_SYNC_TIMEOUT_MS as yt,CdkEventMonitor as Ft,startStackMonitoring as ht,DEFAULT_DEPLOY_TIMEOUT_MS as xt,isCdkError as Mt,formatInfrastructureError as Ut,getStructuralHint as vt,getSourceContext as bt,hasCdkDifferences as kt,parseDiffOutput as Yt,CloudFormationService as Vt,CloudFormationError as Gt,EcsService as Bt,EcsError as Kt,EcsServiceResolver as Xt,TemplateHashService as Ht,TemplateHashError as wt,CdkContextBuilder as Jt,emitProgress as Qt,PROGRESS_MESSAGES as jt,parseBuildPhase as Wt,buildStepContextBuildConfig as Zt,convertCloudFormationOutputsToRecord as qt,ApplicationStackService as zt}from"./services/index.js";import{CdkError as eo}from"./types/errors/index.js";import{BaseServiceError as to,ValidationError as oo,AuthError as io,AwsError as ao,DeploymentError as no,NetworkError as so,FileSystemError as Eo,ConfigError as co,toServiceError as So}from"./types/errors/index.js";import{filterDangerousEnvVars as _o,maskSensitiveOutput as Ao,parseShellArgs as po,sleep as Ro}from"@fjall/util";import{artefactOutputKey as mo,DeployModeSchema as uo,ServiceArtefactSchema as Do,ServiceArtefactsSchema as Po}from"@fjall/util";import{hasDockerfile as fo}from"./util/dockerfileDetection.js";import{sleepAbortable as No}from"./util/sleepAbortable.js";import{createSequencedCallbacks as Lo}from"./util/sequencedCallbacks.js";import{fileExists as yo}from"@fjall/util/fsHelpers";import{success as ho,failure as xo,isSuccess as Mo,isFailure as Uo}from"@fjall/generator";import{deploy as bo}from"./orchestration/index.js";import{destroy as Yo}from"./orchestration/index.js";import{buildParamsContext as Go}from"./orchestration/contextHelpers.js";import{restart as Ko,probeSecretsDrift as Xo,probeServiceDeploymentStatus as Ho,computeSecretsDrift as wo,deriveStaleParameters as Jo,extractConsumedSsmParameters as Qo}from"./orchestration/index.js";import{partitionAccounts as Wo}from"./orchestration/index.js";import{buildRegionList as qo,buildAccountRegionPairs as zo,cascadeHomeRegion as $o,cascadeOperationKey as ei}from"./orchestration/index.js";import{projectScalarSummary as ti,projectAccountRows as oi}from"./orchestration/index.js";import{reconcileProviderAccounts as ai,mergeReconciledProviderAccounts as ni}from"./orchestration/index.js";import{decideNextTransition as Ei,reconcileTrailMigration as ci,decommissionMemberTrailStorage as Si,ORG_TRAIL_BUCKET_OUTPUT_KEY as li,TRAIL_BUCKET_OUTPUT_KEY as _i,TRAIL_KEY_ARN_OUTPUT_KEY as Ai}from"./orchestration/index.js";import{classifyDriftFailure as Ri,fetchLastOperationEvents as Ti,DriftProbe as mi,clearDriftSuspects as di,defaultDriftJournalDir as ui,readDriftSuspects as Di,recordDriftSuspects as Pi,detectStackDrift as Oi,runDriftPreFlight as fi,formatDriftPreFlightBlock as Ci,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Ni,DRIFT_PREFLIGHT_BUDGET_MS as Ii,runRoute53RecordPreflight as Li}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as yi,computeRemediationOpId as Fi,defaultRemediationJournalDir as hi,findRemediationJournalByOpId as xi,listActiveRemediationOps as Mi,listActiveRemediationOpsForContext as Ui,readRemediationJournal as vi,sweepExpiredRemediationJournals as bi,writeRemediationJournal as ki,REMEDIATION_JOURNAL_RETENTION_DAYS as Yi,captureRemediationForensics as Vi,defaultRemediationForensicsDir as Gi,applyRetainFlip as Bi,composeFlipCapabilities as Ki,computeTemplateDigest as Xi,deriveRetainFlipTemplate as Hi,findMarkedResourcesByOpId as wi,proveFlipMetadataOnly as Ji,readRetainFlipState as Qi,verifyRetainFlipDiff as ji,FORGET_MARKER_KEY as Wi,FORGET_FLIP_SPEC as Zi,RECREATE_MARKER_KEY as qi,assessForgetResumability as zi,completeForgetAfterConverge as $i,completeForgetAfterDeploy as ea,formatRecreateInFlightCures as ra,partitionPreFlightByRemediation as ta,runForgetSurgery as oa,synthTemplateDeclaresResource as ia,runRecreateSurgery as aa,snapshotPolicyForType as na,SNAPSHOT_CAPABLE_RESOURCE_TYPES as sa,runRecreatePreFlight as Ea,deriveRemovalTemplate as ca,findRemovalDeletionFailures as Sa,findResourcesPresent as la,proveRemovalTargetsOnly as _a,advertisableDriftVerbs as Aa,buildDriftRepairTicket as pa,runDriftRepairGate as Ra,formatPinOutcomeDetail as Ta,pinProbeCoverage as ma,renderPinReportLines as da,runPinRemediation as ua,captureLegacySurfaces as Da,decodeLegacyAnchor as Pa,runIdentitySurfaceGate as Oa,collectIdentityPinCandidates as fa,degradedIdentityPinOutcomes as Ca,renderIdentityPinReportLines as Na,runIdentityPinMigration as Ia,composePostFailureRepairOffer as La,formatDriftRepairOffer as ga,DriftRepairAvailableError as ya,checkDeployPathStackAvailability as Fa,isDeployPathBlockingStatus as ha,StackUnavailableError as xa,assertLeaseBeforeStack as Ma,LeaseDeniedError as Ua}from"./orchestration/index.js";import{unlockBucket as ba,unlockQueue as ka}from"./orchestration/index.js";import{triageBucketPolicy as Va,isEnforceSslStatement as Ga,toResourcePolicyStatements as Ba,restoreBucketPolicy as Ka,synthesiseEnforceSslDocument as Xa,ensureEnforceSsl as Ha,restoreAndReconcileQuarantinedBucket as wa}from"./orchestration/index.js";import{verifyOrgTrailDelivery as Qa}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as Wa,isRootTaskPolicyArn as Za,ROOT_TASK_POLICY_ARNS as qa,MAX_ROOT_SESSION_SECONDS as za}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as en,flattenAccountsToEnvironments as rn,extractAllAccountNames as tn,accountsConfigToOUTree as on,isStringArray as an,isAccountsConfig as nn,isOuOnlyAccountBucket as sn,OU_ONLY_ACCOUNT_BUCKETS as En}from"./orchestration/index.js";import{runOpenNextBuild as Sn}from"./orchestration/index.js";import{runOrganisationSetup as _n,ORG_SETUP_PHASES as An}from"./orchestration/index.js";import{DOMAIN_DELEGATION_ERROR_TYPES as Rn,DomainDelegationError as Tn,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as mn,PUBLIC_DNS_QUERY_TIMEOUT_MS as dn,createPublicResolvers as un,NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as Dn,NS_PROPAGATION_DEFAULT_INTERVAL_MS as Pn,waitForNsPropagation as On,ACM_CAA_ISSUERS as fn,runCaaPreflight as Cn,deployDelegatedDomain as Nn,CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as In,templateOwnsDelegationRecord as Ln,deleteChildNsFromParent as gn,nsDelegationPhysicalName as yn,runDelegatedDomainDestroy as Fn}from"./orchestration/index.js";import{classifyZoneRecords as xn,buildSatelliteRecordIndex as Mn,createSystemDnsNameProbe as Un,systemDnsNameProbe as vn,normaliseRecordName as bn,isRoute53NameServer as kn,isDelegatedToRoute53 as Yn}from"./orchestration/index.js";import{resolveBuildSecrets as Gn,resolveSecretRefValue as Bn,resolveBuildSecretSessionProvider as Kn,sourcedRefsFromBuildArgs as Xn,resolveBuildArgs as Hn,buildBuildSecretSessionPolicy as wn,buildDeploySessionPolicy as Jn,partitionForRegion as Qn,validateBuildGroup as jn}from"./orchestration/index.js";import{FrameworkRegistry as Zn}from"./orchestration/index.js";import{openNextBuilder as zn,staticSiteBuilder as $n,dockerBuilder as es}from"./orchestration/index.js";import{StepRegistry as ts,getDestroyStepId as os}from"./steps/index.js";import{buildDeployPlan as as,computeDeployPlan as ns,computeAssemblyDigest as ss,digestHead as Es,classifyImpact as cs,derivePropertyChanges as Ss,isDataLoss as ls,isStatefulResourceType as _s,renderPlanSummary as As,renderPlanLines as ps,toWirePlanChanges as Rs,signApprovalToken as Ts,verifyApprovalToken as ms,DEFAULT_APPROVAL_TTL_MS as ds,APPROVAL_TOKEN_PATTERN as us,runApprovalGate as Ds,approvalRefusalReason as Ps}from"./orchestration/index.js";import{runDestructionGate as fs,buildDestructionTicket as Cs,evaluateDestructionConsents as Ns,computeTicketDigest as Is,legalRemediationVerbs as Ls,executableRemediationVerbs as gs,advertisableRemediationVerbs as ys,renderDestructionTicketLines as Fs,renderConsentVerdictLines as hs,loadDeployPlan as xs,createMemoisedPlanLoader as Ms}from"./orchestration/index.js";import{DEPLOYMENT_FAILURE_CLASSIFIER_VERSION as vs,classifyDeployFailure as bs,classifyFromEcsCompletion as ks,classifyFromFailureAnalysis as Ys,classifyUnclassified as Vs}from"./orchestration/failure/classifyFailure.js";import{attachDeploymentFailure as Bs,getDeploymentFailure as Ks}from"./orchestration/failure/deploymentFailureAttachment.js";export{fn as ACM_CAA_ISSUERS,j as ALL_PROGRESS_KINDS,Ir as APPLICATION_DEPLOY_ORDER,Lr as APPLICATION_DESTROY_ORDER,Cr as APPLICATION_STACKS,Q as APPROVAL_DECISIONS,J as APPROVAL_KINDS,us as APPROVAL_TOKEN_PATTERN,et as ApplicationError,zt as ApplicationStackService,io as AuthError,ao as AwsError,K as BUILDERS,to as BaseServiceError,Y as CASCADE_ACCOUNT_PHASES,_ as CASCADE_ACCOUNT_STATUSES,X as CASCADE_OUTCOME_RESULTS,l as CASCADE_PHASES,zr as CDK_NO_STACKS_MATCH,tr as CONSENT_VERDICTS,In as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,Nt as CdkArgumentBuilder,Jt as CdkContextBuilder,eo as CdkError,Ft as CdkEventMonitor,It as CdkProcessManager,Ct as CdkService,P as ChangeCountsSchema,Gt as CloudFormationError,Ot as CloudFormationEventMonitor,Vt as CloudFormationService,co as ConfigError,ds as DEFAULT_APPROVAL_TTL_MS,xt as DEFAULT_DEPLOY_TIMEOUT_MS,xe as DEFAULT_MAX_PAGES,mn as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,yt as DEPENDENCY_SYNC_TIMEOUT_MS,S as DEPLOYMENT_ERROR_MESSAGE_MAX,E as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,n as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,s as DEPLOYMENT_EVENT_STATUS_REASON_MAX,c as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,a as DEPLOYMENT_EVENT_TYPES,vs as DEPLOYMENT_FAILURE_CLASSIFIER_VERSION,t as DEPLOY_CORE_VERSION_GLOBAL,M as DEPLOY_EVENT_ARN_MAX,O as DEPLOY_EVENT_CONTRACT,f as DEPLOY_EVENT_CONTRACT_MAJOR,C as DEPLOY_EVENT_CONTRACT_MINOR,F as DEPLOY_EVENT_ERROR_MESSAGE_MAX,I as DEPLOY_EVENT_ID_MAX,g as DEPLOY_EVENT_MESSAGE_MAX,L as DEPLOY_EVENT_NAME_MAX,x as DEPLOY_EVENT_OUTPUT_MAX,y as DEPLOY_EVENT_STATUS_REASON_MAX,h as DEPLOY_EVENT_TRAIL_DETAIL_MAX,U as DEPLOY_EVENT_URL_MAX,V as DEPLOY_RESULTS,rr as DESTRUCTION_FINDINGS,G as DETECTION_PHASES,Rn as DOMAIN_DELEGATION_ERROR_TYPES,Ii as DRIFT_PREFLIGHT_BUDGET_MS,Ni as DRIFT_PREFLIGHT_TRIGGER_STATUSES,nr as DRIFT_VERDICTS,T as DeployEventSchema,uo as DeployModeSchema,d as DeployResourceSchema,no as DeploymentError,i as DeploymentEventSchema,$e as DestructionConsentSchema,Ze as DestructionFindingSchema,er as DestructionOutcomeSchema,qe as DestructionTicketResourceSchema,ze as DestructionTicketSchema,Tn as DomainDelegationError,cr as DriftFindingSchema,Sr as DriftJournalRecordSchema,mi as DriftProbe,ya as DriftRepairAvailableError,Er as DriftSuspectSchema,sr as DriftVerdictSchema,Kt as EcsError,Bt as EcsService,Xt as EcsServiceResolver,Zi as FORGET_FLIP_SPEC,Wi as FORGET_MARKER_KEY,Eo as FileSystemError,nt as FjallStateFileSchema,Zn as FrameworkRegistry,We as IDENTITY_PIN_SLOT_SWAP_GLOSS,Me as IDENTITY_STORE_PAGE_SIZE,$r as INFRASTRUCTURE_FILENAME,He as INFRASTRUCTURE_STEP_NAMES,we as INFRA_STEP_NAME,Dt as LEGACY_DOMAIN_STATE_FILENAME,b as LOG_LEVELS,Ua as LeaseDeniedError,za as MAX_ROOT_SESSION_SECONDS,Pn as NS_PROPAGATION_DEFAULT_INTERVAL_MS,Dn as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,so as NetworkError,gr as OPENNEXT_DEPLOY_ORDER,yr as OPENNEXT_DESTROY_ORDER,xr as OPENNEXT_PARALLEL_GROUPS,Wr as OPENNEXT_PATTERNS,Nr as ORGANISATION_TYPES,An as ORG_SETUP_PHASES,li as ORG_TRAIL_BUCKET_OUTPUT_KEY,En as OU_ONLY_ACCOUNT_BUCKETS,Fr as PARALLEL_DEPLOY_GROUPS,hr as PARALLEL_DESTROY_GROUPS,Mr as PARALLEL_OPERATION_TYPES,B as PHASE_STATUSES,H as PLAN_ACTIONS,jt as PROGRESS_MESSAGES,dn as PUBLIC_DNS_QUERY_TIMEOUT_MS,u as PlanChangeSchema,D as PlanPropertyChangeSchema,fr as ProgressReporter,qi as RECREATE_MARKER_KEY,Yi as REMEDIATION_JOURNAL_RETENTION_DAYS,Ar as REMEDIATION_PHASES,je as REMEDIATION_VERB_GLOSS,w as REPLACEMENT_MODES,Ve as ROOT_ACCESS_FEATURES,qa as ROOT_TASK_POLICY_ARNS,Tr as RemediationFlipProofSchema,mr as RemediationJournalRecordSchema,pr as RemediationPhaseSchema,Rr as RemediationTargetSchema,Qe as RemediationVerbSchema,dr as RemediationVerbWithSurgerySchema,Ge as RootAccessEnablementError,ke as SECURITY_SERVICE_PRINCIPALS,pe as SERVICE_PRINCIPALS,sa as SNAPSHOT_CAPABLE_RESOURCE_TYPES,k as STACK_CLEANUP_PHASES,qr as STACK_FAILED_STATE_PATTERN,Zr as STACK_NOT_FOUND_PATTERN,v as STEP_COMPLETE_STATUSES,Ke as STEP_IDS,Xe as STEP_NAMES,N as SUPPORTED_CONTRACT_MARKERS,Do as ServiceArtefactSchema,Po as ServiceArtefactsSchema,$ as SimpleAwsProvider,xa as StackUnavailableError,m as StepProgressSchema,ts as StepRegistry,or as TICKET_VERDICT_SOURCES,_i as TRAIL_BUCKET_OUTPUT_KEY,Ai as TRAIL_KEY_ARN_OUTPUT_KEY,wt as TemplateHashError,Ht as TemplateHashService,ir as TicketVerdictSourceSchema,oo as ValidationError,on as accountsConfigToOUTree,Ie as activateCostAllocationTags,Te as activateTrustedAccess,Aa as advertisableDriftVerbs,ys as advertisableRemediationVerbs,Bi as applyRetainFlip,Ps as approvalRefusalReason,yi as archiveCompletedRemediationJournal,mo as artefactOutputKey,Ma as assertLeaseBeforeStack,zi as assessForgetResumability,Wa as assumeRootForTask,Bs as attachDeploymentFailure,zo as buildAccountRegionPairs,Ce as buildAccountToOUMap,wn as buildBuildSecretSessionPolicy,as as buildDeployPlan,Jn as buildDeploySessionPolicy,Cs as buildDestructionTicket,pa as buildDriftRepairTicket,Go as buildParamsContext,qo as buildRegionList,Mn as buildSatelliteRecordIndex,Zt as buildStepContextBuildConfig,ie as buildTargetSetUnreadyAdvisory,oe as buildTargetUnreadyAdvisory,Da as captureLegacySurfaces,Vi as captureRemediationForensics,$o as cascadeHomeRegion,ei as cascadeOperationKey,Fa as checkDeployPathStackAvailability,Le as checkIdentityCentreStatus,se as checkRegionEnabled,re as checkTargetReadiness,A as clampDeploymentEventStrings,bs as classifyDeployFailure,Ri as classifyDriftFailure,ks as classifyFromEcsCompletion,Ys as classifyFromFailureAnalysis,cs as classifyImpact,Vs as classifyUnclassified,xn as classifyZoneRecords,gt as clearDependencyIntegrityCache,di as clearDriftSuspects,fa as collectIdentityPinCandidates,$i as completeForgetAfterConverge,ea as completeForgetAfterDeploy,Ki as composeFlipCapabilities,La as composePostFailureRepairOffer,ye as composeSdkAbortSignal,ss as computeAssemblyDigest,ns as computeDeployPlan,Fi as computeRemediationOpId,wo as computeSecretsDrift,Xi as computeTemplateDigest,Is as computeTicketDigest,qt as convertCloudFormationOutputsToRecord,Pe as createAccount,W as createDeployEmitter,ct as createEmptyState,Ms as createMemoisedPlanLoader,un as createPublicResolvers,Lo as createSequencedCallbacks,Un as createSystemDnsNameProbe,Ei as decideNextTransition,Pa as decodeLegacyAnchor,Si as decommissionMemberTrailStorage,ui as defaultDriftJournalDir,Gi as defaultRemediationForensicsDir,hi as defaultRemediationJournalDir,Ca as degradedIdentityPinOutcomes,gn as deleteChildNsFromParent,dt as deleteDomainState,St as deleteStateFile,bo as deploy,Nn as deployDelegatedDomain,Ss as derivePropertyChanges,ca as deriveRemovalTemplate,it as deriveResourcesFromManifestStacks,Hi as deriveRetainFlipTemplate,Jo as deriveStaleParameters,le as describeOrganisation,te as describeTargetReadinessReason,Yo as destroy,Oi as detectStackDrift,Es as digestHead,es as dockerBuilder,Ue as drainPages,Qt as emitProgress,Ye as enableCentralisedRootAccess,me as enableIpamDelegatedAdmin,_e as enablePolicyTypes,Re as enableRamSharing,Ae as enableServiceAccess,Lt as ensureDependencyIntegrity,Ha as ensureEnforceSsl,Se as ensureOrganisationExists,Oe as ensureOrganisationalUnitsExist,Ns as evaluateDestructionConsents,gs as executableRemediationVerbs,tn as extractAllAccountNames,Qo as extractConsumedSsmParameters,Fe as extractErrorName,xo as failure,Ti as fetchLastOperationEvents,yo as fileExists,_o as filterDangerousEnvVars,De as findAccount,Ne as findDevelopmentOuId,wi as findMarkedResourcesByOpId,xi as findRemediationJournalByOpId,Sa as findRemovalDeletionFailures,la as findResourcesPresent,rn as flattenAccountsToEnvironments,Ci as formatDriftPreFlightBlock,ga as formatDriftRepairOffer,Ut as formatInfrastructureError,Ta as formatPinOutcomeDetail,ra as formatRecreateInFlightCures,Yr as getApplicationDeployOrder,Vr as getApplicationDestroyOrder,Gr as getApplicationStackName,Jr as getApplicationStepId,wr as getApplicationStepName,Ks as getDeploymentFailure,os as getDestroyStepId,Br as getOrganisationStackName,br as getParallelDeployGroups,kr as getParallelDestroyGroups,bt as getSourceContext,_t as getStateFilePath,vt as getStructuralHint,kt as hasCdkDifferences,fo as hasDockerfile,ut as hashDomainDirectory,he as isAborted,nn as isAccountsConfig,Ur as isApplicationOperation,Kr as isApplicationStack,Mt as isCdkError,ls as isDataLoss,Yn as isDelegatedToRoute53,ha as isDeployPathBlockingStatus,Ga as isEnforceSslStatement,Uo as isFailure,ve as isOULeaf,jr as isOpenNextPattern,vr as isOrganisationOperation,sn as isOuOnlyAccountBucket,Xr as isQuarantineDetail,Pr as isRemediationPlaceholderPhysicalId,Hr as isRetainedBucketsDetail,Za as isRootTaskPolicyArn,kn as isRoute53NameServer,_s as isStatefulResourceType,an as isStringArray,Mo as isSuccess,Ls as legalRemediationVerbs,ue as listAccounts,Mi as listActiveRemediationOps,Ui as listActiveRemediationOpsForContext,xs as loadDeployPlan,Ao as maskSensitiveOutput,ni as mergeReconciledProviderAccounts,bn as normaliseRecordName,yn as nsDelegationPhysicalName,zn as openNextBuilder,en as parseAccountsConfiguration,Wt as parseBuildPhase,q as parseDeployContractVersion,Z as parseDeployEvent,Yt as parseDiffOutput,po as parseShellArgs,Wo as partitionAccounts,Qn as partitionForRegion,ta as partitionPreFlightByRemediation,ma as pinProbeCoverage,fe as placeAccountsInOUs,ae as probeAccountStackExists,Xo as probeSecretsDrift,Ho as probeServiceDeploymentStatus,oi as projectAccountRows,ti as projectScalarSummary,Ji as proveFlipMetadataOnly,_a as proveRemovalTargetsOnly,Rt as readDomainState,Di as readDriftSuspects,vi as readRemediationJournal,Qi as readRetainFlipState,st as readStateFile,ai as reconcileProviderAccounts,ci as reconcileTrailMigration,mt as recordDomainDeployState,Pi as recordDriftSuspects,Ee as regionDisabledMessage,At as regionSuffix,be as registerSecurityDelegates,ur as remediationPhaseRank,Dr as remediationPlaceholderPhysicalId,hs as renderConsentVerdictLines,Fs as renderDestructionTicketLines,Na as renderIdentityPinReportLines,da as renderPinReportLines,ps as renderPlanLines,As as renderPlanSummary,Hn as resolveBuildArgs,Kn as resolveBuildSecretSessionProvider,Gn as resolveBuildSecrets,Bn as resolveSecretRefValue,Ko as restart,wa as restoreAndReconcileQuarantinedBucket,Ka as restoreBucketPolicy,Ds as runApprovalGate,Cn as runCaaPreflight,Fn as runDelegatedDomainDestroy,fs as runDestructionGate,fi as runDriftPreFlight,Ra as runDriftRepairGate,oa as runForgetSurgery,Ia as runIdentityPinMigration,Oa as runIdentitySurfaceGate,Sn as runOpenNextBuild,_n as runOrganisationSetup,ua as runPinRemediation,Ea as runRecreatePreFlight,aa as runRecreateSurgery,Li as runRoute53RecordPreflight,Ts as signApprovalToken,Ro as sleep,No as sleepAbortable,ge as snapshotIdentityCentre,na as snapshotPolicyForType,Xn as sourcedRefsFromBuildArgs,ht as startStackMonitoring,$n as staticSiteBuilder,tt as stubCallerIdentity,ho as success,bi as sweepExpiredRemediationJournals,ia as synthTemplateDeclaresResource,Xa as synthesiseEnforceSslDocument,vn as systemDnsNameProbe,Ln as templateOwnsDelegationRecord,Qr as toPascalCase,Ba as toResourcePolicyStatements,So as toServiceError,Rs as toWirePlanChanges,Va as triageBucketPolicy,p as truncateUtf16Safe,ba as unlockBucket,ka as unlockQueue,de as updateBackupGlobalSettings,lt as updateTemplateHash,jn as validateBuildGroup,lr as verbsForDriftVerdict,ms as verifyApprovalToken,Qa as verifyOrgTrailDelivery,ji as verifyRetainFlipDiff,On as waitForNsPropagation,rt as wrapApplicationError,Tt as writeDomainState,ki as writeRemediationJournal,Et as writeStateFile};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Re=Object.defineProperty;var D=(e,n)=>Re(e,"name",{value:n,configurable:!0});import{join as fe}from"path";import{CloudFormationClient as Ce}from"@aws-sdk/client-cloudformation";import{EC2Client as Ie}from"@aws-sdk/client-ec2";import{success as I,failure as d}from"@fjall/generator";import{logger as F}from"@fjall/util/logger";import{ImageTagSchema as Oe,getErrorMessage as Q,imageTagParameterName as Ae,maskSensitiveOutput as k}from"@fjall/util";import{parseDockerDeclarationsFromManifest as Le}from"@fjall/util/manifest";import{stubCallerIdentity as Be}from"../../types/deployment/index.js";import{getApplicationDeployOrder as Me,getApplicationStackName as O,getApplicationStepName as pe,getApplicationStepId as me,APPLICATION_STACKS as C}from"../../types/operations.js";import{CdkContextBuilder as $e}from"../../services/supporting/CdkContextBuilder.js";import{buildParamsContext as xe,buildCapacityIdentityContext as Fe,bootstrapOrFail as je}from"../contextHelpers.js";import{resolveDeployEnvironment as Ge}from"../deployEnvironment.js";import{buildBootstrapTagsIfResolved as He}from"../bootstrapTags.js";import{hasOrganisationTierAccount as Ue}from"../../aws/organisations/accountGlobals.js";import{runDetectionPipeline as _e}from"./detectionPipeline.js";import{assertCapacityPinsSupportedByAssembly as We,assertEngineCompatibleWithAssembly as Ke}from"./engineCompat.js";import{STEP_IDS as _,STEP_NAMES as qe}from"../../types/stepDefinitions.js";import{StepRegistry as Ve}from"../../steps/stepRegistry.js";import{checkTargetReadiness as ze}from"../../aws/targetReadiness.js";import{cascadeHomeRegion as Je}from"../organisation/cascadeHelpers.js";import{withStepLifecycle as Ye}from"../stepLifecycle.js";import{DOCKER_BUILD_STEP_NAME as ye,runDockerBuild as Qe}from"./dockerBuildHelper.js";import{getParallelPhase2Stacks as Xe,getStackNamesToDeploy as Ze,deployParallelPhase as et,deployStackSequential as tt,runDockerPreCompute as rt,runLambdaVersionPublish as nt,createBuildCallbacks as ot,willRunDockerBuild as at}from"./applicationDeployHelpers.js";import{verifyAssemblyIntegrity as ke}from"./assemblyIntegrity.js";import{captureDatabaseConnectionOutputs as it,captureServiceTaskDefinitions as st,reconcileDatabaseEndpointChange as ct}from"./databaseEndpointReconcile.js";import{deployCodeOnly as lt}from"./codeOnlyDeploy.js";import{checkDeployPathStackAvailability as he}from"../activeDeploymentGuard.js";import{assertLeaseBeforeStack as W}from"./leaseGate.js";import{collectFullDeployArtefacts as dt}from"./artefactCollection.js";import{CfnRegistryService as ut}from"../../services/infrastructure/CfnRegistryService.js";import{ChangeSetProbe as gt}from"../../services/infrastructure/changeSetProbe.js";import{runApprovalGate as ft}from"./approvalGate.js";import{buildDestructionTicket as pt,runDestructionGate as mt}from"./destructionGate.js";import{DESTRUCTION_RESUME_TTL_MS as yt,signApprovalToken as kt}from"./plan/approvalToken.js";import{computeAssemblyDigest as ht}from"./plan/assemblyDigest.js";import{createMemoisedPlanLoader as St}from"./plan/loadDeployPlan.js";import{runDriftPreFlightGate as bt}from"../drift/preFlightGate.js";import{completeForgetAfterDeploy as wt}from"../remediation/forgetResource.js";import{composePostFailureRepairOffer as Se}from"../remediation/postFailureRepairOffer.js";import{renderPinReportLines as Et,runPinRemediation as Tt}from"../remediation/pinRemediation.js";import{degradedIdentityPinOutcomes as be,renderIdentityPinReportLines as Pt}from"../remediation/migrateIdentity.js";import{runRecreatePreFlight as vt}from"../remediation/recreatePreFlight.js";import{runRecreateSurgery as Nt}from"../remediation/recreateResource.js";const j="applicationDeploy";function Dt(e){const n=Object.entries(e);if(n.length===0)return;const o={};for(const[t,i]of n){const w=Ae(t);o[w]=i}return o}D(Dt,"buildCdkImageTagParameters");function Rt(e){if(e?.mode!==void 0&&e.mode!=="rollback"){if(e.imageTag)return d(new Error(`--image-tag requires rollback mode (explicit mode '${e.mode}' was supplied alongside an image tag)`));if(e.serviceImageTags)return d(new Error(`serviceImageTags requires rollback mode (explicit mode '${e.mode}' was supplied alongside serviceImageTags)`))}if(e?.mode==="rollback"){if(e.imageTag&&e.serviceImageTags)return d(new Error("rollback mode accepts exactly one of --image-tag or serviceImageTags \u2014 they are mutually exclusive"));if(!e.imageTag&&!e.serviceImageTags)return d(new Error("rollback mode requires --image-tag <tag> or serviceImageTags naming the image(s) to roll to"))}if(e?.serviceImageTags!==void 0){if(e.serviceName)return d(new Error("serviceImageTags already names its services \u2014 --service cannot be combined with it"));const n=Object.entries(e.serviceImageTags);if(n.length===0)return d(new Error("serviceImageTags must name at least one service"));for(const[o,t]of n){const i=Oe.safeParse(t);if(!i.success)return d(new Error(`serviceImageTags.${o} is not a valid image tag: ${i.error.message}`))}}return I(void 0)}D(Rt,"validateRollbackOptions");function we(e,n,o){if(e.onStackTargets===void 0||o.length===0)return;const t=n.awsProvider.getAccountId(),i=n.awsProvider.getRegion();e.onStackTargets(o.map(w=>({stackName:w,...t!==""?{accountId:t}:{},...i!==""?{region:i}:{}})))}D(we,"emitStackTargets");async function Sr(e,n,o){const{callbacks:t,options:i}=e,w=Date.now(),G=i?.mode??(i?.imageTag||i?.serviceImageTags?"rollback":i?.deployOnly?"code-only":"full");if(G==="restart"){const r=new Error('mode "restart" is not a deploy \u2014 call the restart() entry point (fjall rollout) instead');return t.onError?.(r),d(r)}const X=Rt(i);if(!X.success){const r=k(X.error.message),a=new Error(r);return t.onError?.(a),d(a)}const K=Ge({orgConfig:e.orgConfig,accountId:n.awsProvider.getAccountId()});if(!K.success){const r=new Error(k(K.error.message));return t.onError?.(r),d(r)}const B=$e.buildDeploymentContext({deployType:"application",target:o.appName,path:o.path,region:n.awsProvider.getRegion(),environment:K.data,callerIdentity:Be(n.awsProvider.getAccountId()),...xe({orgConfig:e.orgConfig,identity:e.identity,skipOidc:e.options?.skipOidc}),...e.managedDomainBindings!==void 0?{managedDomainBindings:e.managedDomainBindings}:{},...Fe(e)},{verbose:i?.verbose,infraOnly:i?.infraOnly},e.orgConfig),P=n.frameworkRegistry.resolve({appPath:o.path});let Z;const M=G==="rollback";if(P&&!M){Z=P.builder.plan({appPath:o.path},P.detection);const r=ot(t),a=await P.builder.build(o.path,Z,r,{skipBuild:i?.skipBuild,infraOnly:i?.infraOnly,...e.abortSignal!==void 0&&{abortSignal:e.abortSignal}});if(!a.success){const c=new Error(k(a.error.message));return t.onError?.(c),d(c)}}if(G==="code-only"||M){t.onLog?.(M?i?.serviceImageTags?`Rollback mode \u2014 rolling ${Object.keys(i.serviceImageTags).length} service(s) to their release-recorded image tags`:`Rollback mode \u2014 rolling to image tag ${i?.imageTag}`:"Deploy-only mode \u2014 skipping infrastructure pipeline","info");const r=fe(o.path,"cdk.out"),a=Ke({cdkOutPath:r,onWarning:D(f=>t.onLog?.(f,"warn"),"onWarning")});if(!a.success){const f=new Error(k(a.error.message));return t.onError?.(f),d(f)}const c=We({cdkOutPath:r,capacityIdentityWire:B.capacityIdentity,appName:o.appName});if(!c.success){const f=new Error(k(c.error.message));return t.onError?.(f),d(f)}const m=Le(r),l=m.declaresBuild,y=P?.detection.hasDockerfile===!0,g=l||y;F.debug(j,"Deploy-only branch entered",{mode:G,imageTag:i?.imageTag,serviceImageTags:i?.serviceImageTags,appName:o.appName,appPath:o.path,cdkOutPath:r,dockerProviderAvailable:e.dockerProvider!==void 0,builderName:P?.builder.name,hasDockerfileFromManifest:l,hasDockerfileFromDisk:y,hasDockerfile:g,manifestDockerServiceCount:m.ecsServices.length,manifestDockerPaths:m.ecsServices.map(f=>f.docker.path),manifestLambdaDockerEntryCount:m.lambdaEntries.length}),!l&&!y&&t.onLog?.("No Dockerfile detected via manifest or appPath \u2014 skipping Docker build. If this app uses a cross-repo Dockerfile, ensure a full deploy has run first to populate cdk.out/fjall-manifest.json.","warn");const s=await he([O(o.appName,C.COMPUTE)],n.cfnService,e.abortSignal);if(!s.success)return t.onError?.(s.error),d(s.error);we(t,n,[O(o.appName,C.COMPUTE)]);let u={},h;if(!M&&e.dockerProvider!==void 0&&g){F.debug(j,"Running Docker build before code-only deploy",{source:l?"manifest":"disk"});const f=await Qe(e,n,o,t);if(!f.success)return d(f.error);u=f.data.contentHashTagsByService,h=f.data}else F.debug(j,"Skipping Docker build",{reason:M?"rollback":e.dockerProvider===void 0?"no dockerProvider":"no Dockerfile detected"});const b=await W(e.assertLeaseForStack,O(o.appName,C.COMPUTE),e.abortSignal);return b!==void 0?(t.onError?.(b),d(b)):lt(e,n,o,u,h)}t.onLog?.("Analysing infrastructure\u2026","info");const H=await _e(o,n,B,t,e.abortSignal);if(!H.success){const r=new Error(k(H.error.message),{cause:H.error});return t.onError?.(r),d(r)}const p=H.data;try{await t.onDetectionComplete?.({...p,builderName:P?.builder.name??"unknown"})}catch(r){const a=new Error(k(Q(r)),{cause:r});return t.onError?.(a),d(a)}const Ee={deploymentType:"application",operation:"deploy",deployOnly:!1,infraOnly:i?.infraOnly??!1,hasDockerfile:p.hasDockerfile,pattern:p.pattern,resources:p.resources,...P&&{builderName:P.builder.name}},ee=Ve.getSteps(Ee),te=ee.findIndex(r=>r.id===_.TARGET_READINESS),re=await Ye(t,{stepId:_.TARGET_READINESS,stepName:qe.TARGET_READINESS,...te>=0&&{stepIndex:te,totalSteps:ee.length}},async()=>{if(i?.skipReadinessCheck)return t.onLog?.("Skipping target readiness check (--skip-readiness-check)","warn"),{kind:"skipped",data:void 0};const r=n.awsProvider.getAccountId(),a=e.orgConfig?.providerAccounts.find(y=>y.id===r)?.name,c=n.awsProvider.getCredentials(),m=Je(e.orgConfig),l=await ze({cloudFormation:n.awsProvider.getClient(Ce),ec2:new Ie({region:m,...c!==void 0&&{credentials:c}})},{id:r,...a!==void 0&&{name:a}},n.awsProvider.getRegion(),e.orgConfig,e.abortSignal);return l.success?l.data.ready?{kind:"completed",data:void 0}:{kind:"error",error:new Error(k(l.data.advisory))}:{kind:"error",error:new Error(k(l.error.message),{cause:l.error})}},e.abortSignal);if(!re.success)return re;const v=Me({pattern:p.pattern,resources:p.resources}),A=v.length,ne=p.hasDockerfile&&e.dockerProvider!==void 0&&v.includes(C.COMPUTE)&&i?.infraOnly!==!0;if(!p.hasDifferences&&!i?.force&&!ne){t.onLog?.("No infrastructure changes detected","info"),t.onLog?.(i?.infraOnly===!0?"Infrastructure-only mode \u2014 application code was not rebuilt. Run with --deploy-only to deploy code changes.":"Nothing to deploy. Run with --deploy-only to redeploy application code.","info");const r=p.hasDockerfile&&e.dockerProvider!==void 0&&v.includes(C.COMPUTE);for(let c=0;c<v.length;c++){const m=v[c];r&&m===C.COMPUTE&&(t.onStepStart?.(_.DOCKER_OPERATIONS,ye),t.onStepComplete?.(_.DOCKER_OPERATIONS,ye,"skipped"));const l=me(m,"deploy"),y=pe(m,"deploy");t.onStepStart?.(l,y,c,A),t.onStepComplete?.(l,y,"skipped",c,A)}const a=await n.stackService.resolveWebsiteUrl(o.appName);return I({target:o.appName,deploymentType:"application",outputs:a?{websiteUrl:a}:void 0,noChanges:!0,artefacts:[],durationMs:Date.now()-w})}const L=fe(o.path,"cdk.out"),E=Ze({deployOrder:v,stackChanges:p.stackChanges,appName:o.appName,force:i?.force===!0,computeBuildPossible:ne});we(t,n,[...E]);const q=await he([...E],n.cfnService,e.abortSignal);if(!q.success)return t.onError?.(q.error),d(q.error);const oe={stacksToDeploy:[...E],imageBuild:at({stackNamesToDeploy:E,appName:o.appName,hasDockerProvider:e.dockerProvider!==void 0,hasDockerfile:p.hasDockerfile})},ae=ht(p.currentHashes,oe),V=St({cfnService:n.cfnService,cdkOutPath:L,changedStacks:[...E],assemblyDigest:ae,registry:new ut(n.awsProvider),changeSetProbe:new gt(n.awsProvider),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}),z=await bt(n.awsProvider,{stackNames:[...E],cdkOutPath:L,cfnService:n.cfnService,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(z.kind==="blocked"){const r=new Error(z.message);return t.onError?.(r),d(r)}const ie=z.verifiedAbsentByNecessity??[],U=e.approvalGate!==void 0||i?.approvalToken!==void 0&&i.approvalToken!==""||i?.planOnly===!0;if(U){const r=await ft({approvalGate:e.approvalGate,options:i??{},target:o.appName,cdkOutPath:L,detection:{stackChanges:p.stackChanges,currentHashes:p.currentHashes},scope:oe,cfnService:n.cfnService,loadPlan:V,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!r.success)return r;const a=r.data;if(a.kind==="rejected")return t.onLog?.(`Deploy rejected: ${k(a.reason)}`,"warn"),I({target:o.appName,deploymentType:"application",rejected:!0,artefacts:[],...a.planDetail!==void 0?{planDetail:a.planDetail}:{},durationMs:Date.now()-w});if(a.kind==="awaiting"){const c=await V(),m=c.success?pt(c.data,ie):void 0;return I({target:o.appName,deploymentType:"application",awaitingApproval:!0,approvalToken:a.approvalToken,assemblyDigest:a.assemblyDigest,planDetail:a.planDetail,...m!==void 0?{destructionTicket:m}:{},artefacts:[],durationMs:Date.now()-w})}}const N=await mt({loadPlan:V,options:i??{},target:o.appName,callbacks:t,verifiedAbsentByNecessity:ie,...e.destructionConsentGate!==void 0?{consentGate:e.destructionConsentGate}:{}});if(!N.success)return t.onError?.(N.error),d(N.error);if(N.data.kind==="withheld"){const r=U?kt({assemblyDigest:ae,ttlMs:yt}):void 0;return I({target:o.appName,deploymentType:"application",destructionPending:!0,destructionTicket:N.data.ticket,destructionOutcome:N.data.outcome,destructionHaltReasons:N.data.reasons,...r!==void 0?{destructionResumeToken:r.token,destructionResumeExpiresAt:r.expiresAt}:{},artefacts:[],durationMs:Date.now()-w})}if(N.data.kind==="proceed"){const{ticket:r,verbsByPhysicalName:a}=N.data,c=r.resources.filter(l=>a.get(l.physicalName)==="pin");if(c.length>0){const l=c.filter(u=>u.finding==="rename-detected"),y=c.filter(u=>u.finding!=="rename-detected");t.onLog?.(`Pin remediation for ${o.appName}: ${c.length} consented pin(s) \u2014 deploy stopped for config write-back; nothing was applied to AWS`,"warn");let g;if(l.length>0){if(e.identityPinRunner!==void 0)try{g=await e.identityPinRunner(l,e.abortSignal)}catch(u){g={outcomes:be(l,"unknown",`identity-pin runner failed: ${k(Q(u))} \u2014 fix the cause, then run 'fjall migrate identity'`),verified:[],clean:!1}}else g={outcomes:be(l,"unknown","this surface cannot run the identity-pin migration \u2014 run 'fjall migrate identity' to pin and validate this slot"),verified:[],clean:!1};for(const u of Pt(g))t.onLog?.(u,"warn")}let s;if(y.length>0){s=await Tt(n.awsProvider,{targets:y.map(u=>({stack:u.stack,logicalId:u.logicalId,resourceType:u.resourceType,physicalName:u.physicalName,offendingProperties:u.offendingProperties})),...e.infrastructureSource!==void 0?{infrastructureContent:e.infrastructureSource.content,infrastructureFilePath:e.infrastructureSource.filePath}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});for(const u of Et(s))t.onLog?.(u,"warn")}return c.length<r.resources.length&&t.onLog?.("Remaining consented change(s) were not applied \u2014 the config write-back changes the plan, so they re-consent on the next deploy","warn"),I({target:o.appName,deploymentType:"application",pinPending:!0,...s!==void 0?{pinReport:s}:{},...g!==void 0?{identityPinReport:g}:{},pinDeferredConsents:r.resources.length-c.length,destructionTicket:r,artefacts:[],durationMs:Date.now()-w})}const m=r.resources.filter(l=>l.finding==="pinned-name-replacement"&&a.get(l.physicalName)==="recreate");if(m.length>0){const l=new Map;for(const s of m){const u=l.get(s.stack)??[];u.push(s),l.set(s.stack,u)}const y=await vt(n.awsProvider,{stacks:[...l].map(([s,u])=>({stackName:s,targets:u.map(h=>({logicalId:h.logicalId,resourceType:h.resourceType,physicalId:h.physicalName}))})),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!y.success){const s=new Error(k(y.error.message),{cause:y.error});return t.onError?.(s),d(s)}const g=[];for(const[s,u]of l){const h=await W(e.assertLeaseForStack,s,e.abortSignal,"destroy");if(h!==void 0)return g.length>0&&t.onLog?.(`Surgery already completed on ${g.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`,"warn"),t.onError?.(h),d(h);const b=u.map(S=>S.physicalName);t.onLog?.(`Recreate remediation for ${o.appName}: orchestrating the pinned-name replacement of ${b.join(", ")} on ${s}`,"warn");const f=await Nt(n.awsProvider,{stackName:s,targets:u.map(S=>({logicalId:S.logicalId,resourceType:S.resourceType,physicalId:S.physicalName})),appName:o.appName,consentedPhysicalNames:b,doneJournalPolicy:"archive-and-restart",plannedReplacementLogicalIds:u.map(S=>S.logicalId),onProgress:D(S=>t.onLog?.(S,"info"),"onProgress"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!f.success){const S=g.length>0?` Surgery already completed on ${g.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`:"",T=new Error(k(`${f.error.message}${S}`));return t.onError?.(T),d(T)}g.push(`${s} (${b.join(", ")})`)}}}const Te=e.orgConfig!==void 0&&!Ue(e.orgConfig.providerAccounts),Pe=He({account:e.orgConfig?.providerAccounts.find(r=>r.id===n.awsProvider.getAccountId()),estate:Te?"solo":"org"}),se=await je(n,B,t,Pe);if(!se.success)return se;const ce=O(o.appName,C.DATABASE),J=E.has(ce),ve=J?await it(n.cfnService,o.appName,e.abortSignal):void 0,Ne=J?await st(n.ecsResolver,n.ecsService,o.appName,e.abortSignal):void 0,$={},x=new Map;let le,de={};const R=D(async()=>{!J||!x.has(ce)||await ct({appName:o.appName,connectionOutputsBefore:ve,serviceTaskDefinitionsBefore:Ne,services:{cfnService:n.cfnService,ecsService:n.ecsService,ecsResolver:n.ecsResolver},callbacks:t,...e.confirmDatabaseEndpointRestart!==void 0?{confirmRestart:e.confirmDatabaseEndpointRestart}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}})},"reconcileIfDatabaseReplaced");for(let r=0;r<v.length;r++){const a=v[r],c=O(o.appName,a),m=me(a,"deploy"),l=pe(a,"deploy");if(!E.has(c)){t.onStepStart?.(m,l,r,A),t.onLog?.(`Skipping ${a} \u2014 no changes detected`,"info"),t.onStepComplete?.(m,l,"skipped",r,A);continue}const y=await W(e.assertLeaseForStack,c,e.abortSignal);if(y!==void 0)return await R(),t.onError?.(y),d(y);const g=Xe(v,r,o.appName,E);if(g.length>=2){const T=await ke({hashService:n.hashService,cdkOutPath:L,stackNames:g.map(Y=>O(o.appName,Y)),detectionHashes:p.currentHashes,approvalGated:U});if(!T.success)return await R(),t.onError?.(T.error),d(T.error);const ge=await et(g,o,n,B,t,r,A,p,$,x);if(!ge.success)return await R(),d(await Se(n.awsProvider,{stackNames:g.map(Y=>O(o.appName,Y)),appName:o.appName,originalError:ge.error,cfnService:n.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));r+=g.length-1;continue}const s=await rt(a,e,n,o,t,p.hasDockerfile);if(s!==null&&!s.success)return await R(),d(s.error);s!==null&&s.success&&(le=s.data);const u=s!==null&&s.success?s.data.contentHashTagsByService:{},h=Dt(u);if(s!==null){const T=await W(e.assertLeaseForStack,c,e.abortSignal);if(T!==void 0)return await R(),t.onError?.(T),d(T)}const b=await ke({hashService:n.hashService,cdkOutPath:L,stackNames:[c],detectionHashes:p.currentHashes,approvalGated:U});if(!b.success)return await R(),t.onError?.(b.error),d(b.error);const f=await tt(a,n,B,t,r,A,$,h!==void 0||e.abortSignal!==void 0?{...h!==void 0?{parameters:h}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}:void 0);if(!f.success)return await R(),d(await Se(n.awsProvider,{stackNames:[c],appName:o.appName,originalError:f.error,cfnService:n.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));a===C.COMPUTE&&(de=await nt(o,n,t,u,e.abortSignal));const S=p.currentHashes.get(c);S&&x.set(c,S)}if(await R(),x.size>0){const r=await n.hashService.updateStateAfterDeploy(o.path,x);if(!r.success){const a=k(r.error.message);F.debug(j,"Failed to update state file",{error:a}),t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy unchanged stacks: ${a}`,"warn")}}const ue=await n.stackService.resolveWebsiteUrl(o.appName);ue&&($.websiteUrl=ue);const De=await dt(n,o.appName,le,t,L,de,e.abortSignal);return await wt(n.awsProvider,{stackNames:[...E],appName:o.appName,onLog:D((r,a)=>t.onLog?.(r,a),"onLog"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}).catch(r=>{F.debug(j,"Forget completion sweep failed",{error:k(Q(r))})}),I({target:o.appName,deploymentType:"application",outputs:Object.keys($).length>0?$:void 0,artefacts:De,durationMs:Date.now()-w})}D(Sr,"deployApplication");export{Sr as deployApplication,we as emitStackTargets};
|
|
1
|
+
var Re=Object.defineProperty;var P=(e,n)=>Re(e,"name",{value:n,configurable:!0});import{join as fe}from"path";import{CloudFormationClient as Ie}from"@aws-sdk/client-cloudformation";import{EC2Client as Ce}from"@aws-sdk/client-ec2";import{success as A,failure as l}from"@fjall/generator";import{logger as F}from"@fjall/util/logger";import{ImageTagSchema as Oe,getErrorMessage as Q,imageTagParameterName as Ae,maskSensitiveOutput as h}from"@fjall/util";import{parseDockerDeclarationsFromManifest as Le}from"@fjall/util/manifest";import{stubCallerIdentity as Be}from"../../types/deployment/index.js";import{getApplicationDeployOrder as Me,getApplicationStackName as C,getApplicationStepName as pe,getApplicationStepId as me,APPLICATION_STACKS as R}from"../../types/operations.js";import{CdkContextBuilder as $e}from"../../services/supporting/CdkContextBuilder.js";import{buildParamsContext as xe,buildCapacityIdentityContext as Fe,bootstrapOrFail as je}from"../contextHelpers.js";import{resolveDeployEnvironment as Ge}from"../deployEnvironment.js";import{buildBootstrapTagsIfResolved as He}from"../bootstrapTags.js";import{hasOrganisationTierAccount as Ue}from"../../aws/organisations/accountGlobals.js";import{runDetectionPipeline as _e}from"./detectionPipeline.js";import{assertCapacityPinsSupportedByAssembly as We,assertEngineCompatibleWithAssembly as Ke}from"./engineCompat.js";import{STEP_IDS as _,STEP_NAMES as qe}from"../../types/stepDefinitions.js";import{StepRegistry as Ve}from"../../steps/stepRegistry.js";import{checkTargetReadiness as ze}from"../../aws/targetReadiness.js";import{cascadeHomeRegion as Je}from"../organisation/cascadeHelpers.js";import{withStepLifecycle as Ye}from"../stepLifecycle.js";import{DOCKER_BUILD_STEP_NAME as ye,runDockerBuild as Qe}from"./dockerBuildHelper.js";import{getParallelPhase2Stacks as Xe,getStackNamesToDeploy as Ze,deployParallelPhase as et,deployStackSequential as tt,runDockerPreCompute as rt,runLambdaVersionPublish as nt,createBuildCallbacks as ot,willRunDockerBuild as at}from"./applicationDeployHelpers.js";import{verifyAssemblyIntegrity as he}from"./assemblyIntegrity.js";import{captureDatabaseConnectionOutputs as it,captureServiceTaskDefinitions as st,reconcileDatabaseEndpointChange as ct}from"./databaseEndpointReconcile.js";import{deployCodeOnly as lt}from"./codeOnlyDeploy.js";import{ensureSchemaGateImage as dt}from"./schemaGateImage.js";import{checkDeployPathStackAvailability as ke}from"../activeDeploymentGuard.js";import{assertLeaseBeforeStack as W}from"./leaseGate.js";import{collectFullDeployArtefacts as ut}from"./artefactCollection.js";import{CfnRegistryService as gt}from"../../services/infrastructure/CfnRegistryService.js";import{ChangeSetProbe as ft}from"../../services/infrastructure/changeSetProbe.js";import{runApprovalGate as pt}from"./approvalGate.js";import{buildDestructionTicket as mt,runDestructionGate as yt}from"./destructionGate.js";import{DESTRUCTION_RESUME_TTL_MS as ht,signApprovalToken as kt}from"./plan/approvalToken.js";import{computeAssemblyDigest as St}from"./plan/assemblyDigest.js";import{createMemoisedPlanLoader as bt}from"./plan/loadDeployPlan.js";import{runDriftPreFlightGate as wt}from"../drift/preFlightGate.js";import{completeForgetAfterDeploy as Et}from"../remediation/forgetResource.js";import{composePostFailureRepairOffer as Se}from"../remediation/postFailureRepairOffer.js";import{renderPinReportLines as Tt,runPinRemediation as Pt}from"../remediation/pinRemediation.js";import{degradedIdentityPinOutcomes as be,renderIdentityPinReportLines as vt}from"../remediation/migrateIdentity.js";import{runRecreatePreFlight as Nt}from"../remediation/recreatePreFlight.js";import{runRecreateSurgery as Dt}from"../remediation/recreateResource.js";const j="applicationDeploy";function Rt(e){const n=Object.entries(e);if(n.length===0)return;const o={};for(const[t,s]of n){const E=Ae(t);o[E]=s}return o}P(Rt,"buildCdkImageTagParameters");function It(e){if(e?.mode!==void 0&&e.mode!=="rollback"){if(e.imageTag)return l(new Error(`--image-tag requires rollback mode (explicit mode '${e.mode}' was supplied alongside an image tag)`));if(e.serviceImageTags)return l(new Error(`serviceImageTags requires rollback mode (explicit mode '${e.mode}' was supplied alongside serviceImageTags)`))}if(e?.mode==="rollback"){if(e.imageTag&&e.serviceImageTags)return l(new Error("rollback mode accepts exactly one of --image-tag or serviceImageTags \u2014 they are mutually exclusive"));if(!e.imageTag&&!e.serviceImageTags)return l(new Error("rollback mode requires --image-tag <tag> or serviceImageTags naming the image(s) to roll to"))}if(e?.serviceImageTags!==void 0){if(e.serviceName)return l(new Error("serviceImageTags already names its services \u2014 --service cannot be combined with it"));const n=Object.entries(e.serviceImageTags);if(n.length===0)return l(new Error("serviceImageTags must name at least one service"));for(const[o,t]of n){const s=Oe.safeParse(t);if(!s.success)return l(new Error(`serviceImageTags.${o} is not a valid image tag: ${s.error.message}`))}}return A(void 0)}P(It,"validateRollbackOptions");function we(e,n,o){if(e.onStackTargets===void 0||o.length===0)return;const t=n.awsProvider.getAccountId(),s=n.awsProvider.getRegion();e.onStackTargets(o.map(E=>({stackName:E,...t!==""?{accountId:t}:{},...s!==""?{region:s}:{}})))}P(we,"emitStackTargets");async function wr(e,n,o){const{callbacks:t,options:s}=e,E=Date.now(),G=s?.mode??(s?.imageTag||s?.serviceImageTags?"rollback":s?.deployOnly?"code-only":"full");if(G==="restart"){const r=new Error('mode "restart" is not a deploy \u2014 call the restart() entry point (fjall rollout) instead');return t.onError?.(r),l(r)}const X=It(s);if(!X.success){const r=h(X.error.message),a=new Error(r);return t.onError?.(a),l(a)}const K=Ge({orgConfig:e.orgConfig,accountId:n.awsProvider.getAccountId()});if(!K.success){const r=new Error(h(K.error.message));return t.onError?.(r),l(r)}const B=$e.buildDeploymentContext({deployType:"application",target:o.appName,path:o.path,region:n.awsProvider.getRegion(),environment:K.data,callerIdentity:Be(n.awsProvider.getAccountId()),...xe({orgConfig:e.orgConfig,identity:e.identity,skipOidc:e.options?.skipOidc}),...e.managedDomainBindings!==void 0?{managedDomainBindings:e.managedDomainBindings}:{},...Fe(e)},{verbose:s?.verbose,infraOnly:s?.infraOnly},e.orgConfig),v=n.frameworkRegistry.resolve({appPath:o.path});let Z;const M=G==="rollback";if(v&&!M){Z=v.builder.plan({appPath:o.path},v.detection);const r=ot(t),a=await v.builder.build(o.path,Z,r,{skipBuild:s?.skipBuild,infraOnly:s?.infraOnly,...e.abortSignal!==void 0&&{abortSignal:e.abortSignal}});if(!a.success){const i=new Error(h(a.error.message));return t.onError?.(i),l(i)}}if(G==="code-only"||M){t.onLog?.(M?s?.serviceImageTags?`Rollback mode \u2014 rolling ${Object.keys(s.serviceImageTags).length} service(s) to their release-recorded image tags`:`Rollback mode \u2014 rolling to image tag ${s?.imageTag}`:"Deploy-only mode \u2014 skipping infrastructure pipeline","info");const r=fe(o.path,"cdk.out"),a=Ke({cdkOutPath:r,onWarning:P(f=>t.onLog?.(f,"warn"),"onWarning")});if(!a.success){const f=new Error(h(a.error.message));return t.onError?.(f),l(f)}const i=We({cdkOutPath:r,capacityIdentityWire:B.capacityIdentity,appName:o.appName});if(!i.success){const f=new Error(h(i.error.message));return t.onError?.(f),l(f)}const m=Le(r),d=m.declaresBuild,y=v?.detection.hasDockerfile===!0,g=d||y;F.debug(j,"Deploy-only branch entered",{mode:G,imageTag:s?.imageTag,serviceImageTags:s?.serviceImageTags,appName:o.appName,appPath:o.path,cdkOutPath:r,dockerProviderAvailable:e.dockerProvider!==void 0,builderName:v?.builder.name,hasDockerfileFromManifest:d,hasDockerfileFromDisk:y,hasDockerfile:g,manifestDockerServiceCount:m.ecsServices.length,manifestDockerPaths:m.ecsServices.map(f=>f.docker.path),manifestLambdaDockerEntryCount:m.lambdaEntries.length}),!d&&!y&&t.onLog?.("No Dockerfile detected via manifest or appPath \u2014 skipping Docker build. If this app uses a cross-repo Dockerfile, ensure a full deploy has run first to populate cdk.out/fjall-manifest.json.","warn");const c=await ke([C(o.appName,R.COMPUTE)],n.cfnService,e.abortSignal);if(!c.success)return t.onError?.(c.error),l(c.error);we(t,n,[C(o.appName,R.COMPUTE)]);let u={},k;if(!M&&e.dockerProvider!==void 0&&g){F.debug(j,"Running Docker build before code-only deploy",{source:d?"manifest":"disk"});const f=await Qe(e,n,o,t);if(!f.success)return l(f.error);u=f.data.contentHashTagsByService,k=f.data}else F.debug(j,"Skipping Docker build",{reason:M?"rollback":e.dockerProvider===void 0?"no dockerProvider":"no Dockerfile detected"});const w=await W(e.assertLeaseForStack,C(o.appName,R.COMPUTE),e.abortSignal);return w!==void 0?(t.onError?.(w),l(w)):lt(e,n,o,u,k)}t.onLog?.("Analysing infrastructure\u2026","info");const H=await _e(o,n,B,t,e.abortSignal);if(!H.success){const r=new Error(h(H.error.message),{cause:H.error});return t.onError?.(r),l(r)}const p=H.data;try{await t.onDetectionComplete?.({...p,builderName:v?.builder.name??"unknown"})}catch(r){const a=new Error(h(Q(r)),{cause:r});return t.onError?.(a),l(a)}const Ee={deploymentType:"application",operation:"deploy",deployOnly:!1,infraOnly:s?.infraOnly??!1,hasDockerfile:p.hasDockerfile,pattern:p.pattern,resources:p.resources,...v&&{builderName:v.builder.name}},ee=Ve.getSteps(Ee),te=ee.findIndex(r=>r.id===_.TARGET_READINESS),re=await Ye(t,{stepId:_.TARGET_READINESS,stepName:qe.TARGET_READINESS,...te>=0&&{stepIndex:te,totalSteps:ee.length}},async()=>{if(s?.skipReadinessCheck)return t.onLog?.("Skipping target readiness check (--skip-readiness-check)","warn"),{kind:"skipped",data:void 0};const r=n.awsProvider.getAccountId(),a=e.orgConfig?.providerAccounts.find(y=>y.id===r)?.name,i=n.awsProvider.getCredentials(),m=Je(e.orgConfig),d=await ze({cloudFormation:n.awsProvider.getClient(Ie),ec2:new Ce({region:m,...i!==void 0&&{credentials:i}})},{id:r,...a!==void 0&&{name:a}},n.awsProvider.getRegion(),e.orgConfig,e.abortSignal);return d.success?d.data.ready?{kind:"completed",data:void 0}:{kind:"error",error:new Error(h(d.data.advisory))}:{kind:"error",error:new Error(h(d.error.message),{cause:d.error})}},e.abortSignal);if(!re.success)return re;const N=Me({pattern:p.pattern,resources:p.resources}),L=N.length,ne=p.hasDockerfile&&e.dockerProvider!==void 0&&N.includes(R.COMPUTE)&&s?.infraOnly!==!0;if(!p.hasDifferences&&!s?.force&&!ne){t.onLog?.("No infrastructure changes detected","info"),t.onLog?.(s?.infraOnly===!0?"Infrastructure-only mode \u2014 application code was not rebuilt. Run with --deploy-only to deploy code changes.":"Nothing to deploy. Run with --deploy-only to redeploy application code.","info");const r=p.hasDockerfile&&e.dockerProvider!==void 0&&N.includes(R.COMPUTE);for(let i=0;i<N.length;i++){const m=N[i];r&&m===R.COMPUTE&&(t.onStepStart?.(_.DOCKER_OPERATIONS,ye),t.onStepComplete?.(_.DOCKER_OPERATIONS,ye,"skipped"));const d=me(m,"deploy"),y=pe(m,"deploy");t.onStepStart?.(d,y,i,L),t.onStepComplete?.(d,y,"skipped",i,L)}const a=await n.stackService.resolveWebsiteUrl(o.appName);return A({target:o.appName,deploymentType:"application",outputs:a?{websiteUrl:a}:void 0,noChanges:!0,artefacts:[],durationMs:Date.now()-E})}const O=fe(o.path,"cdk.out"),b=Ze({deployOrder:N,stackChanges:p.stackChanges,appName:o.appName,force:s?.force===!0,computeBuildPossible:ne});we(t,n,[...b]);const q=await ke([...b],n.cfnService,e.abortSignal);if(!q.success)return t.onError?.(q.error),l(q.error);const oe={stacksToDeploy:[...b],imageBuild:at({stackNamesToDeploy:b,appName:o.appName,hasDockerProvider:e.dockerProvider!==void 0,hasDockerfile:p.hasDockerfile})},ae=St(p.currentHashes,oe),V=bt({cfnService:n.cfnService,cdkOutPath:O,changedStacks:[...b],assemblyDigest:ae,registry:new gt(n.awsProvider),changeSetProbe:new ft(n.awsProvider),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}),z=await wt(n.awsProvider,{stackNames:[...b],cdkOutPath:O,cfnService:n.cfnService,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(z.kind==="blocked"){const r=new Error(z.message);return t.onError?.(r),l(r)}const ie=z.verifiedAbsentByNecessity??[],U=e.approvalGate!==void 0||s?.approvalToken!==void 0&&s.approvalToken!==""||s?.planOnly===!0;if(U){const r=await pt({approvalGate:e.approvalGate,options:s??{},target:o.appName,cdkOutPath:O,detection:{stackChanges:p.stackChanges,currentHashes:p.currentHashes},scope:oe,cfnService:n.cfnService,loadPlan:V,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!r.success)return r;const a=r.data;if(a.kind==="rejected")return t.onLog?.(`Deploy rejected: ${h(a.reason)}`,"warn"),A({target:o.appName,deploymentType:"application",rejected:!0,artefacts:[],...a.planDetail!==void 0?{planDetail:a.planDetail}:{},durationMs:Date.now()-E});if(a.kind==="awaiting"){const i=await V(),m=i.success?mt(i.data,ie):void 0;return A({target:o.appName,deploymentType:"application",awaitingApproval:!0,approvalToken:a.approvalToken,assemblyDigest:a.assemblyDigest,planDetail:a.planDetail,...m!==void 0?{destructionTicket:m}:{},artefacts:[],durationMs:Date.now()-E})}}const D=await yt({loadPlan:V,options:s??{},target:o.appName,callbacks:t,verifiedAbsentByNecessity:ie,...e.destructionConsentGate!==void 0?{consentGate:e.destructionConsentGate}:{}});if(!D.success)return t.onError?.(D.error),l(D.error);if(D.data.kind==="withheld"){const r=U?kt({assemblyDigest:ae,ttlMs:ht}):void 0;return A({target:o.appName,deploymentType:"application",destructionPending:!0,destructionTicket:D.data.ticket,destructionOutcome:D.data.outcome,destructionHaltReasons:D.data.reasons,...r!==void 0?{destructionResumeToken:r.token,destructionResumeExpiresAt:r.expiresAt}:{},artefacts:[],durationMs:Date.now()-E})}if(b.has(C(o.appName,R.COMPUTE))){const r=await dt({awsProvider:n.awsProvider,cdkOutPath:O,onLog:P((a,i)=>t.onLog?.(a,i),"onLog"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!r.success)return t.onError?.(r.error),l(r.error)}if(D.data.kind==="proceed"){const{ticket:r,verbsByPhysicalName:a}=D.data,i=r.resources.filter(d=>a.get(d.physicalName)==="pin");if(i.length>0){const d=i.filter(u=>u.finding==="rename-detected"),y=i.filter(u=>u.finding!=="rename-detected");t.onLog?.(`Pin remediation for ${o.appName}: ${i.length} consented pin(s) \u2014 deploy stopped for config write-back; nothing was applied to AWS`,"warn");let g;if(d.length>0){if(e.identityPinRunner!==void 0)try{g=await e.identityPinRunner(d,e.abortSignal)}catch(u){g={outcomes:be(d,"unknown",`identity-pin runner failed: ${h(Q(u))} \u2014 fix the cause, then run 'fjall migrate identity'`),verified:[],clean:!1}}else g={outcomes:be(d,"unknown","this surface cannot run the identity-pin migration \u2014 run 'fjall migrate identity' to pin and validate this slot"),verified:[],clean:!1};for(const u of vt(g))t.onLog?.(u,"warn")}let c;if(y.length>0){c=await Pt(n.awsProvider,{targets:y.map(u=>({stack:u.stack,logicalId:u.logicalId,resourceType:u.resourceType,physicalName:u.physicalName,offendingProperties:u.offendingProperties})),...e.infrastructureSource!==void 0?{infrastructureContent:e.infrastructureSource.content,infrastructureFilePath:e.infrastructureSource.filePath}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});for(const u of Tt(c))t.onLog?.(u,"warn")}return i.length<r.resources.length&&t.onLog?.("Remaining consented change(s) were not applied \u2014 the config write-back changes the plan, so they re-consent on the next deploy","warn"),A({target:o.appName,deploymentType:"application",pinPending:!0,...c!==void 0?{pinReport:c}:{},...g!==void 0?{identityPinReport:g}:{},pinDeferredConsents:r.resources.length-i.length,destructionTicket:r,artefacts:[],durationMs:Date.now()-E})}const m=r.resources.filter(d=>d.finding==="pinned-name-replacement"&&a.get(d.physicalName)==="recreate");if(m.length>0){const d=new Map;for(const c of m){const u=d.get(c.stack)??[];u.push(c),d.set(c.stack,u)}const y=await Nt(n.awsProvider,{stacks:[...d].map(([c,u])=>({stackName:c,targets:u.map(k=>({logicalId:k.logicalId,resourceType:k.resourceType,physicalId:k.physicalName}))})),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!y.success){const c=new Error(h(y.error.message),{cause:y.error});return t.onError?.(c),l(c)}const g=[];for(const[c,u]of d){const k=await W(e.assertLeaseForStack,c,e.abortSignal,"destroy");if(k!==void 0)return g.length>0&&t.onLog?.(`Surgery already completed on ${g.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`,"warn"),t.onError?.(k),l(k);const w=u.map(S=>S.physicalName);t.onLog?.(`Recreate remediation for ${o.appName}: orchestrating the pinned-name replacement of ${w.join(", ")} on ${c}`,"warn");const f=await Dt(n.awsProvider,{stackName:c,targets:u.map(S=>({logicalId:S.logicalId,resourceType:S.resourceType,physicalId:S.physicalName})),appName:o.appName,consentedPhysicalNames:w,doneJournalPolicy:"archive-and-restart",plannedReplacementLogicalIds:u.map(S=>S.logicalId),onProgress:P(S=>t.onLog?.(S,"info"),"onProgress"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!f.success){const S=g.length>0?` Surgery already completed on ${g.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`:"",T=new Error(h(`${f.error.message}${S}`));return t.onError?.(T),l(T)}g.push(`${c} (${w.join(", ")})`)}}}const Te=e.orgConfig!==void 0&&!Ue(e.orgConfig.providerAccounts),Pe=He({account:e.orgConfig?.providerAccounts.find(r=>r.id===n.awsProvider.getAccountId()),estate:Te?"solo":"org"}),se=await je(n,B,t,Pe);if(!se.success)return se;const ce=C(o.appName,R.DATABASE),J=b.has(ce),ve=J?await it(n.cfnService,o.appName,e.abortSignal):void 0,Ne=J?await st(n.ecsResolver,n.ecsService,o.appName,e.abortSignal):void 0,$={},x=new Map;let le,de={};const I=P(async()=>{!J||!x.has(ce)||await ct({appName:o.appName,connectionOutputsBefore:ve,serviceTaskDefinitionsBefore:Ne,services:{cfnService:n.cfnService,ecsService:n.ecsService,ecsResolver:n.ecsResolver},callbacks:t,...e.confirmDatabaseEndpointRestart!==void 0?{confirmRestart:e.confirmDatabaseEndpointRestart}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}})},"reconcileIfDatabaseReplaced");for(let r=0;r<N.length;r++){const a=N[r],i=C(o.appName,a),m=me(a,"deploy"),d=pe(a,"deploy");if(!b.has(i)){t.onStepStart?.(m,d,r,L),t.onLog?.(`Skipping ${a} \u2014 no changes detected`,"info"),t.onStepComplete?.(m,d,"skipped",r,L);continue}const y=await W(e.assertLeaseForStack,i,e.abortSignal);if(y!==void 0)return await I(),t.onError?.(y),l(y);const g=Xe(N,r,o.appName,b);if(g.length>=2){const T=await he({hashService:n.hashService,cdkOutPath:O,stackNames:g.map(Y=>C(o.appName,Y)),detectionHashes:p.currentHashes,approvalGated:U});if(!T.success)return await I(),t.onError?.(T.error),l(T.error);const ge=await et(g,o,n,B,t,r,L,p,$,x);if(!ge.success)return await I(),l(await Se(n.awsProvider,{stackNames:g.map(Y=>C(o.appName,Y)),appName:o.appName,originalError:ge.error,cfnService:n.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));r+=g.length-1;continue}const c=await rt(a,e,n,o,t,p.hasDockerfile);if(c!==null&&!c.success)return await I(),l(c.error);c!==null&&c.success&&(le=c.data);const u=c!==null&&c.success?c.data.contentHashTagsByService:{},k=Rt(u);if(c!==null){const T=await W(e.assertLeaseForStack,i,e.abortSignal);if(T!==void 0)return await I(),t.onError?.(T),l(T)}const w=await he({hashService:n.hashService,cdkOutPath:O,stackNames:[i],detectionHashes:p.currentHashes,approvalGated:U});if(!w.success)return await I(),t.onError?.(w.error),l(w.error);const f=await tt(a,n,B,t,r,L,$,k!==void 0||e.abortSignal!==void 0?{...k!==void 0?{parameters:k}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}:void 0);if(!f.success)return await I(),l(await Se(n.awsProvider,{stackNames:[i],appName:o.appName,originalError:f.error,cfnService:n.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));a===R.COMPUTE&&(de=await nt(o,n,t,u,e.abortSignal));const S=p.currentHashes.get(i);S&&x.set(i,S)}if(await I(),x.size>0){const r=await n.hashService.updateStateAfterDeploy(o.path,x);if(!r.success){const a=h(r.error.message);F.debug(j,"Failed to update state file",{error:a}),t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy unchanged stacks: ${a}`,"warn")}}const ue=await n.stackService.resolveWebsiteUrl(o.appName);ue&&($.websiteUrl=ue);const De=await ut(n,o.appName,le,t,O,de,e.abortSignal);return await Et(n.awsProvider,{stackNames:[...b],appName:o.appName,onLog:P((r,a)=>t.onLog?.(r,a),"onLog"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}).catch(r=>{F.debug(j,"Forget completion sweep failed",{error:h(Q(r))})}),A({target:o.appName,deploymentType:"application",outputs:Object.keys($).length>0?$:void 0,artefacts:De,durationMs:Date.now()-E})}P(wr,"deployApplication");export{wr as deployApplication,we as emitStackTargets};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var B=Object.defineProperty;var
|
|
2
|
-
`);return
|
|
1
|
+
var B=Object.defineProperty;var c=(e,r)=>B(e,"name",{value:r,configurable:!0});import{join as O}from"node:path";import{success as E,failure as P}from"@fjall/generator";import{getErrorMessage as R,maskSensitiveOutput as y}from"@fjall/util";import{parseLambdaDockerEntriesFromManifest as $}from"@fjall/util/manifest";import{isAborted as L}from"../../aws/organisations/types.js";import{APPLICATION_STACKS as b,getApplicationStackName as w,getApplicationStepName as N,getApplicationStepId as C,PARALLEL_DEPLOY_GROUPS as v}from"../../types/operations.js";import{emitProgress as T}from"../../services/supporting/helpers.js";import{forwardOutput as x,forwardResourceProgress as j}from"../contextHelpers.js";import{createEcsDeploymentTail as I}from"./ecsDeploymentTail.js";import{emptyBuildProducts as _,runDockerBuild as M}from"./dockerBuildHelper.js";import{runWelcomeImageSetup as U}from"./welcomeImageHelper.js";import{withStepLifecycle as F}from"../stepLifecycle.js";function te(e){const r=new Set;for(const i of e.deployOrder){const s=w(e.appName,i),n=e.stackChanges.get(s)??!0,l=i===b.COMPUTE&&e.computeBuildPossible;(n||e.force||l)&&r.add(s)}return r}c(te,"getStackNamesToDeploy");function re(e){return e.stackNamesToDeploy.has(w(e.appName,b.COMPUTE))&&e.hasDockerProvider&&e.hasDockerfile}c(re,"willRunDockerBuild");function oe(e,r,i,s){const n=new Set(v.PHASE_2.stacks),l=[];for(let o=r;o<e.length&&n.has(e[o]);o++)l.push(e[o]);if(l.length<2)return[];const f=l.filter(o=>s.has(w(i,o)));return f.length>=2?f:[]}c(oe,"getParallelPhase2Stacks");async function ne(e,r,i,s,n,l,f,o,g,m){for(let t=0;t<e.length;t++){const u=e[t],a=C(u,"deploy"),p=N(u,"deploy");n.onStepStart?.(a,p,l+t,f)}T(n,"Deploying infrastructure in parallel\u2026"),n.onParallelPhaseStart?.(e,"Storage and database resources (parallel)");const d=await i.stackService.deployStacksInParallel(e,s,{onOutput:x(n),onResourceProgress:c((t,u)=>{n.onResourceProgress?.(t),u&&n.onParallelStackResourceProgress?.(u,t)},"onResourceProgress"),onStackComplete:c((t,u,a,p)=>{const h=C(t,"deploy"),A=N(t,"deploy"),D=l+e.indexOf(t),k=L(i.abortSignal);n.onStepComplete?.(h,A,u?"completed":k?"cancelled":"error",D,f),!u&&p&&!k&&n.onError?.(new Error(y(p.message)))},"onStackComplete")});if(!d.success)return n.onParallelPhaseComplete?.([]),P(d.error);const S=d.data.filter(t=>!t.success);if(n.onParallelPhaseComplete?.(d.data.map(t=>({stack:t.stack,success:t.success,error:t.error}))),S.length>0){const t=S.map(a=>a.stack).join(", "),u=S.map(a=>`${a.stack}: ${y(a.error?.message??"Unknown error")}`).join(`
|
|
2
|
+
`);return P(new Error(`Failed to deploy stacks: ${t}
|
|
3
3
|
|
|
4
|
-
${
|
|
4
|
+
${u}`))}for(const t of d.data){if(t.success&&t.outputs)for(const[p,h]of Object.entries(t.outputs))g[p]=String(h);const u=w(r.appName,t.stack),a=o.currentHashes.get(u);a&&m.set(u,a)}return E(void 0)}c(ne,"deployParallelPhase");async function ie(e,r,i,s,n,l,f,o){const g=C(e,"deploy"),m=N(e,"deploy");return F(s,{stepId:g,stepName:m,stepIndex:n,totalSteps:l},async()=>{const d=o?.abortSignal??r.abortSignal,S=I({ecsService:r.ecsService,callbacks:s,...d!==void 0&&{abortSignal:d}}),t=j(s);let u=!1;try{const a=await r.stackService.deployStack(e,i,{onOutput:x(s),onResourceProgress:c(p=>{S.observeResourceEvent(p),t(p)},"onResourceProgress")},o?.parameters!==void 0||o?.abortSignal!==void 0?{...o?.parameters!==void 0?{parameters:o.parameters}:{},...o?.abortSignal!==void 0?{abortSignal:o.abortSignal}:{}}:void 0);if(u=a.success,!a.success)return{kind:"error",error:a.error};if(a.data.outputs)for(const[p,h]of Object.entries(a.data.outputs))f[p]=String(h);return{kind:"completed",data:void 0}}finally{await S.finalise({deploySucceeded:u}).catch(a=>{T(s,`ECS deployment tail did not finalise cleanly: ${y(R(a))}`,"warning")})}},r.abortSignal)}c(ie,"deployStackSequential");async function se(e,r,i,s,n,l){if(e!==b.COMPUTE||!r.dockerProvider)return null;if(l){const o=await M(r,i,s,n);return o.success?E(o.data):P(o.error)}const f=await U(r,i,s,n);return f.success?E(_()):P(f.error)}c(se,"runDockerPreCompute");async function ae(e,r,i,s,n){if(Object.keys(s).length===0)return{};const l=O(e.path,"cdk.out"),o=$(l).filter(m=>s[m.imageKey]!==void 0);if(o.length===0)return{};const g={};for(const m of o){if(L(n)){i.onLog?.(`Skipping the Lambda version publish for '${m.name}' \u2014 the deployment was cancelled. The function's $LATEST code is up to date; only the published-version record is affected.`,"warn");continue}const d=await r.lambdaService.publishVersion(m.name,n);if(!d.success){i.onLog?.(`Published image for Lambda '${m.name}', but publishing a new version failed: ${y(d.error.message)}. The function's $LATEST code is up to date; only the published-version record is affected.`,"warn");continue}g[m.name]=d.data}return g}c(ae,"runLambdaVersionPublish");function ue(e){return{onBuildStart:c(r=>{e.onOpenNextBuildStart?.(),e.onLog?.(`${r} build started`,"info")},"onBuildStart"),onBuildProgress:c((r,i)=>{e.onOpenNextProgress?.(i)},"onBuildProgress"),onBuildComplete:c(r=>{e.onOpenNextBuildComplete?.(),e.onLog?.(`${r} build complete`,"info")},"onBuildComplete"),onBuildError:c((r,i)=>{e.onOpenNextBuildError?.(i)},"onBuildError")}}c(ue,"createBuildCallbacks");export{ue as createBuildCallbacks,ne as deployParallelPhase,ie as deployStackSequential,oe as getParallelPhase2Stacks,te as getStackNamesToDeploy,se as runDockerPreCompute,ae as runLambdaVersionPublish,re as willRunDockerBuild};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var s=Object.defineProperty;var i=(
|
|
1
|
+
var s=Object.defineProperty;var i=(r,o)=>s(r,"name",{value:o,configurable:!0});import{success as m,failure as d}from"@fjall/generator";import{toKebab as u,toPascalCase as f}from"@fjall/util";import{buildCacheRepositoryName as y}from"@fjall/util/docker";import{SCHEMA_GATE_ECR_REPO_NAME as $}from"@fjall/util/migration";import{MAX_INLINE_POLICY_CHARS as n}from"./buildSecretSession.js";const S=["cloudformation:CreateStack","cloudformation:UpdateStack","cloudformation:DeleteStack","cloudformation:CreateChangeSet","cloudformation:ExecuteChangeSet","cloudformation:DeleteChangeSet","cloudformation:CancelUpdateStack","cloudformation:ContinueUpdateRollback","cloudformation:RollbackStack","cloudformation:SetStackPolicy","cloudformation:UpdateTerminationProtection"],C=["ecr:PutImage","ecr:InitiateLayerUpload","ecr:UploadLayerPart","ecr:CompleteLayerUpload","ecr:BatchDeleteImage","ecr:DeleteRepository","ecr:SetRepositoryPolicy","ecr:DeleteRepositoryPolicy"];function g(r){const{region:o,accountId:e,partition:t}=r,l=f(r.appName),c=u(r.appName),p=[{Sid:"FjallDeployInheritAdmin",Effect:"Allow",Action:"*",Resource:"*"},{Sid:"FjallDeployDenyForeignStackMutation",Effect:"Deny",Action:S,NotResource:[`arn:${t}:cloudformation:${o}:${e}:stack/${l}*/*`,`arn:${t}:cloudformation:${o}:${e}:stack/CDKToolkit/*`]},{Sid:"FjallDeployDenyForeignEcrMutation",Effect:"Deny",Action:C,NotResource:[`arn:${t}:ecr:${o}:${e}:repository/${c}`,`arn:${t}:ecr:${o}:${e}:repository/${y(c)}`,`arn:${t}:ecr:${o}:${e}:repository/cdk-*`,`arn:${t}:ecr:${o}:${e}:repository/${$}`]}],a=JSON.stringify({Version:"2012-10-17",Statement:p});return a.length>n?d(new Error(`Deploy session policy is ${a.length} chars, exceeding the ${n}-char AWS inline-policy limit.`)):m(a)}i(g,"buildDeploySessionPolicy");export{g as buildDeploySessionPolicy};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ResourceEvent } from "@fjall/util/aws";
|
|
2
|
+
import type { DeployCallbacks } from "../../types/callbacks.js";
|
|
3
|
+
import type { EcsService } from "../../services/infrastructure/EcsService.js";
|
|
4
|
+
export declare const ECS_TAIL_POLL_INTERVAL_MS = 15000;
|
|
5
|
+
/**
|
|
6
|
+
* The unstick guidance printed when a stack reaches UPDATE_ROLLBACK_FAILED.
|
|
7
|
+
* Deliberately generic AWS remediation — deploy-core ships to customers, so
|
|
8
|
+
* no fjall-internal references belong here.
|
|
9
|
+
*/
|
|
10
|
+
export declare const UPDATE_ROLLBACK_FAILED_RUNBOOK: string;
|
|
11
|
+
export interface EcsDeploymentTail {
|
|
12
|
+
/** Feed every CFN resource event here; ECS service events start supervision. */
|
|
13
|
+
observeResourceEvent(event: ResourceEvent): void;
|
|
14
|
+
/**
|
|
15
|
+
* Stop polling, take a final snapshot per supervised service, and emit
|
|
16
|
+
* `onECSComplete`. Never throws; safe to call when nothing was supervised.
|
|
17
|
+
* Services where no fresh deployment was ever adopted (e.g. a
|
|
18
|
+
* desiredCount-only update that creates no new deployment) emit nothing.
|
|
19
|
+
* When the last observation is non-terminal and no final snapshot is
|
|
20
|
+
* available, `deploySucceeded` decides the verdict — CloudFormation only
|
|
21
|
+
* reports a successful stack once the service stabilised.
|
|
22
|
+
*/
|
|
23
|
+
finalise(outcome?: {
|
|
24
|
+
deploySucceeded?: boolean;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface EcsDeploymentTailDeps {
|
|
28
|
+
ecsService: EcsService;
|
|
29
|
+
callbacks: DeployCallbacks;
|
|
30
|
+
abortSignal?: AbortSignal;
|
|
31
|
+
/** Test seam — production callers use the default. */
|
|
32
|
+
pollIntervalMs?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Observe-only ECS supervision for the full CFN deploy path (the seam the
|
|
36
|
+
* callback vocabulary at `types/callbacks.ts` reserves as "the future
|
|
37
|
+
* full-deploy ECS-tail step"). While CloudFormation drives a rolling update,
|
|
38
|
+
* this tail polls the service's PRIMARY deployment, counts distinct stopped
|
|
39
|
+
* tasks started by it, and narrates stopped-task forensics (`stoppedReason`,
|
|
40
|
+
* container exit codes) that are otherwise invisible until someone opens the
|
|
41
|
+
* console. It never cancels anything — CFN remains the deploy authority.
|
|
42
|
+
*
|
|
43
|
+
* Verdict semantics: `onECSComplete.success` reports the SUPERVISED
|
|
44
|
+
* deployment's outcome. A circuit-breaker or CFN rollback that replaces the
|
|
45
|
+
* supervised deployment is a failure verdict even though the service ends up
|
|
46
|
+
* stable on the old revision.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createEcsDeploymentTail(deps: EcsDeploymentTailDeps): EcsDeploymentTail;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var B=Object.defineProperty;var d=(o,s)=>B(o,"name",{value:s,configurable:!0});import{logger as u}from"@fjall/util/logger";import{getErrorMessage as I,maskSensitiveOutput as f}from"@fjall/util";import{isAborted as _}from"../../aws/organisations/types.js";import{sleepAbortable as U}from"../../util/sleepAbortable.js";const p="EcsDeploymentTail",z="AWS::ECS::Service",K="AWS::CloudFormation::Stack",G=new Set(["CREATE_IN_PROGRESS","UPDATE_IN_PROGRESS"]),Y=15e3,j=3e4,W=["CloudFormation entered UPDATE_ROLLBACK_FAILED \u2014 the stack is wedged and will refuse further updates until the rollback completes.","To unstick it:"," 1. Find the resource(s) that failed to roll back: aws cloudformation describe-stack-events --stack-name <stack> (look for UPDATE_ROLLBACK_FAILED resource events and their status reasons)."," 2. Fix the underlying cause if possible (an ECS service that cannot stabilise usually means the previous image cannot boot \u2014 check stopped-task reasons above)."," 3. Resume the rollback: aws cloudformation continue-update-rollback --stack-name <stack> [--resources-to-skip <logical-ids>]."," 4. Reference: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html#troubleshooting-errors-update-rollback-failed"].join(`
|
|
2
|
+
`);function Z(o){const{ecsService:s,callbacks:i,abortSignal:c}=o,b=o.pollIntervalMs??Y,S=new Map,h=new AbortController,D=c!==void 0?AbortSignal.any([c,h.signal]):h.signal;let E=!1,N=!1;const C=d(e=>{i.onECSProgress?.(f(e))},"emitProgress"),$=d((e,t)=>t.createdAt!==void 0&&t.createdAt.getTime()>=e.updateStartedAt.getTime()-j,"isFreshDeployment"),O=d(async e=>{const t=await s.describeServices(e.clusterName,[e.serviceArn],D);if(!t.success){u.debug(p,"DescribeServices poll failed (transient, observing)",{serviceArn:e.serviceArn,error:f(t.error.message)});return}const r=t.data[0];if(r===void 0)return;const n=r.deployments?.find(l=>l.status==="PRIMARY");if(n?.id!==void 0&&(e.targetDeploymentId===void 0?$(e,n)&&(e.targetDeploymentId=n.id,e.targetTaskDefinitionArn=n.taskDefinition):n.id!==e.targetDeploymentId&&n.id!==e.replacedByDeploymentId&&(e.replacedByDeploymentId=n.id,C(`${e.serviceName}: ECS replaced the in-flight deployment \u2014 now rolling out ${w(n.taskDefinition)}`)),(n.id===e.targetDeploymentId||n.id===e.replacedByDeploymentId)&&n.rolloutState!==void 0)){const k=`${n.id}:${n.rolloutState}`;if(k!==e.lastNarratedRollout){e.lastNarratedRollout=k;const A=n.rolloutStateReason!==void 0&&n.rolloutStateReason!==""?` (${n.rolloutStateReason})`:"";C(`${e.serviceName}: rollout ${n.rolloutState}${A} \u2014 running ${n.runningCount??0}/${n.desiredCount??0}`),i.onECSUpdate?.(n.rolloutState,e.serviceName)}n.id===e.targetDeploymentId&&(e.lastRolloutState=n.rolloutState,n.rolloutStateReason!==void 0&&n.rolloutStateReason!==""&&(e.lastRolloutReason=n.rolloutStateReason))}if(e.targetDeploymentId===void 0)return;const R=await s.listStoppedTasks(e.clusterName,e.targetDeploymentId,D);if(!R.success){u.debug(p,"ListTasks poll failed (transient, observing)",{serviceArn:e.serviceArn,error:f(R.error.message)});return}const a=R.data.filter(l=>!e.stoppedTaskArns.has(l));if(a.length===0&&e.pendingForensicArns.size===0)return;for(const l of a)e.stoppedTaskArns.add(l);const y=e.pendingForensicArns.size>0,v=[...e.pendingForensicArns,...a];let m=!1;const T=await s.describeTasks(e.clusterName,v,D);if(T.success)m=y,e.pendingForensicArns.clear(),T.data.length>0&&(e.latestForensic=T.data[T.data.length-1]);else{for(const l of v)e.pendingForensicArns.add(l);u.debug(p,"DescribeTasks poll failed (transient, observing)",{serviceArn:e.serviceArn,error:f(T.error.message)})}if(a.length===0&&!m)return;const g=e.latestForensic!==void 0?` \u2014 latest: ${F(e.latestForensic)}`:"";C(`${e.serviceName}: ${e.stoppedTaskArns.size} task(s) from the new revision stopped since the update began${g}`)},"pollOnce"),P=d(async e=>{for(;!E&&!_(D);){try{await O(e)}catch(t){u.debug(p,"Tail poll threw (transient, observing)",{serviceArn:e.serviceArn,error:f(I(t))})}await U(b,D)}},"runTailLoop"),L=d((e,t)=>{const r=V(e);if(r===void 0){u.debug(p,"Cannot derive cluster from legacy-format service ARN; skipping tail",{serviceArn:e});return}const n={serviceArn:e,clusterName:r.clusterName,serviceName:r.serviceName,startedAtMs:Date.now(),updateStartedAt:t,stoppedTaskArns:new Set,pendingForensicArns:new Set,loop:Promise.resolve()};n.loop=P(n),S.set(e,n),u.debug(p,"ECS deployment tail started",{serviceArn:e,clusterName:r.clusterName})},"startTail");return{observeResourceEvent(e){if(!E){if(e.resourceType===z&&G.has(e.status)&&e.physicalId!==void 0&&e.physicalId!==""&&!S.has(e.physicalId)){L(e.physicalId,e.timestamp);return}e.resourceType===K&&e.status==="UPDATE_ROLLBACK_FAILED"&&!N&&(N=!0,i.onOutput?.(`${W}
|
|
3
|
+
`))}},async finalise(e){if(E)return;E=!0,h.abort();const t=e?.deploySucceeded===!0;await Promise.all([...S.values()].map(async r=>{await r.loop.catch(n=>{u.debug(p,"Tail loop rejected during finalise",{serviceArn:r.serviceArn,error:f(I(n))})}),await M(r,t).catch(n=>{u.debug(p,"Tail completion emission failed",{serviceArn:r.serviceArn,error:f(I(n))})})}))}};async function M(e,t){if(e.targetDeploymentId===void 0){u.debug(p,"No fresh deployment was ever adopted; skipping ECS completion event",{serviceArn:e.serviceArn});return}let r,n,R,a=e.lastRolloutState,y=e.lastRolloutReason;if(!_(c)){const l=await s.describeServices(e.clusterName,[e.serviceArn],c);if(l.success&&l.data[0]!==void 0){const k=l.data[0];r=k.taskDefinition,n=k.runningCount,R=k.desiredCount;const A=k.deployments?.find(x=>x.status==="PRIMARY");A?.id!==void 0&&(A.id===e.targetDeploymentId?A.rolloutState!==void 0&&(a=A.rolloutState,y=A.rolloutStateReason??y):e.replacedByDeploymentId===void 0&&(e.replacedByDeploymentId=A.id))}else l.success||u.debug(p,"Final DescribeServices snapshot failed",{serviceArn:e.serviceArn,error:f(l.error.message)})}const v=e.replacedByDeploymentId!==void 0;let m;v?m=!1:a==="COMPLETED"?m=!0:a==="FAILED"?m=!1:m=t,r!==void 0&&e.targetTaskDefinitionArn!==void 0&&r!==e.targetTaskDefinitionArn&&C(`${e.serviceName}: service settled on ${w(r)}, not the deployment's target ${w(e.targetTaskDefinitionArn)} \u2014 ECS rolled the service back`);const g=[];m||(y!==void 0?g.push(y):v||g.push(`rollout state ${a??"unknown"} when monitoring ended`),v&&g.push("ECS replaced the in-flight deployment before it completed"),e.stoppedTaskArns.size>0&&g.push(`${e.stoppedTaskArns.size} distinct task(s) from the new revision stopped`),e.latestForensic!==void 0&&g.push(`latest: ${F(e.latestForensic)}`)),i.onECSComplete?.({serviceName:e.serviceName,serviceArn:e.serviceArn,success:m,taskDefinitionArn:r??e.targetTaskDefinitionArn??"unknown",durationMs:Date.now()-e.startedAtMs,...g.length>0&&{reason:f(g.join("; "))},...n!==void 0&&{finalRunningCount:n},...R!==void 0&&{finalDesiredCount:R},...a!==void 0&&{rolloutState:a},...v&&{replaced:!0},...e.stoppedTaskArns.size>0&&{stoppedTaskCount:e.stoppedTaskArns.size},...e.latestForensic?.stopCode!==void 0&&{stopCode:e.latestForensic.stopCode},...e.latestForensic?.stoppedReason!==void 0&&{stoppedReason:f(e.latestForensic.stoppedReason)}})}}d(Z,"createEcsDeploymentTail");function V(o){const s=":service/",i=o.indexOf(s);if(i===-1)return;const b=o.slice(i+s.length).split("/");if(b.length<2)return;const S=b[0],h=b[1];if(!(S===void 0||S===""||h===void 0||h===""))return{clusterName:S,serviceName:h}}d(V,"parseServiceArn");function w(o){if(o===void 0)return"unknown revision";const s=o.split("/"),i=s[s.length-1];return i!==void 0&&i!==""?i:o}d(w,"shortTaskDefinition");function F(o){const s=o.containers.filter(c=>c.exitCode!==void 0).map(c=>`${c.name??"container"} exit ${c.exitCode}`).join(", "),i=o.stoppedReason??o.stopCode??"no stopped reason recorded";return s!==""?`${i} (${s})`:i}d(F,"formatForensic");export{Y as ECS_TAIL_POLL_INTERVAL_MS,W as UPDATE_ROLLBACK_FAILED_RUNBOOK,Z as createEcsDeploymentTail};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Result } from "@fjall/generator";
|
|
2
|
+
import type { AwsProvider } from "../../aws/AwsProvider.js";
|
|
3
|
+
export interface EnsureSchemaGateImageParams {
|
|
4
|
+
awsProvider: AwsProvider;
|
|
5
|
+
/** The synthesised assembly directory containing `fjall-manifest.json`. */
|
|
6
|
+
cdkOutPath: string;
|
|
7
|
+
onLog?: (message: string, level: "info" | "warn") => void;
|
|
8
|
+
abortSignal?: AbortSignal;
|
|
9
|
+
/** Test seam — production callers omit it (global fetch). */
|
|
10
|
+
fetchFn?: typeof fetch;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Ensure every schema-gate image tag the manifest declares exists in the
|
|
14
|
+
* target account's private ECR (`fjall/schema-gate`) before any task
|
|
15
|
+
* definition referencing it ships. Tags are recorded only for DEFAULT-image
|
|
16
|
+
* gates — a BYO `schemaGate.image` records nothing, so its availability stays
|
|
17
|
+
* the author's responsibility.
|
|
18
|
+
*
|
|
19
|
+
* Present tag → no-op (one DescribeImages). Absent → create the repository
|
|
20
|
+
* if needed (IMMUTABLE — release-pinned tags must never be repointed), then
|
|
21
|
+
* mirror the tag from the public repository via the OCI distribution API
|
|
22
|
+
* (anonymous pull) and the ECR SDK (layer upload + PutImage), preserving
|
|
23
|
+
* digests end-to-end so the multi-arch index survives byte-identical.
|
|
24
|
+
*
|
|
25
|
+
* Fail-closed: any failure refuses the deploy BEFORE CloudFormation mutates —
|
|
26
|
+
* shipping a task definition whose gate image cannot be pulled would stop
|
|
27
|
+
* every task at provisioning with no CFN-visible cause.
|
|
28
|
+
*
|
|
29
|
+
* Failure messages are pre-masked at construction — callers may surface
|
|
30
|
+
* `error.message` to log/callback sinks without re-masking.
|
|
31
|
+
*/
|
|
32
|
+
export declare function ensureSchemaGateImage(params: EnsureSchemaGateImageParams): Promise<Result<void>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var L=Object.defineProperty;var d=(e,t)=>L(e,"name",{value:t,configurable:!0});import{createHash as N}from"node:crypto";import{ECRClient as O,BatchCheckLayerAvailabilityCommand as G,CompleteLayerUploadCommand as D,CreateRepositoryCommand as H,DescribeImagesCommand as j,InitiateLayerUploadCommand as U,PutImageCommand as F,UploadLayerPartCommand as Y}from"@aws-sdk/client-ecr";import{success as S,failure as E}from"@fjall/generator";import{getErrorMessage as w,maskSensitiveOutput as p}from"@fjall/util";import{logger as _}from"@fjall/util/logger";import{parseSchemaGateImageTagsFromManifest as z}from"@fjall/util/manifest";import{SCHEMA_GATE_ECR_REPO_NAME as m,SCHEMA_GATE_PUBLIC_IMAGE_REPO as h}from"@fjall/util/migration";import{composeSdkAbortSignal as l,extractErrorName as $,isAborted as b}from"../../aws/organisations/types.js";const R="SchemaGateImage",k=h.indexOf("/"),g=h.slice(0,k),T=h.slice(k+1),s='The deploy was refused before any stack changed. Fix the cause and re-run, or set schemaGate: { image: "<uri>" } to bring your own gate image, or schemaGate: { materialise: false } to disable the gate container.',J=["application/vnd.oci.image.index.v1+json","application/vnd.oci.image.manifest.v1+json","application/vnd.docker.distribution.manifest.list.v2+json","application/vnd.docker.distribution.manifest.v2+json"].join(", "),V=new Set(["application/vnd.oci.image.index.v1+json","application/vnd.docker.distribution.manifest.list.v2+json"]),W=10*1024*1024,P=12e4;class r extends Error{static{d(this,"SchemaGateImageError")}}function y(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}d(y,"isRecord");async function le(e){const t=z(e.cdkOutPath);if(t.outcome==="manifest-unreadable")return E(new r(`Cannot determine the assembly's schema-gate image tags: ${p(t.reason)}. Re-run the build to regenerate the assembly, or remove the corrupt cdk.out and redeploy.`));const o=t.tags;if(o.length===0)return S(void 0);const a=e.awsProvider.getClient(O),n=e.fetchFn??fetch;try{for(const i of o){if(b(e.abortSignal))throw new r(`Aborted before ensuring schema-gate image '${m}:${i}'`);if(await X(a,i,e.abortSignal)){_.debug(R,"Schema-gate image already present",{tag:i});continue}e.onLog?.(`Schema-gate image ${m}:${i} is not in this account's ECR \u2014 mirroring it from ${h} (one-off per engine version)`,"info"),await Z(a,e.abortSignal),await q(a,n,i,e.abortSignal),e.onLog?.(`Mirrored schema-gate image ${m}:${i}`,"info")}return S(void 0)}catch(i){return i instanceof r?E(i):E(new Error(`Could not ensure the schema-gate image in this account's ECR: ${p(w(i))}. ${s}`))}}d(le,"ensureSchemaGateImage");async function X(e,t,o){try{return await e.send(new j({repositoryName:m,imageIds:[{imageTag:t}]}),{abortSignal:l(o)}),!0}catch(a){const n=$(a);if(n==="ImageNotFoundException"||n==="RepositoryNotFoundException")return!1;throw new r(`Could not check for schema-gate image '${m}:${t}': ${p(w(a))}. ${s}`)}}d(X,"isTagPresent");async function Z(e,t){try{await e.send(new H({repositoryName:m,imageScanningConfiguration:{scanOnPush:!0},imageTagMutability:"IMMUTABLE"}),{abortSignal:l(t)}),_.debug(R,"Created schema-gate repository",{repositoryName:m})}catch(o){if($(o)!=="RepositoryAlreadyExistsException")throw new r(`Could not create schema-gate repository '${m}': ${p(w(o))}. ${s}`)}}d(Z,"ensureGateRepository");async function q(e,t,o,a){const n=await K(t,a),i=await v(t,n,o,a);if(V.has(i.mediaType))for(const c of ee(i.parsed,o)){if(b(a))throw new r(`Aborted while mirroring schema-gate image '${m}:${o}'`);const f=await v(t,n,c,a);await x(e,t,n,f.parsed,o,a),await M(e,f.raw,f.mediaType,{imageDigest:c},a)}else await x(e,t,n,i.parsed,o,a);await M(e,i.raw,i.mediaType,{imageTag:o},a)}d(q,"mirrorTag");async function K(e,t){const o=`https://${g}/token/?service=${g}&scope=repository:${T}:pull`,a=await e(o,{signal:l(t)});if(!a.ok)throw new r(`Could not obtain an anonymous pull token from ${g}: HTTP ${a.status}. ${s}`);const n=await a.json();if(!y(n)||typeof n.token!="string"||n.token==="")throw new r(`The ${g} token endpoint returned no usable token. ${s}`);return n.token}d(K,"fetchPublicPullToken");async function v(e,t,o,a){const n=await e(`https://${g}/v2/${T}/manifests/${o}`,{headers:{Authorization:`Bearer ${t}`,Accept:J},signal:l(a)});if(!n.ok)throw new r(`Could not fetch manifest '${o}' from ${h}: HTTP ${n.status}. ${s}`);const i=await n.text();o.startsWith("sha256:")&&B(Buffer.from(i),o,`manifest ${o}`);let c;try{c=JSON.parse(i)}catch{throw new r(`Manifest '${o}' from ${h} is not valid JSON. ${s}`)}if(!y(c))throw new r(`Manifest '${o}' from ${h} has an unexpected shape. ${s}`);const f=n.headers.get("content-type"),A=f!==null&&f!==""?f:typeof c.mediaType=="string"?c.mediaType:"";return{raw:i,mediaType:A,parsed:c}}d(v,"fetchPublicManifest");const Q=/^sha256:[0-9a-f]{64}$/;function C(e,t){if(!Q.test(e))throw new r(`A descriptor for '${h}:${t}' carries a malformed digest. ${s}`);return e}d(C,"assertDigestShape");function ee(e,t){if(!Array.isArray(e.manifests))throw new r(`The index manifest for '${h}:${t}' carries no child manifests. ${s}`);const o=[];for(const a of e.manifests){if(!y(a)||typeof a.digest!="string")throw new r(`The index manifest for '${h}:${t}' has a malformed child descriptor. ${s}`);o.push(C(a.digest,t))}return o}d(ee,"collectIndexChildDigests");function te(e,t){const o=[],a=e.config;if(!y(a)||typeof a.digest!="string")throw new r(`An image manifest for '${h}:${t}' has no config digest. ${s}`);if(o.push(C(a.digest,t)),!Array.isArray(e.layers))throw new r(`An image manifest for '${h}:${t}' has no layer list. ${s}`);for(const n of e.layers){if(!y(n)||typeof n.digest!="string")throw new r(`An image manifest for '${h}:${t}' has a malformed layer descriptor. ${s}`);o.push(C(n.digest,t))}return o}d(te,"collectBlobDigests");async function x(e,t,o,a,n,i){const c=te(a,n),f=await e.send(new G({repositoryName:m,layerDigests:c}),{abortSignal:l(i)}),A=new Set((f.layers??[]).filter(u=>u.layerAvailability==="AVAILABLE").map(u=>u.layerDigest));for(const u of c){if(b(i))throw new r(`Aborted while mirroring schema-gate image '${m}:${n}'`);if(A.has(u))continue;const I=await oe(t,o,u,i);B(I,u,`blob ${u}`),await ae(e,u,I,i)}}d(x,"mirrorImageBlobs");async function oe(e,t,o,a){const n=await e(`https://${g}/v2/${T}/blobs/${o}`,{headers:{Authorization:`Bearer ${t}`},signal:l(a,P)});if(!n.ok)throw new r(`Could not download blob ${o} from ${h}: HTTP ${n.status}. ${s}`);return new Uint8Array(await n.arrayBuffer())}d(oe,"fetchPublicBlob");function B(e,t,o){const a=`sha256:${N("sha256").update(e).digest("hex")}`;if(a!==t)throw new r(`Integrity check failed for ${o} from ${h}: downloaded content hashes to ${a}. Refusing to push it. ${s}`)}d(B,"assertDigestMatches");async function ae(e,t,o,a){const i=(await e.send(new U({repositoryName:m}),{abortSignal:l(a)})).uploadId;if(i===void 0)throw new r(`ECR returned no upload id for blob ${t}. ${s}`);let c=0;for(;c<o.length;){if(b(a))throw new r(`Aborted while uploading blob ${t} to '${m}'`);const f=Math.min(c+W,o.length);await e.send(new Y({repositoryName:m,uploadId:i,partFirstByte:c,partLastByte:f-1,layerPartBlob:o.subarray(c,f)}),{abortSignal:l(a,P)}),c=f}try{await e.send(new D({repositoryName:m,uploadId:i,layerDigests:[t]}),{abortSignal:l(a)})}catch(f){if($(f)!=="LayerAlreadyExistsException")throw new r(`Could not complete the upload of blob ${t}: ${p(w(f))}. ${s}`)}}d(ae,"uploadBlob");async function M(e,t,o,a,n){try{await e.send(new F({repositoryName:m,imageManifest:t,...o!==""?{imageManifestMediaType:o}:{},...a}),{abortSignal:l(n)})}catch(i){if($(i)!=="ImageAlreadyExistsException")throw new r(`Could not push a schema-gate manifest to '${m}': ${p(w(i))}. ${s}`)}}d(M,"putImage");export{le as ensureSchemaGateImage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.defineProperty;var l=(e,r)=>C(e,"name",{value:r,configurable:!0});import{success as p,failure as g}from"@fjall/generator";import{isApplicationOperation as y}from"../types/operations.js";import{isAborted as k}from"../aws/organisations/types.js";import{checkRegionEnabled as A,regionDisabledMessage as D}from"../aws/regions/regionOptStatus.js";import{createDeployServices as E}from"./serviceFactory.js";import{resolveOperation as F}from"./resolveOperation.js";import{classifyDeployFailure as S}from"./failure/classifyFailure.js";import{attachDeploymentFailure as O}from"./failure/deploymentFailureAttachment.js";import{deployApplication as h}from"./application/applicationDeploy.js";import{deployOrganisation as M}from"./organisation/organisationDeploy.js";async function $(e){const r=Date.now(),u=await A(e.awsCredentials.region,e.awsCredentials,e.abortSignal);if(u==="disabled"){const t=new Error(D(e.awsCredentials.region));return e.callbacks.onError?.(t),g(t)}u==="enabling"&&e.callbacks.onProgress?.({type:"warning",message:`Region ${e.awsCredentials.region} is still activating (opt-in status ENABLING); the deploy may fail until activation completes.`});let i,s;const b=e.callbacks.onFailureAnalysis,m=e.callbacks.onECSComplete,c={...e,callbacks:{...e.callbacks,onFailureAnalysis:l(t=>{i=t,b?.(t)},"onFailureAnalysis"),onECSComplete:l(t=>{t.success||(s=t),m?.(t)},"onECSComplete")}},d=E(c),n=await F(e.target,e.workingDirectory);if(!n.success)return e.callbacks.onError?.(n.error),n;const a=n.data,w=y(a)?"application":"organisation",o=y(a)?await h(c,d,a):await M(c,d,a);if(k(e.abortSignal))return p({target:e.target,deploymentType:w,cancelled:!0,artefacts:[],durationMs:Date.now()-r});if(!o.success){const t=S({error:o.error,...i!==void 0&&{analysis:i},...s!==void 0&&{ecsFailure:s}});return e.callbacks.onDeploymentFailure?.(t),g(O(o.error,t))}const f=i!==void 0&&o.data.failureAnalysis===void 0?{...o.data,failureAnalysis:i}:o.data;return p({...f,...f.durationMs===void 0?{durationMs:Date.now()-r}:{}})}l($,"deploy");export{$ as deploy};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic terminal-failure classifier — maps the structured sources the
|
|
3
|
+
* engine already holds at the moment of failure (CFN failure analysis, ECS
|
|
4
|
+
* stopped-task forensics, the raw terminal error) onto the canonical
|
|
5
|
+
* `DeploymentFailure` record. Design:
|
|
6
|
+
* aiDocs/designs/2026-08-10-deployment-failure-taxonomy.md § 4.
|
|
7
|
+
*
|
|
8
|
+
* Classification happens HERE, where `category`/`stopCode`/`rolloutState`
|
|
9
|
+
* still exist as fields — never by regex over prose at render time (the
|
|
10
|
+
* design's explicitly rejected alternative). Everything dynamic is masked
|
|
11
|
+
* before it is bounded (mask-then-truncate).
|
|
12
|
+
*/
|
|
13
|
+
import { type DeploymentFailure, type DeploymentFailurePhase } from "@fjall/util";
|
|
14
|
+
import { type FailureAnalysis } from "@fjall/util/aws";
|
|
15
|
+
import type { ECSCompleteEvent } from "../../types/events.js";
|
|
16
|
+
/**
|
|
17
|
+
* Bump when a mapping changes meaning — stored on every record so persisted
|
|
18
|
+
* rows can be re-classified offline.
|
|
19
|
+
*/
|
|
20
|
+
export declare const DEPLOYMENT_FAILURE_CLASSIFIER_VERSION = "1";
|
|
21
|
+
/**
|
|
22
|
+
* Classify a failed CloudFormation stack operation from the analyser's
|
|
23
|
+
* structured output. The analysis nests verbatim (wire form) so no detail the
|
|
24
|
+
* monitor computed is lost.
|
|
25
|
+
*/
|
|
26
|
+
export declare function classifyFromFailureAnalysis(analysis: FailureAnalysis, stackName?: string): DeploymentFailure;
|
|
27
|
+
/**
|
|
28
|
+
* Classify a failed ECS stabilisation from the tail's structured completion
|
|
29
|
+
* event. Returns undefined for a successful event.
|
|
30
|
+
*/
|
|
31
|
+
export declare function classifyFromEcsCompletion(event: ECSCompleteEvent): DeploymentFailure | undefined;
|
|
32
|
+
export interface ClassifyUnclassifiedOptions {
|
|
33
|
+
/** The pipeline phase, when the caller knows where the failure occurred. */
|
|
34
|
+
phase?: Exclude<DeploymentFailurePhase, "unknown">;
|
|
35
|
+
/** Raw process/log output for excerpt extraction, when richer than the message. */
|
|
36
|
+
output?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The taxonomy's first-class fallback: nothing structured survived, so the
|
|
40
|
+
* record is bounded and located rather than classified — bare `unclassified`
|
|
41
|
+
* (phase unknown) or `unclassified.<phase>`, always carrying a masked excerpt
|
|
42
|
+
* window when the source outgrows `detail`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function classifyUnclassified(message: string, options?: ClassifyUnclassifiedOptions): DeploymentFailure;
|
|
45
|
+
export interface ClassifyDeployFailureInput {
|
|
46
|
+
/** The terminal Result error. */
|
|
47
|
+
error: Error;
|
|
48
|
+
/** The last FailureAnalysis the CFN monitor emitted, when a stack failed. */
|
|
49
|
+
analysis?: FailureAnalysis;
|
|
50
|
+
/** The last failed ECS completion event, when the tail observed one. */
|
|
51
|
+
ecsFailure?: ECSCompleteEvent;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Classify a terminal deploy failure from the richest structured source
|
|
55
|
+
* available: CFN analysis first, then ECS forensics, then the unclassified
|
|
56
|
+
* fallback over the error message.
|
|
57
|
+
*/
|
|
58
|
+
export declare function classifyDeployFailure(input: ClassifyDeployFailureInput): DeploymentFailure;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var h=Object.defineProperty;var n=(e,s)=>h(e,"name",{value:s,configurable:!0});import{DEPLOYMENT_FAILURE_LIMITS as i,DEPLOYMENT_FAILURE_SCHEMA_VERSION as u,extractErrorWindow as _,maskSensitiveOutput as k,toDeploymentFailureAnalysis as E}from"@fjall/util";const f="1",p="Deployment failed",C={"cfn.permissions":"AWS permissions blocked a resource change","cfn.validation":"AWS rejected a resource configuration","cfn.dependency":"A resource dependency was missing","cfn.limit":"An AWS service quota was exceeded","cfn.timeout":"A resource operation timed out","cfn.resource_create_failed":"A CloudFormation resource operation failed","ecs.circuit_breaker":"The new version failed to start and was rolled back","ecs.health_check_failed":"The new version failed its container health checks","ecs.task_start_failed":"Tasks from the new version kept stopping","ecs.stabilise_timeout":"The service did not stabilise in time"},T={permissions:"cfn.permissions",validation:"cfn.validation",dependency:"cfn.dependency",limit:"cfn.limit",network:"cfn.timeout",unknown:"cfn.resource_create_failed"},g={permissions:"customer_aws",dependency:"customer_aws",limit:"customer_aws",network:"customer_aws",validation:"indeterminate",unknown:"indeterminate"},F={"ecs.circuit_breaker":["Check the application logs for the stopped tasks \u2014 the new version could not start","The previously running version was left in place"],"ecs.health_check_failed":["Check the container health-check command and its start period","Confirm the application listens on its configured port"],"ecs.task_start_failed":["Check the application logs for the stopped tasks"],"ecs.stabilise_timeout":["Check the ECS service events for what kept the rollout from completing"]};function m(e){return C[e]??p}n(m,"failureTitle");function a(e,s,t){const c=k(e).trim(),o=c===""?t:c;return o.length>s?`${o.slice(0,s-1)}\u2026`:o}n(a,"boundText");function d(e,s){return e.length>s?e.slice(0,s):e}n(d,"boundIdentifier");function S(e,s){const t=e.rootCause.category,c=T[t],o=e.rootCause.resource,l={...o.logicalId!==""&&{logicalId:d(o.logicalId,i.resourceField)},...o.resourceType!==""&&{resourceType:d(o.resourceType,i.resourceField)},...s!==void 0&&s!==""&&{stackName:d(s,i.resourceField)}};return{schemaVersion:u,code:c,phase:"cloudformation",fault:g[t],title:m(c),detail:a(e.summary,i.detail,"A CloudFormation stack operation failed"),provider:{source:"cloudformation",message:a(e.rootCause.reason,i.providerMessage,"No status reason recorded")},...Object.keys(l).length>0&&{resource:l},remediation:e.remediation.filter(r=>r.trim()!=="").slice(0,i.remediationSteps).map(r=>r.length>i.remediationStep?`${r.slice(0,i.remediationStep-1)}\u2026`:r),analysis:E(e),classifierVersion:f}}n(S,"classifyFromFailureAnalysis");function y(e){if(e.success)return;let s,t;return e.stoppedReason!==void 0&&/health check/i.test(e.stoppedReason)?(s="ecs.health_check_failed",t="customer_code"):e.rolloutState==="FAILED"?(s="ecs.circuit_breaker",t="customer_code"):(e.stoppedTaskCount??0)>0?(s="ecs.task_start_failed",t="customer_code"):e.replaced===!0?(s="unclassified.ecs_stabilise",t="indeterminate"):(s="ecs.stabilise_timeout",t="indeterminate"),{schemaVersion:u,code:s,phase:"ecs_stabilise",fault:t,title:m(s),detail:a(e.reason??"",i.detail,`Service ${e.serviceName} did not reach a steady state`),provider:{source:"ecs",...e.stopCode!==void 0&&e.stopCode!==""&&{code:d(e.stopCode,i.providerCode)},message:a(e.stoppedReason??e.reason??"",i.providerMessage,"No stopped reason recorded")},remediation:[...F[s]??[]],classifierVersion:f}}n(y,"classifyFromEcsCompletion");function A(e,s={}){const t=s.phase??"unknown",c=s.phase===void 0?"unclassified":`unclassified.${s.phase}`,o=s.output??e,r=s.output!==void 0||o.length>i.detail?_(o):"";return{schemaVersion:u,code:c,phase:t,fault:"indeterminate",title:p,detail:a(e,i.detail,"The deployment failed"),...r!==""&&{excerpt:r},remediation:[],classifierVersion:f}}n(A,"classifyUnclassified");function L(e){if(e.analysis!==void 0)return S(e.analysis);if(e.ecsFailure!==void 0){const s=y(e.ecsFailure);if(s!==void 0)return s}return A(e.error.message)}n(L,"classifyDeployFailure");export{f as DEPLOYMENT_FAILURE_CLASSIFIER_VERSION,L as classifyDeployFailure,y as classifyFromEcsCompletion,S as classifyFromFailureAnalysis,A as classifyUnclassified};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attach/read the classified `DeploymentFailure` on a terminal error WITHOUT
|
|
3
|
+
* wrapping it in a new class — consumers branch on error identity
|
|
4
|
+
* (`instanceof DriftRepairAvailableError` drives the CLI repair offer), so a
|
|
5
|
+
* wrapper would silently break them. This is the Result-side twin of the
|
|
6
|
+
* `onDeploymentFailure` callback.
|
|
7
|
+
*/
|
|
8
|
+
import { type DeploymentFailure } from "@fjall/util";
|
|
9
|
+
/**
|
|
10
|
+
* Attach the record to the error, non-enumerably so serialisers and message
|
|
11
|
+
* formatters do not double-ship it. Returns the same error instance.
|
|
12
|
+
*/
|
|
13
|
+
export declare function attachDeploymentFailure<E extends Error>(error: E, failure: DeploymentFailure): E;
|
|
14
|
+
/**
|
|
15
|
+
* Read a previously attached record; undefined when absent or malformed
|
|
16
|
+
* (validated via the schema, never cast).
|
|
17
|
+
*/
|
|
18
|
+
export declare function getDeploymentFailure(error: unknown): DeploymentFailure | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var i=Object.defineProperty;var t=(e,n)=>i(e,"name",{value:n,configurable:!0});import{DeploymentFailureSchema as l}from"@fjall/util";const a="deploymentFailure";function d(e,n){return Object.defineProperty(e,a,{value:n,enumerable:!1,configurable:!0}),e}t(d,"attachDeploymentFailure");function f(e){if(typeof e!="object"||e===null||!(a in e))return;const n=e.deploymentFailure,u=l.safeParse(n);return u.success?u.data:void 0}t(f,"getDeploymentFailure");export{d as attachDeploymentFailure,f as getDeploymentFailure};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { deploy } from "./deploy.js";
|
|
2
2
|
export { destroy } from "./destroy.js";
|
|
3
|
-
export { restart, probeSecretsDrift } from "./restart/restartApplication.js";
|
|
4
|
-
export type { RestartParams, RestartResult, SecretsDriftProbeParams } from "./restart/restartApplication.js";
|
|
3
|
+
export { restart, probeSecretsDrift, probeServiceDeploymentStatus } from "./restart/restartApplication.js";
|
|
4
|
+
export type { RestartParams, RestartResult, SecretsDriftProbeParams, ServiceDeploymentStatus, ApplicationServiceStatus } from "./restart/restartApplication.js";
|
|
5
5
|
export { computeSecretsDrift, deriveStaleParameters, extractConsumedSsmParameters, ssmParameterNameFromValueFrom } from "./restart/secretsDrift.js";
|
|
6
6
|
export type { ApplicationSecretsDrift, ServiceSecretsDrift, StaleParameter, SecretsDriftServices } from "./restart/secretsDrift.js";
|
|
7
7
|
export { deployOrganisation } from "./organisation/organisationDeploy.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{deploy as t}from"./deploy.js";import{destroy as i}from"./destroy.js";import{restart as n,probeSecretsDrift as s}from"./restart/restartApplication.js";import{computeSecretsDrift as l,deriveStaleParameters as p,extractConsumedSsmParameters as m,ssmParameterNameFromValueFrom as u}from"./restart/secretsDrift.js";import{deployOrganisation as d}from"./organisation/organisationDeploy.js";import{destroyOrganisation as S}from"./organisation/organisationDestroy.js";import{cleanupFailedStack as P,emptyS3Bucket as T,preEmptyStackBuckets as A,formatQuarantineSuspectedMessage as y,formatRetainedBucketsMessage as E,isQuarantineDetail as D,isRetainedBucketsDetail as g,PRE_EMPTY_TAG_KEYS as _,isCleanableState as O,SAFE_CLEANUP_STATES as v}from"./stackCleanup.js";import{partitionAccounts as k,buildRegionList as B,buildAccountRegionPairs as L,cascadeHomeRegion as C,cascadeOperationKey as b}from"./organisation/cascadeHelpers.js";import{projectScalarSummary as U,projectAccountRows as h}from"./organisation/cascadeSummary.js";import{reconcileProviderAccounts as N,mergeReconciledProviderAccounts as K}from"./organisation/reconcileProviderAccounts.js";import{decideNextTransition as Y,reconcileTrailMigration as V,ORG_TRAIL_BUCKET_OUTPUT_KEY as J,TRAIL_BUCKET_OUTPUT_KEY as H,TRAIL_KEY_ARN_OUTPUT_KEY as Q}from"./trailMigration/trailMigration.js";import{decommissionMemberTrailStorage as j}from"./trailMigration/memberTrailCleanup.js";import{unlockBucket as q}from"./unlock/unlockBucket.js";import{unlockQueue as X}from"./unlock/unlockQueue.js";import{triageBucketPolicy as $,isEnforceSslStatement as ee}from"./unlock/bucketPolicyTriage.js";import{toResourcePolicyStatements as te}from"./unlock/toResourcePolicyStatements.js";import{restoreBucketPolicy as ie,synthesiseEnforceSslDocument as ae,ensureEnforceSsl as ne}from"./unlock/restoreBucketPolicy.js";import{restoreAndReconcileQuarantinedBucket as ce}from"./unlock/restoreAndReconcileQuarantinedBucket.js";import{parseAccountsConfiguration as pe,flattenAccountsToEnvironments as me,extractAllAccountNames as ue,accountsConfigToOUTree as fe,isStringArray as de,isAccountsConfig as Re,isOuOnlyAccountBucket as Se,OU_ONLY_ACCOUNT_BUCKETS as xe}from"./organisation/accountsConfig.js";import{resolveBuildSecrets as Te,resolveSecretRefValue as Ae,resolveBuildSecretSessionProvider as ye,sourcedRefsFromBuildArgs as Ee}from"./application/buildSecretResolver.js";import{buildBuildSecretSessionPolicy as ge,partitionForRegion as _e}from"./application/buildSecretSession.js";import{buildDeploySessionPolicy as ve}from"./application/deploySessionPolicy.js";import{resolveBuildArgs as ke}from"./application/buildArgResolver.js";import{validateBuildGroup as Le}from"./application/buildGroupValidator.js";export*from"./domain/index.js";import{runOpenNextBuild as Ie}from"./application/openNextBuild.js";import{runOrganisationSetup as he,ORG_SETUP_PHASES as Ge}from"./organisation/organisationSetup.js";export*from"./builders/index.js";import{buildDeployPlan as Me,computeDeployPlan as Ye,computeAssemblyDigest as Ve,digestHead as Je,classifyImpact as He,derivePropertyChanges as Qe,isDataLoss as we,isStatefulResourceType as je,renderPlanSummary as We,renderPlanLines as qe,toWirePlanChanges as ze,signApprovalToken as Xe,verifyApprovalToken as Ze,DEFAULT_APPROVAL_TTL_MS as $e,APPROVAL_TOKEN_PATTERN as er}from"./application/plan/index.js";import{runApprovalGate as tr,approvalRefusalReason as or}from"./application/approvalGate.js";import{runDestructionGate as ar,buildDestructionTicket as nr,evaluateDestructionConsents as sr,computeTicketDigest as cr,legalRemediationVerbs as lr,executableRemediationVerbs as pr,advertisableRemediationVerbs as mr,renderDestructionTicketLines as ur,renderConsentVerdictLines as fr}from"./application/destructionGate.js";import{loadDeployPlan as Rr,createMemoisedPlanLoader as Sr}from"./application/plan/loadDeployPlan.js";import{classifyDriftFailure as Pr,fetchLastOperationEvents as Tr}from"./drift/classifyDriftFailure.js";import{DriftProbe as yr}from"./drift/driftProbe.js";import{clearDriftSuspects as Dr,defaultDriftJournalDir as gr,readDriftSuspects as _r,recordDriftSuspects as Or}from"./drift/driftSuspectJournal.js";import{detectStackDrift as Fr}from"./drift/detectStackDrift.js";import{runDriftPreFlight as Br,formatDriftPreFlightBlock as Lr,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Cr,DRIFT_PREFLIGHT_BUDGET_MS as br}from"./drift/driftPreFlight.js";import{runRoute53RecordPreflight as Ur}from"./drift/route53RecordPreflight.js";import{archiveCompletedRemediationJournal as Gr,computeRemediationOpId as Nr,defaultRemediationJournalDir as Kr,findRemediationJournalByOpId as Mr,listActiveRemediationOps as Yr,listActiveRemediationOpsForContext as Vr,readRemediationJournal as Jr,sweepExpiredRemediationJournals as Hr,writeRemediationJournal as Qr,REMEDIATION_JOURNAL_RETENTION_DAYS as wr}from"./remediation/remediationJournal.js";import{captureRemediationForensics as Wr,defaultRemediationForensicsDir as qr}from"./remediation/forensicsCapture.js";import{applyRetainFlip as Xr,composeFlipCapabilities as Zr,computeTemplateDigest as $r,deriveRetainFlipTemplate as et,findMarkedResourcesByOpId as rt,proveFlipMetadataOnly as tt,readRetainFlipState as ot,verifyRetainFlipDiff as it,FORGET_MARKER_KEY as at,FORGET_FLIP_SPEC as nt,RECREATE_MARKER_KEY as st}from"./remediation/retainFlip.js";import{assessForgetResumability as lt,completeForgetAfterConverge as pt,completeForgetAfterDeploy as mt,formatRecreateInFlightCures as ut,partitionPreFlightByRemediation as ft,runForgetSurgery as dt,synthTemplateDeclaresResource as Rt}from"./remediation/forgetResource.js";import{runRecreateSurgery as xt,snapshotPolicyForType as Pt,SNAPSHOT_CAPABLE_RESOURCE_TYPES as Tt}from"./remediation/recreateResource.js";import{runRecreatePreFlight as yt}from"./remediation/recreatePreFlight.js";import{deriveRemovalTemplate as Dt,findRemovalDeletionFailures as gt,findResourcesPresent as _t,proveRemovalTargetsOnly as Ot}from"./remediation/removalUpdate.js";import{advertisableDriftVerbs as Ft,buildDriftRepairTicket as kt,runDriftRepairGate as Bt}from"./remediation/driftRepairGate.js";import{formatPinOutcomeDetail as Ct,pinProbeCoverage as bt,renderPinReportLines as It,runPinRemediation as Ut}from"./remediation/pinRemediation.js";import{composePostFailureRepairOffer as Gt,formatDriftRepairOffer as Nt,DriftRepairAvailableError as Kt}from"./remediation/postFailureRepairOffer.js";import{captureLegacySurfaces as Yt,decodeLegacyAnchor as Vt,runIdentitySurfaceGate as Jt}from"./remediation/pinIdentity.js";import{collectIdentityPinCandidates as Qt,degradedIdentityPinOutcomes as wt,renderIdentityPinReportLines as jt,runIdentityPinMigration as Wt}from"./remediation/migrateIdentity.js";import{checkDeployPathStackAvailability as zt,isDeployPathBlockingStatus as Xt,StackUnavailableError as Zt}from"./activeDeploymentGuard.js";import{assertLeaseBeforeStack as eo,LeaseDeniedError as ro}from"./application/leaseGate.js";export{er as APPROVAL_TOKEN_PATTERN,$e as DEFAULT_APPROVAL_TTL_MS,br as DRIFT_PREFLIGHT_BUDGET_MS,Cr as DRIFT_PREFLIGHT_TRIGGER_STATUSES,yr as DriftProbe,Kt as DriftRepairAvailableError,nt as FORGET_FLIP_SPEC,at as FORGET_MARKER_KEY,ro as LeaseDeniedError,Ge as ORG_SETUP_PHASES,J as ORG_TRAIL_BUCKET_OUTPUT_KEY,xe as OU_ONLY_ACCOUNT_BUCKETS,_ as PRE_EMPTY_TAG_KEYS,st as RECREATE_MARKER_KEY,wr as REMEDIATION_JOURNAL_RETENTION_DAYS,v as SAFE_CLEANUP_STATES,Tt as SNAPSHOT_CAPABLE_RESOURCE_TYPES,Zt as StackUnavailableError,H as TRAIL_BUCKET_OUTPUT_KEY,Q as TRAIL_KEY_ARN_OUTPUT_KEY,fe as accountsConfigToOUTree,Ft as advertisableDriftVerbs,mr as advertisableRemediationVerbs,Xr as applyRetainFlip,or as approvalRefusalReason,Gr as archiveCompletedRemediationJournal,eo as assertLeaseBeforeStack,lt as assessForgetResumability,L as buildAccountRegionPairs,ge as buildBuildSecretSessionPolicy,Me as buildDeployPlan,ve as buildDeploySessionPolicy,nr as buildDestructionTicket,kt as buildDriftRepairTicket,B as buildRegionList,Yt as captureLegacySurfaces,Wr as captureRemediationForensics,C as cascadeHomeRegion,b as cascadeOperationKey,zt as checkDeployPathStackAvailability,Pr as classifyDriftFailure,He as classifyImpact,P as cleanupFailedStack,Dr as clearDriftSuspects,Qt as collectIdentityPinCandidates,pt as completeForgetAfterConverge,mt as completeForgetAfterDeploy,Zr as composeFlipCapabilities,Gt as composePostFailureRepairOffer,Ve as computeAssemblyDigest,Ye as computeDeployPlan,Nr as computeRemediationOpId,l as computeSecretsDrift,$r as computeTemplateDigest,cr as computeTicketDigest,Sr as createMemoisedPlanLoader,Y as decideNextTransition,Vt as decodeLegacyAnchor,j as decommissionMemberTrailStorage,gr as defaultDriftJournalDir,qr as defaultRemediationForensicsDir,Kr as defaultRemediationJournalDir,wt as degradedIdentityPinOutcomes,t as deploy,d as deployOrganisation,Qe as derivePropertyChanges,Dt as deriveRemovalTemplate,et as deriveRetainFlipTemplate,p as deriveStaleParameters,i as destroy,S as destroyOrganisation,Fr as detectStackDrift,Je as digestHead,T as emptyS3Bucket,ne as ensureEnforceSsl,sr as evaluateDestructionConsents,pr as executableRemediationVerbs,ue as extractAllAccountNames,m as extractConsumedSsmParameters,Tr as fetchLastOperationEvents,rt as findMarkedResourcesByOpId,Mr as findRemediationJournalByOpId,gt as findRemovalDeletionFailures,_t as findResourcesPresent,me as flattenAccountsToEnvironments,Lr as formatDriftPreFlightBlock,Nt as formatDriftRepairOffer,Ct as formatPinOutcomeDetail,y as formatQuarantineSuspectedMessage,ut as formatRecreateInFlightCures,E as formatRetainedBucketsMessage,Re as isAccountsConfig,O as isCleanableState,we as isDataLoss,Xt as isDeployPathBlockingStatus,ee as isEnforceSslStatement,Se as isOuOnlyAccountBucket,D as isQuarantineDetail,g as isRetainedBucketsDetail,je as isStatefulResourceType,de as isStringArray,lr as legalRemediationVerbs,Yr as listActiveRemediationOps,Vr as listActiveRemediationOpsForContext,Rr as loadDeployPlan,K as mergeReconciledProviderAccounts,pe as parseAccountsConfiguration,k as partitionAccounts,_e as partitionForRegion,ft as partitionPreFlightByRemediation,bt as pinProbeCoverage,A as preEmptyStackBuckets,s as probeSecretsDrift,h as projectAccountRows,U as projectScalarSummary,tt as proveFlipMetadataOnly,Ot as proveRemovalTargetsOnly,_r as readDriftSuspects,Jr as readRemediationJournal,ot as readRetainFlipState,N as reconcileProviderAccounts,V as reconcileTrailMigration,Or as recordDriftSuspects,fr as renderConsentVerdictLines,ur as renderDestructionTicketLines,jt as renderIdentityPinReportLines,It as renderPinReportLines,qe as renderPlanLines,We as renderPlanSummary,ke as resolveBuildArgs,ye as resolveBuildSecretSessionProvider,Te as resolveBuildSecrets,Ae as resolveSecretRefValue,n as restart,ce as restoreAndReconcileQuarantinedBucket,ie as restoreBucketPolicy,tr as runApprovalGate,ar as runDestructionGate,Br as runDriftPreFlight,Bt as runDriftRepairGate,dt as runForgetSurgery,Wt as runIdentityPinMigration,Jt as runIdentitySurfaceGate,Ie as runOpenNextBuild,he as runOrganisationSetup,Ut as runPinRemediation,yt as runRecreatePreFlight,xt as runRecreateSurgery,Ur as runRoute53RecordPreflight,Xe as signApprovalToken,Pt as snapshotPolicyForType,Ee as sourcedRefsFromBuildArgs,u as ssmParameterNameFromValueFrom,Hr as sweepExpiredRemediationJournals,Rt as synthTemplateDeclaresResource,ae as synthesiseEnforceSslDocument,te as toResourcePolicyStatements,ze as toWirePlanChanges,$ as triageBucketPolicy,q as unlockBucket,X as unlockQueue,Le as validateBuildGroup,Ze as verifyApprovalToken,it as verifyRetainFlipDiff,Qr as writeRemediationJournal};
|
|
1
|
+
import{deploy as t}from"./deploy.js";import{destroy as i}from"./destroy.js";import{restart as n,probeSecretsDrift as s,probeServiceDeploymentStatus as c}from"./restart/restartApplication.js";import{computeSecretsDrift as p,deriveStaleParameters as m,extractConsumedSsmParameters as u,ssmParameterNameFromValueFrom as f}from"./restart/secretsDrift.js";import{deployOrganisation as R}from"./organisation/organisationDeploy.js";import{destroyOrganisation as x}from"./organisation/organisationDestroy.js";import{cleanupFailedStack as T,emptyS3Bucket as y,preEmptyStackBuckets as A,formatQuarantineSuspectedMessage as E,formatRetainedBucketsMessage as D,isQuarantineDetail as g,isRetainedBucketsDetail as _,PRE_EMPTY_TAG_KEYS as O,isCleanableState as v,SAFE_CLEANUP_STATES as F}from"./stackCleanup.js";import{partitionAccounts as B,buildRegionList as L,buildAccountRegionPairs as b,cascadeHomeRegion as C,cascadeOperationKey as I}from"./organisation/cascadeHelpers.js";import{projectScalarSummary as h,projectAccountRows as G}from"./organisation/cascadeSummary.js";import{reconcileProviderAccounts as K,mergeReconciledProviderAccounts as M}from"./organisation/reconcileProviderAccounts.js";import{decideNextTransition as V,reconcileTrailMigration as J,ORG_TRAIL_BUCKET_OUTPUT_KEY as H,TRAIL_BUCKET_OUTPUT_KEY as Q,TRAIL_KEY_ARN_OUTPUT_KEY as w}from"./trailMigration/trailMigration.js";import{decommissionMemberTrailStorage as W}from"./trailMigration/memberTrailCleanup.js";import{unlockBucket as z}from"./unlock/unlockBucket.js";import{unlockQueue as Z}from"./unlock/unlockQueue.js";import{triageBucketPolicy as ee,isEnforceSslStatement as re}from"./unlock/bucketPolicyTriage.js";import{toResourcePolicyStatements as oe}from"./unlock/toResourcePolicyStatements.js";import{restoreBucketPolicy as ae,synthesiseEnforceSslDocument as ne,ensureEnforceSsl as se}from"./unlock/restoreBucketPolicy.js";import{restoreAndReconcileQuarantinedBucket as le}from"./unlock/restoreAndReconcileQuarantinedBucket.js";import{parseAccountsConfiguration as me,flattenAccountsToEnvironments as ue,extractAllAccountNames as fe,accountsConfigToOUTree as de,isStringArray as Re,isAccountsConfig as Se,isOuOnlyAccountBucket as xe,OU_ONLY_ACCOUNT_BUCKETS as Pe}from"./organisation/accountsConfig.js";import{resolveBuildSecrets as ye,resolveSecretRefValue as Ae,resolveBuildSecretSessionProvider as Ee,sourcedRefsFromBuildArgs as De}from"./application/buildSecretResolver.js";import{buildBuildSecretSessionPolicy as _e,partitionForRegion as Oe}from"./application/buildSecretSession.js";import{buildDeploySessionPolicy as Fe}from"./application/deploySessionPolicy.js";import{resolveBuildArgs as Be}from"./application/buildArgResolver.js";import{validateBuildGroup as be}from"./application/buildGroupValidator.js";export*from"./domain/index.js";import{runOpenNextBuild as Ue}from"./application/openNextBuild.js";import{runOrganisationSetup as Ge,ORG_SETUP_PHASES as Ne}from"./organisation/organisationSetup.js";export*from"./builders/index.js";import{buildDeployPlan as Ye,computeDeployPlan as Ve,computeAssemblyDigest as Je,digestHead as He,classifyImpact as Qe,derivePropertyChanges as we,isDataLoss as je,isStatefulResourceType as We,renderPlanSummary as qe,renderPlanLines as ze,toWirePlanChanges as Xe,signApprovalToken as Ze,verifyApprovalToken as $e,DEFAULT_APPROVAL_TTL_MS as er,APPROVAL_TOKEN_PATTERN as rr}from"./application/plan/index.js";import{runApprovalGate as or,approvalRefusalReason as ir}from"./application/approvalGate.js";import{runDestructionGate as nr,buildDestructionTicket as sr,evaluateDestructionConsents as cr,computeTicketDigest as lr,legalRemediationVerbs as pr,executableRemediationVerbs as mr,advertisableRemediationVerbs as ur,renderDestructionTicketLines as fr,renderConsentVerdictLines as dr}from"./application/destructionGate.js";import{loadDeployPlan as Sr,createMemoisedPlanLoader as xr}from"./application/plan/loadDeployPlan.js";import{classifyDriftFailure as Tr,fetchLastOperationEvents as yr}from"./drift/classifyDriftFailure.js";import{DriftProbe as Er}from"./drift/driftProbe.js";import{clearDriftSuspects as gr,defaultDriftJournalDir as _r,readDriftSuspects as Or,recordDriftSuspects as vr}from"./drift/driftSuspectJournal.js";import{detectStackDrift as kr}from"./drift/detectStackDrift.js";import{runDriftPreFlight as Lr,formatDriftPreFlightBlock as br,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Cr,DRIFT_PREFLIGHT_BUDGET_MS as Ir}from"./drift/driftPreFlight.js";import{runRoute53RecordPreflight as hr}from"./drift/route53RecordPreflight.js";import{archiveCompletedRemediationJournal as Nr,computeRemediationOpId as Kr,defaultRemediationJournalDir as Mr,findRemediationJournalByOpId as Yr,listActiveRemediationOps as Vr,listActiveRemediationOpsForContext as Jr,readRemediationJournal as Hr,sweepExpiredRemediationJournals as Qr,writeRemediationJournal as wr,REMEDIATION_JOURNAL_RETENTION_DAYS as jr}from"./remediation/remediationJournal.js";import{captureRemediationForensics as qr,defaultRemediationForensicsDir as zr}from"./remediation/forensicsCapture.js";import{applyRetainFlip as Zr,composeFlipCapabilities as $r,computeTemplateDigest as et,deriveRetainFlipTemplate as rt,findMarkedResourcesByOpId as tt,proveFlipMetadataOnly as ot,readRetainFlipState as it,verifyRetainFlipDiff as at,FORGET_MARKER_KEY as nt,FORGET_FLIP_SPEC as st,RECREATE_MARKER_KEY as ct}from"./remediation/retainFlip.js";import{assessForgetResumability as pt,completeForgetAfterConverge as mt,completeForgetAfterDeploy as ut,formatRecreateInFlightCures as ft,partitionPreFlightByRemediation as dt,runForgetSurgery as Rt,synthTemplateDeclaresResource as St}from"./remediation/forgetResource.js";import{runRecreateSurgery as Pt,snapshotPolicyForType as Tt,SNAPSHOT_CAPABLE_RESOURCE_TYPES as yt}from"./remediation/recreateResource.js";import{runRecreatePreFlight as Et}from"./remediation/recreatePreFlight.js";import{deriveRemovalTemplate as gt,findRemovalDeletionFailures as _t,findResourcesPresent as Ot,proveRemovalTargetsOnly as vt}from"./remediation/removalUpdate.js";import{advertisableDriftVerbs as kt,buildDriftRepairTicket as Bt,runDriftRepairGate as Lt}from"./remediation/driftRepairGate.js";import{formatPinOutcomeDetail as Ct,pinProbeCoverage as It,renderPinReportLines as Ut,runPinRemediation as ht}from"./remediation/pinRemediation.js";import{composePostFailureRepairOffer as Nt,formatDriftRepairOffer as Kt,DriftRepairAvailableError as Mt}from"./remediation/postFailureRepairOffer.js";import{captureLegacySurfaces as Vt,decodeLegacyAnchor as Jt,runIdentitySurfaceGate as Ht}from"./remediation/pinIdentity.js";import{collectIdentityPinCandidates as wt,degradedIdentityPinOutcomes as jt,renderIdentityPinReportLines as Wt,runIdentityPinMigration as qt}from"./remediation/migrateIdentity.js";import{checkDeployPathStackAvailability as Xt,isDeployPathBlockingStatus as Zt,StackUnavailableError as $t}from"./activeDeploymentGuard.js";import{assertLeaseBeforeStack as ro,LeaseDeniedError as to}from"./application/leaseGate.js";export{rr as APPROVAL_TOKEN_PATTERN,er as DEFAULT_APPROVAL_TTL_MS,Ir as DRIFT_PREFLIGHT_BUDGET_MS,Cr as DRIFT_PREFLIGHT_TRIGGER_STATUSES,Er as DriftProbe,Mt as DriftRepairAvailableError,st as FORGET_FLIP_SPEC,nt as FORGET_MARKER_KEY,to as LeaseDeniedError,Ne as ORG_SETUP_PHASES,H as ORG_TRAIL_BUCKET_OUTPUT_KEY,Pe as OU_ONLY_ACCOUNT_BUCKETS,O as PRE_EMPTY_TAG_KEYS,ct as RECREATE_MARKER_KEY,jr as REMEDIATION_JOURNAL_RETENTION_DAYS,F as SAFE_CLEANUP_STATES,yt as SNAPSHOT_CAPABLE_RESOURCE_TYPES,$t as StackUnavailableError,Q as TRAIL_BUCKET_OUTPUT_KEY,w as TRAIL_KEY_ARN_OUTPUT_KEY,de as accountsConfigToOUTree,kt as advertisableDriftVerbs,ur as advertisableRemediationVerbs,Zr as applyRetainFlip,ir as approvalRefusalReason,Nr as archiveCompletedRemediationJournal,ro as assertLeaseBeforeStack,pt as assessForgetResumability,b as buildAccountRegionPairs,_e as buildBuildSecretSessionPolicy,Ye as buildDeployPlan,Fe as buildDeploySessionPolicy,sr as buildDestructionTicket,Bt as buildDriftRepairTicket,L as buildRegionList,Vt as captureLegacySurfaces,qr as captureRemediationForensics,C as cascadeHomeRegion,I as cascadeOperationKey,Xt as checkDeployPathStackAvailability,Tr as classifyDriftFailure,Qe as classifyImpact,T as cleanupFailedStack,gr as clearDriftSuspects,wt as collectIdentityPinCandidates,mt as completeForgetAfterConverge,ut as completeForgetAfterDeploy,$r as composeFlipCapabilities,Nt as composePostFailureRepairOffer,Je as computeAssemblyDigest,Ve as computeDeployPlan,Kr as computeRemediationOpId,p as computeSecretsDrift,et as computeTemplateDigest,lr as computeTicketDigest,xr as createMemoisedPlanLoader,V as decideNextTransition,Jt as decodeLegacyAnchor,W as decommissionMemberTrailStorage,_r as defaultDriftJournalDir,zr as defaultRemediationForensicsDir,Mr as defaultRemediationJournalDir,jt as degradedIdentityPinOutcomes,t as deploy,R as deployOrganisation,we as derivePropertyChanges,gt as deriveRemovalTemplate,rt as deriveRetainFlipTemplate,m as deriveStaleParameters,i as destroy,x as destroyOrganisation,kr as detectStackDrift,He as digestHead,y as emptyS3Bucket,se as ensureEnforceSsl,cr as evaluateDestructionConsents,mr as executableRemediationVerbs,fe as extractAllAccountNames,u as extractConsumedSsmParameters,yr as fetchLastOperationEvents,tt as findMarkedResourcesByOpId,Yr as findRemediationJournalByOpId,_t as findRemovalDeletionFailures,Ot as findResourcesPresent,ue as flattenAccountsToEnvironments,br as formatDriftPreFlightBlock,Kt as formatDriftRepairOffer,Ct as formatPinOutcomeDetail,E as formatQuarantineSuspectedMessage,ft as formatRecreateInFlightCures,D as formatRetainedBucketsMessage,Se as isAccountsConfig,v as isCleanableState,je as isDataLoss,Zt as isDeployPathBlockingStatus,re as isEnforceSslStatement,xe as isOuOnlyAccountBucket,g as isQuarantineDetail,_ as isRetainedBucketsDetail,We as isStatefulResourceType,Re as isStringArray,pr as legalRemediationVerbs,Vr as listActiveRemediationOps,Jr as listActiveRemediationOpsForContext,Sr as loadDeployPlan,M as mergeReconciledProviderAccounts,me as parseAccountsConfiguration,B as partitionAccounts,Oe as partitionForRegion,dt as partitionPreFlightByRemediation,It as pinProbeCoverage,A as preEmptyStackBuckets,s as probeSecretsDrift,c as probeServiceDeploymentStatus,G as projectAccountRows,h as projectScalarSummary,ot as proveFlipMetadataOnly,vt as proveRemovalTargetsOnly,Or as readDriftSuspects,Hr as readRemediationJournal,it as readRetainFlipState,K as reconcileProviderAccounts,J as reconcileTrailMigration,vr as recordDriftSuspects,dr as renderConsentVerdictLines,fr as renderDestructionTicketLines,Wt as renderIdentityPinReportLines,Ut as renderPinReportLines,ze as renderPlanLines,qe as renderPlanSummary,Be as resolveBuildArgs,Ee as resolveBuildSecretSessionProvider,ye as resolveBuildSecrets,Ae as resolveSecretRefValue,n as restart,le as restoreAndReconcileQuarantinedBucket,ae as restoreBucketPolicy,or as runApprovalGate,nr as runDestructionGate,Lr as runDriftPreFlight,Lt as runDriftRepairGate,Rt as runForgetSurgery,qt as runIdentityPinMigration,Ht as runIdentitySurfaceGate,Ue as runOpenNextBuild,Ge as runOrganisationSetup,ht as runPinRemediation,Et as runRecreatePreFlight,Pt as runRecreateSurgery,hr as runRoute53RecordPreflight,Ze as signApprovalToken,Tt as snapshotPolicyForType,De as sourcedRefsFromBuildArgs,f as ssmParameterNameFromValueFrom,Qr as sweepExpiredRemediationJournals,St as synthTemplateDeclaresResource,ne as synthesiseEnforceSslDocument,oe as toResourcePolicyStatements,Xe as toWirePlanChanges,ee as triageBucketPolicy,z as unlockBucket,Z as unlockQueue,be as validateBuildGroup,$e as verifyApprovalToken,at as verifyRetainFlipDiff,wr as writeRemediationJournal};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var S=Object.defineProperty;var f=(t,i)=>S(t,"name",{value:i,configurable:!0});import{z as d}from"zod";import{success as h,failure as c}from"@fjall/generator";import{environmentToTier as w,stageFromWireEnvironment as y,normaliseError as N}from"@fjall/util";import{logger as E}from"@fjall/util/logger";import{OrganizationsClient as P}from"@aws-sdk/client-organizations";import{listAccounts as I}from"../../aws/organisations/accounts.js";import{parseAccountsConfiguration as O,flattenAccountsToEnvironments as M}from"./accountsConfig.js";const C=6e4,U=d.object({Id:d.string().min(1),Name:d.string().min(1)});async function W(t,i){let n;const r=new Promise((e,o)=>{n=setTimeout(()=>o(new Error(`Timed out parsing ACCOUNTS configuration after ${C}ms`)),C)});let a;try{a=await Promise.race([O(i),r])}catch(e){return c(N(e))}finally{n!==void 0&&clearTimeout(n)}if(!a.success)return c(new Error(`Failed to parse ACCOUNTS configuration: ${a.error.message}`));if(a.data===null)return c(new Error("ACCOUNTS configuration file not found"));const T=M(a.data),l=new Map;for(const{accountName:e,environment:o}of T)l.set(e.toLowerCase(),{environment:o,displayName:e});let p;try{p=t.awsProvider.getClient(P)}catch(e){return c(N(e))}const m=await I(p);if(!m.success)return c(m.error);const g=new Map;for(const e of m.data){const o=U.safeParse(e);if(!o.success){E.warn("reconcileProviderAccounts","Skipping AWS Organizations account that failed schema validation",{accountId:e.Id,accountName:e.Name,issues:o.error.issues.map(s=>`${s.path.map(String).join(".")}: ${s.message}`)});continue}g.set(o.data.Name.toLowerCase(),{id:o.data.Id,name:o.data.Name})}const A=[],v=[];for(const[e,{environment:o,displayName:s}]of l){const u=g.get(e);if(!u){v.push(s);continue}w(o)!=="organisation"&&A.push({id:u.id,name:u.name,tier:w(o),environment:y(o)})}return h({providerAccounts:A,missingAccountNames:v})}f(W,"reconcileProviderAccounts");function k(t,i){const n=new Map;for(const r of t?.providerAccounts??[])n.set(r.id,r);for(const r of i)n.has(r.id)||n.set(r.id,r);return{...t??{},providerAccounts:Array.from(n.values())}}f(k,"mergeReconciledProviderAccounts");export{k as mergeReconciledProviderAccounts,W as reconcileProviderAccounts};
|
|
@@ -57,6 +57,40 @@ export type SecretsDriftProbeParams = Omit<RestartParams, "callbacks">;
|
|
|
57
57
|
* Used by the CLI's pre-confirm drift display and the webapp's drift pulse.
|
|
58
58
|
*/
|
|
59
59
|
export declare function probeSecretsDrift(params: SecretsDriftProbeParams, injectedServices?: RestartServices): Promise<Result<ApplicationSecretsDrift, Error>>;
|
|
60
|
+
/** Per-service snapshot of the PRIMARY ECS deployment's rollout state. */
|
|
61
|
+
export interface ServiceDeploymentStatus {
|
|
62
|
+
serviceName: string;
|
|
63
|
+
serviceArn: string;
|
|
64
|
+
desiredCount: number;
|
|
65
|
+
runningCount: number;
|
|
66
|
+
pendingCount: number;
|
|
67
|
+
/** `COMPLETED` | `IN_PROGRESS` | `FAILED` — absent on services predating rollout-state reporting. */
|
|
68
|
+
rolloutState?: string;
|
|
69
|
+
rolloutStateReason?: string;
|
|
70
|
+
failedTasks?: number;
|
|
71
|
+
/** Task definition the PRIMARY deployment is rolling out. */
|
|
72
|
+
taskDefinition?: string;
|
|
73
|
+
/** Deployment count on the service — >1 means an old deployment is still draining. */
|
|
74
|
+
activeDeployments: number;
|
|
75
|
+
/** The smoke verdict for this service — see `isServiceDeploymentComplete`. */
|
|
76
|
+
completed: boolean;
|
|
77
|
+
}
|
|
78
|
+
export interface ApplicationServiceStatus {
|
|
79
|
+
target: string;
|
|
80
|
+
clusterArn: string;
|
|
81
|
+
services: ServiceDeploymentStatus[];
|
|
82
|
+
/** True only when EVERY discovered service's PRIMARY deployment is complete. */
|
|
83
|
+
allCompleted: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Read-only per-service deployment-status probe (`fjall services`) — the
|
|
87
|
+
* same resolution ladder as `restart()`/`probeSecretsDrift()`, reporting each
|
|
88
|
+
* service's PRIMARY deployment rollout state. This is the CD smoke surface
|
|
89
|
+
* from the worker-deploy-safety design (item 12): a worker that CloudFormation
|
|
90
|
+
* waved through but is now churning shows `IN_PROGRESS`/`FAILED` (or a
|
|
91
|
+
* running-count shortfall) here instead of being invisible to the gate.
|
|
92
|
+
*/
|
|
93
|
+
export declare function probeServiceDeploymentStatus(params: SecretsDriftProbeParams, injectedServices?: RestartServices): Promise<Result<ApplicationServiceStatus, Error>>;
|
|
60
94
|
/**
|
|
61
95
|
* Restart an application's ECS services without building or deploying:
|
|
62
96
|
* re-register each service's live task definition unchanged and roll the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var x=Object.defineProperty;var
|
|
1
|
+
var x=Object.defineProperty;var S=(e,t)=>x(e,"name",{value:t,configurable:!0});import{success as E,failure as m}from"@fjall/generator";import{CONTENT_HASH_TAG_PATTERN as O,maskSensitiveOutput as R}from"@fjall/util";import{logger as M}from"@fjall/util/logger";import{SimpleAwsProvider as P}from"../../aws/SimpleAwsProvider.js";import{CloudFormationService as L}from"../../services/infrastructure/CloudFormationService.js";import{EcsService as _}from"../../services/infrastructure/EcsService.js";import{EcsServiceResolver as F}from"../../services/infrastructure/EcsServiceResolver.js";import{EcrImageInspectorService as G,stripTagOrDigest as H}from"../../services/infrastructure/EcrImageInspectorService.js";import{SsmParameterMetadataService as U}from"../../services/infrastructure/SsmParameterMetadataService.js";import{extractEcsServiceName as k}from"../../aws/utils/arnParser.js";import{isAborted as V}from"../../aws/organisations/types.js";import{matchesServiceName as Y,resolveServiceTaskDefinition as j}from"../application/serviceImageTagsRollback.js";import{deriveEcrRepositoryArn as B}from"../application/codeOnlyDeploy.js";import{registerAndRollTaskDefinition as q}from"../application/taskDefinitionRoll.js";import{computeSecretsDrift as N}from"./secretsDrift.js";const z="restartApplication";function h(e){const t=new P(e),d=new L(t);return{ecsService:new _(t),ecsResolver:new F(d),ecrImageInspector:new G(t),ssmService:new U(t)}}S(h,"createRestartServices");async function y(e,t,d){const{target:o}=t;let a,n;if(t.knownServices!==void 0)a=t.knownServices.clusterArn,n=t.knownServices.serviceArns;else{const r=await e.getDeployableClusterAndServices(o,t.abortSignal);if(!r.success)return m(new Error(`Failed to discover ECS services for ${o}: ${R(r.error.message)}`));a=r.data.clusterArn,n=r.data.serviceArns}if(a===void 0||n.length===0)return m(new Error(d??`No running ECS services found for ${o} \u2014 nothing to restart. Deploy the application first.`));if(t.serviceName!==void 0){const r=n.filter(f=>{const u=k(f);return u!==void 0&&t.serviceName!==void 0?Y(u,t.serviceName):!1});if(r.length===0){const f=n.map(u=>k(u)).filter(u=>u!==void 0).join(", ");return m(new Error(`No ECS service matching "${t.serviceName}" found for ${o}. Live services: ${f||"none"}`))}n=r}return E({clusterArn:a,serviceArns:n})}S(y,"resolveRestartTargets");async function le(e,t){const{ecsService:d,ecsResolver:o,ssmService:a}=t??h(e.awsCredentials),n=await y(o,e);return n.success?N({ecsService:d,ssmService:a},n.data,e.abortSignal):m(n.error)}S(le,"probeSecretsDrift");function J(e,t){return e===void 0?!1:e.rolloutState!==void 0?e.rolloutState==="COMPLETED":t===1&&(e.desiredCount??0)===(e.runningCount??0)&&(e.pendingCount??0)===0}S(J,"isServiceDeploymentComplete");async function ge(e,t){const{ecsService:d,ecsResolver:o}=t??h(e.awsCredentials),a=await y(o,e,`No ECS services found for ${e.target} \u2014 nothing to check. Deploy the application first.`);if(!a.success)return m(a.error);const{clusterArn:n,serviceArns:r}=a.data,f=await d.describeServices(n,r,e.abortSignal);if(!f.success)return m(new Error(`Failed to describe ECS services for ${e.target}: ${R(f.error.message)}`));const u=new Map(f.data.map(s=>[s.serviceArn,s])),l=r.map(s=>{const g=u.get(s),c=g?.deployments??[],i=c.find(v=>v.status==="PRIMARY");return{serviceName:g?.serviceName??k(s)??s,serviceArn:s,desiredCount:g?.desiredCount??0,runningCount:g?.runningCount??0,pendingCount:g?.pendingCount??0,...i?.rolloutState!==void 0?{rolloutState:i.rolloutState}:{},...i?.rolloutStateReason!==void 0?{rolloutStateReason:i.rolloutStateReason}:{},...i?.failedTasks!==void 0?{failedTasks:i.failedTasks}:{},...i?.taskDefinition!==void 0?{taskDefinition:i.taskDefinition}:{},activeDeployments:c.length,completed:J(i,c.length)}});return E({target:e.target,clusterArn:n,services:l,allCompleted:l.length>0&&l.every(s=>s.completed)})}S(ge,"probeServiceDeploymentStatus");async function ve(e,t){const{target:d,callbacks:o,abortSignal:a}=e,n=Date.now(),{ecsService:r,ecsResolver:f,ecrImageInspector:u,ssmService:l}=t??h(e.awsCredentials),s=await y(f,e);if(!s.success)return o.onError?.(s.error),m(s.error);const{clusterArn:g,serviceArns:c}=s.data,i=await N({ecsService:r,ssmService:l},{clusterArn:g,serviceArns:c},a);let v,T={};i.success?(v=i.data,T=i.data.parameterVersions):o.onLog?.(`Could not compute secrets drift before restart: ${R(i.error.message)}. Restarting anyway.`,"warn");const A=[];for(const C of c){if(V(a))return E({target:d,artefacts:A,appliedParameterVersions:T,...v!==void 0?{preRestartDrift:v}:{},durationMs:Date.now()-n,cancelled:!0});const I=Date.now(),p=k(C)??C;o.onLog?.(`Restarting ${p}\u2026`,"info");const w=await j({ecsService:r},g,C,p,a);if(!w.success){const D=new Error(`Restart failed for ${p}: ${R(w.error.message)}`);return o.onError?.(D),m(D)}const $=await q({ecsService:r},{clusterArn:g,serviceArn:C,serviceName:p,taskDefinition:w.data.taskDefinition,containerDefinitions:w.data.containerDefinitions,previousTaskDefArn:w.data.previousTaskDefArn,startedAtMs:I},o,a);if(!$.success){const D=new Error(`Restart failed for ${p}: ${R($.error.message)}`);return o.onError?.(D),m(D)}const b=await K(u,p,w.data.containerDefinitions,$.data.newTaskDefArn,w.data.previousTaskDefArn,a);b!==void 0?A.push(b):o.onLog?.(`Restarted ${p}, but its image tag could not be recovered \u2014 the restart release will omit this service's artefact.`,"warn")}return M.debug(z,`Restarted ${d}`,{services:c.length,artefacts:A.length}),E({target:d,artefacts:A,appliedParameterVersions:T,...v!==void 0?{preRestartDrift:v}:{},durationMs:Date.now()-n})}S(ve,"restart");async function K(e,t,d,o,a,n){const r=d.find(c=>c.image)?.image;if(r===void 0)return;const f=H(r),u=B(f);let l,s;const g=r.lastIndexOf("@");if(g>0){s=r.slice(g+1);const c=await e.getImageTagsByDigest(f,s,n);if(c.success&&c.data!==void 0){const i=c.data;l=i.find(v=>O.test(v))??i[0]}}else{const c=r.lastIndexOf(":");if(c>0){l=r.slice(c+1);const i=await e.getImageDigest(f,l,n);i.success&&(s=i.data)}}if(!(l===void 0||l===""))return{serviceName:t,imageTag:l,imageUri:`${f}:${l}`,taskDefinitionArn:o,previousTaskDefinitionArn:a,...s!==void 0?{imageDigest:s}:{},...u!==""?{ecrRepositoryArn:u}:{}}}S(K,"deriveRestartArtefact");export{h as createRestartServices,le as probeSecretsDrift,ge as probeServiceDeploymentStatus,ve as restart};
|
|
@@ -16,6 +16,7 @@ export interface ECSServiceInfo {
|
|
|
16
16
|
runningCount?: number;
|
|
17
17
|
pendingCount?: number;
|
|
18
18
|
deployments?: Array<{
|
|
19
|
+
id?: string;
|
|
19
20
|
status?: string;
|
|
20
21
|
desiredCount?: number;
|
|
21
22
|
runningCount?: number;
|
|
@@ -23,6 +24,8 @@ export interface ECSServiceInfo {
|
|
|
23
24
|
failedTasks?: number;
|
|
24
25
|
rolloutState?: string;
|
|
25
26
|
rolloutStateReason?: string;
|
|
27
|
+
taskDefinition?: string;
|
|
28
|
+
createdAt?: Date;
|
|
26
29
|
}>;
|
|
27
30
|
events?: Array<{
|
|
28
31
|
message?: string;
|
|
@@ -30,6 +33,26 @@ export interface ECSServiceInfo {
|
|
|
30
33
|
}>;
|
|
31
34
|
taskDefinition?: string;
|
|
32
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Forensic snapshot of a stopped ECS task — the fields the deployment tail
|
|
38
|
+
* narrates when a rolling update sheds tasks (`stoppedReason`, `stopCode`,
|
|
39
|
+
* per-container exit codes). All optional because ECS omits them for tasks
|
|
40
|
+
* stopped before placement.
|
|
41
|
+
*/
|
|
42
|
+
export interface StoppedTaskInfo {
|
|
43
|
+
taskArn: string;
|
|
44
|
+
taskDefinitionArn?: string;
|
|
45
|
+
stoppedReason?: string;
|
|
46
|
+
stopCode?: string;
|
|
47
|
+
startedBy?: string;
|
|
48
|
+
createdAt?: Date;
|
|
49
|
+
stoppedAt?: Date;
|
|
50
|
+
containers: Array<{
|
|
51
|
+
name?: string;
|
|
52
|
+
exitCode?: number;
|
|
53
|
+
reason?: string;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
33
56
|
export interface ECSClusterInfo {
|
|
34
57
|
clusterArn?: string;
|
|
35
58
|
clusterName?: string;
|
|
@@ -95,4 +118,16 @@ export declare class EcsService {
|
|
|
95
118
|
progressCallback?: (status: DeploymentStatus) => void;
|
|
96
119
|
abortSignal?: AbortSignal;
|
|
97
120
|
}): Promise<Result<void, EcsError>>;
|
|
121
|
+
/**
|
|
122
|
+
* List STOPPED task ARNs started by a specific originator (an ECS service
|
|
123
|
+
* deployment id, e.g. `ecs-svc/9223370…`). Paginated; an abort mid-way
|
|
124
|
+
* returns the pages gathered so far.
|
|
125
|
+
*/
|
|
126
|
+
listStoppedTasks(clusterArn: string, startedBy: string, abortSignal?: AbortSignal): Promise<Result<string[], EcsError>>;
|
|
127
|
+
/**
|
|
128
|
+
* Describe stopped tasks and extract the forensic fields (`stoppedReason`,
|
|
129
|
+
* `stopCode`, container exit codes). Batched at the DescribeTasks limit of
|
|
130
|
+
* 100 ARNs per call; an abort mid-way returns the batches gathered so far.
|
|
131
|
+
*/
|
|
132
|
+
describeTasks(clusterArn: string, taskArns: string[], abortSignal?: AbortSignal): Promise<Result<StoppedTaskInfo[], EcsError>>;
|
|
98
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var F=Object.defineProperty;var b=(v,n)=>F(v,"name",{value:n,configurable:!0});import{ECSClient as M,UpdateServiceCommand as _,DescribeServicesCommand as $,DescribeClustersCommand as A,ListServicesCommand as N,ListClustersCommand as x,ListTasksCommand as I,DescribeTasksCommand as L,RegisterTaskDefinitionCommand as P,DescribeTaskDefinitionCommand as U}from"@aws-sdk/client-ecs";import{success as c,failure as d}from"@fjall/generator";import{BaseServiceError as B}from"../../types/errors/ServiceError.js";import{logger as E}from"@fjall/util/logger";import{getErrorMessage as C,maskSensitiveOutput as p,sleep as G}from"@fjall/util";import{getAwsErrorDetails as H}from"../../aws/utils/awsErrorHandler.js";import{composeSdkAbortSignal as g,isAborted as T}from"../../aws/organisations/types.js";class u extends B{static{b(this,"EcsError")}errorType;resourceArn;constructor(n,s,e,t,r=!1){super(`ECS_${s.toUpperCase()}`,n,t,r),this.errorType=s,this.resourceArn=e}}const R=100;class J{static{b(this,"EcsService")}aws;constructor(n){this.aws=n}getClient(){return this.aws.getClient(M)}async updateService(n,s,e,t){try{const r=this.getClient(),a=new _({cluster:n,service:s,forceNewDeployment:e?.forceNewDeployment!==!1,desiredCount:e?.desiredCount,taskDefinition:e?.taskDefinition});return E.debug("EcsService",`UpdateService request: cluster=${n}, service=${s}, forceNewDeployment=${e?.forceNewDeployment!==!1}, taskDefinition=${e?.taskDefinition??"<unchanged>"}`),await r.send(a,{abortSignal:g(t)}),c(void 0)}catch(r){const{message:a,name:i,httpCode:o}=H(r),l=p(a);E.error("EcsService",`UpdateService failed: ${i} - ${l}`,{clusterArn:n,serviceArn:s,httpCode:o,error:r});let f=`Failed to update ECS service: ${l}`;return o&&(f+=` (HTTP ${o})`),i!=="Error"&&i!=="Unknown"&&(f+=` [${i}]`),d(new u(f,"unknown",s,{clusterArn:n,error:r,httpCode:o,errorName:i},!1))}}async describeServices(n,s,e){try{const t=this.getClient(),r=new $({cluster:n,services:s,include:["TAGS"]}),a=await t.send(r,{abortSignal:g(e)});if(!a.services)return c([]);const i=a.services.map(o=>({serviceArn:o.serviceArn,serviceName:o.serviceName,clusterArn:o.clusterArn,status:o.status,desiredCount:o.desiredCount,runningCount:o.runningCount,pendingCount:o.pendingCount,deployments:o.deployments,events:o.events,taskDefinition:o.taskDefinition}));return c(i)}catch(t){const r=p(C(t));return d(new u(`Failed to describe services: ${r}`,"unknown",void 0,{clusterArn:n,serviceArns:s,error:t},!1))}}async getDeploymentStatus(n,s,e){const t=await this.describeServices(n,[s],e);if(!t.success)return d(t.error);const r=t.data;if(r.length===0)return d(new u(`Service ${s} not found in cluster ${n}`,"service_not_found",s,{clusterArn:n}));const a=r[0],i=a.deployments||[],o=i.find(k=>k.status==="PRIMARY");if(!o)return c({deploymentCompleted:!1,deploymentFailed:!0,runningCount:0,desiredCount:0,pendingCount:0,deploymentCount:i.length,message:"No primary deployment found",percentComplete:0});const l=o.desiredCount||0,f=o.runningCount||0,w=o.pendingCount||0,S=l>0?Math.round(f/l*100):0,D=i.length===1&&f===l&&w===0,y=(o.failedTasks??0)>0||o.rolloutState==="FAILED";let m=`Running: ${f}/${l}`;if(m+=`, Pending: ${w}`,i.length>1&&(m+=` (${i.length} deployments active)`),y){const k=o.rolloutStateReason||(o.failedTasks?`${o.failedTasks} task(s) failed to start`:void 0);k&&(m+=` \u2014 ${k}`)}const h=a.events&&a.events.length>0?a.events[0]?.message:void 0;return c({deploymentCompleted:D,deploymentFailed:y,runningCount:f,desiredCount:l,pendingCount:w,deploymentCount:i.length,message:m,percentComplete:S,latestEvent:h})}async isDeploying(n,s){const e=await this.getDeploymentStatus(n,s);if(!e.success)return E.debug("EcsService","Could not determine deployment status, assuming not deploying",{error:e.error.message}),c(!1);const t=e.data;return c(!t.deploymentCompleted&&!t.deploymentFailed)}async getServiceEvents(n,s,e){try{const t=this.getClient(),r=new $({cluster:n,services:[s],include:["TAGS"]}),a=await t.send(r,{abortSignal:g(e)});if(!a.services||a.services.length===0)return c([]);const o=(a.services[0].events||[]).map(l=>({message:l.message||"",timestamp:l.createdAt||new Date}));return c(o)}catch(t){const r=p(C(t));return d(new u(`Failed to get service events: ${r}`,"unknown",s,{clusterArn:n,error:t}))}}async pollDeployment(n){const{clusterArn:s,serviceArn:e,waitForCompletion:t=!0,maxWaitTime:r=6e5,pollInterval:a=5e3,progressCallback:i,abortSignal:o}=n;if(!t)return c(void 0);const l=Date.now(),f=new Date(l-5e3);let w=null,S="";const D=new Set;for(;Date.now()-l<r;){if(T(o))return d(new u("Deployment polling cancelled by abort signal","unknown",e,{clusterArn:s}));const y=await this.getDeploymentStatus(s,e,o);if(!y.success)return d(y.error);const m=y.data,h=await this.getServiceEvents(s,e,o);if(h.success){const k=this.processDeploymentEvents(h.data,m,f,w,D,i);w=k.lastEventTimestamp,k.eventsReported?S=m.message:m.message!==S&&(i?.(m),S=m.message)}if(m.deploymentCompleted)return c(void 0);if(m.deploymentFailed)return d(new u("ECS deployment failed. Check the ECS console for detailed error information","deployment_failed",e,{clusterArn:s,status:m}));await G(a)}return d(new u(`ECS deployment timed out after ${r/1e3} seconds. The deployment is still in progress. Check the ECS console for status`,"deployment_timeout",e,{clusterArn:s,maxWaitTime:r}))}processDeploymentEvents(n,s,e,t,r,a){const i=n.filter(o=>!(o.timestamp<e||t&&o.timestamp<=t||r.has(o.message)));if(i.length===0)return{lastEventTimestamp:t,eventsReported:!1};for(const o of i)r.add(o.message),a?.({...s,latestEvent:o.message});return{lastEventTimestamp:i[i.length-1].timestamp,eventsReported:!0}}async listClusters(n){try{const s=this.getClient(),e=new x({}),t=await s.send(e,{abortSignal:g(n)});return c(t.clusterArns||[])}catch(s){const e=p(C(s));return d(new u(`Failed to list clusters: ${e}`,"permission_denied",void 0,s))}}async describeClusters(n,s){try{const e=this.getClient(),t=new A({clusters:n}),r=await e.send(t,{abortSignal:g(s)});if(!r.clusters)return c([]);const a=r.clusters.map(i=>({clusterArn:i.clusterArn,clusterName:i.clusterName,status:i.status,registeredContainerInstancesCount:i.registeredContainerInstancesCount,runningTasksCount:i.runningTasksCount,pendingTasksCount:i.pendingTasksCount}));return c(a)}catch(e){const t=p(C(e));return d(new u(`Failed to describe clusters: ${t}`,"unknown",void 0,{clusterArns:n,error:e},!1))}}async listServices(n,s){try{const e=this.getClient(),t=new N({cluster:n}),r=await e.send(t,{abortSignal:g(s)});return c(r.serviceArns||[])}catch(e){const t=p(C(e));return d(new u(`Failed to list services: ${t}`,"unknown",n,{clusterArn:n,error:e},!1))}}async registerTaskDefinition(n,s){try{const e=this.getClient(),t=new P(n),r=await e.send(t,{abortSignal:g(s)});return r.taskDefinition?.taskDefinitionArn?c(r.taskDefinition.taskDefinitionArn):d(new u("Task definition registration failed - no ARN returned","task_definition_failed",void 0,n))}catch(e){const t=p(C(e));return d(new u(`Failed to register task definition: ${t}`,"task_definition_failed",void 0,{taskDefinition:n,error:e},!1))}}async getLatestTaskDefinition(n,s){try{const e=this.getClient(),t=new U({taskDefinition:n}),r=await e.send(t,{abortSignal:g(s)});return c(r.taskDefinition)}catch(e){const t=p(C(e));return d(new u(`Failed to get task definition: ${t}`,"unknown",void 0,{family:n,error:e},!1))}}async deployService(n,s,e){const t=await this.updateService(n,s,{forceNewDeployment:!0,taskDefinition:e?.taskDefinition},e?.abortSignal);if(!t.success)return d(t.error);if(e?.waitForCompletion!==!1){const r=await this.pollDeployment({clusterArn:n,serviceArn:s,waitForCompletion:!0,progressCallback:e?.progressCallback,abortSignal:e?.abortSignal});if(!r.success)return d(r.error)}return c(void 0)}async listStoppedTasks(n,s,e){try{const t=this.getClient(),r=[];let a;do{if(T(e))break;const i=await t.send(new I({cluster:n,startedBy:s,desiredStatus:"STOPPED",...a!==void 0&&{nextToken:a}}),{abortSignal:g(e)});r.push(...i.taskArns??[]),a=i.nextToken}while(a!==void 0);return c(r)}catch(t){const r=p(C(t));return d(new u(`Failed to list stopped tasks: ${r}`,"unknown",void 0,{clusterArn:n,startedBy:s,error:t},!1))}}async describeTasks(n,s,e){if(s.length===0)return c([]);try{const t=this.getClient(),r=[];for(let a=0;a<s.length&&!T(e);a+=R){const i=await t.send(new L({cluster:n,tasks:s.slice(a,a+R)}),{abortSignal:g(e)});for(const o of i.tasks??[])o.taskArn!==void 0&&r.push({taskArn:o.taskArn,taskDefinitionArn:o.taskDefinitionArn,stoppedReason:o.stoppedReason,stopCode:o.stopCode,startedBy:o.startedBy,createdAt:o.createdAt,stoppedAt:o.stoppedAt,containers:(o.containers??[]).map(l=>({name:l.name,exitCode:l.exitCode,reason:l.reason}))})}return c(r)}catch(t){const r=p(C(t));return d(new u(`Failed to describe tasks: ${r}`,"unknown",void 0,{clusterArn:n,taskCount:s.length,error:t},!1))}}}export{u as EcsError,J as EcsService};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DeployCallbacks } from "./callbacks.js";
|
|
2
2
|
/**
|
|
3
|
-
* Every {@link DeployCallbacks} key (
|
|
3
|
+
* Every {@link DeployCallbacks} key (48 callbacks + the `verbose` flag),
|
|
4
4
|
* derived from the type-checked {@link CALLBACK_KEY_PRESENCE} map so the list
|
|
5
5
|
* can never silently diverge from the interface.
|
|
6
6
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e={onStepStart:!0,onStepComplete:!0,onProgress:!0,onLog:!0,onOutput:!0,onResourceProgress:!0,onParallelPhaseStart:!0,onParallelPhaseComplete:!0,onParallelStackResourceProgress:!0,onDockerProgress:!0,onBuildPushStart:!0,onBuildPushProgress:!0,onBuildPushComplete:!0,onTaskDefRegistered:!0,onECSUpdate:!0,onECSProgress:!0,onECSComplete:!0,onMigrationsStart:!0,onMigrationsComplete:!0,onCDKBootstrap:!0,onCdkOutput:!0,onCascadeStart:!0,onCascadeAccountsReconciled:!0,onOrgChangesDetected:!0,onCascadeMissingAccounts:!0,onCascadePhaseStart:!0,onCascadePhaseComplete:!0,onCascadeAccountStart:!0,onCascadeAccountPhaseChange:!0,onCascadeAccountResourceProgress:!0,onCascadeAccountComplete:!0,onCascadeComplete:!0,onCascadeLedger:!0,onTrailMigrationPhase:!0,onTrailLifecycleChanged:!0,onStackCleanupProgress:!0,onDetectionComplete:!0,onDetectionPhaseChange:!0,onStackTargets:!0,onSSOUrl:!0,onAuthComplete:!0,onOpenNextBuildStart:!0,onOpenNextProgress:!0,onOpenNextBuildComplete:!0,onOpenNextBuildError:!0,onFailureAnalysis:!0,onError:!0,verbose:!0},t=Object.keys(e);export{t as ALL_CALLBACK_KEYS};
|
|
1
|
+
const e={onStepStart:!0,onStepComplete:!0,onProgress:!0,onLog:!0,onOutput:!0,onResourceProgress:!0,onParallelPhaseStart:!0,onParallelPhaseComplete:!0,onParallelStackResourceProgress:!0,onDockerProgress:!0,onBuildPushStart:!0,onBuildPushProgress:!0,onBuildPushComplete:!0,onTaskDefRegistered:!0,onECSUpdate:!0,onECSProgress:!0,onECSComplete:!0,onMigrationsStart:!0,onMigrationsComplete:!0,onCDKBootstrap:!0,onCdkOutput:!0,onCascadeStart:!0,onCascadeAccountsReconciled:!0,onOrgChangesDetected:!0,onCascadeMissingAccounts:!0,onCascadePhaseStart:!0,onCascadePhaseComplete:!0,onCascadeAccountStart:!0,onCascadeAccountPhaseChange:!0,onCascadeAccountResourceProgress:!0,onCascadeAccountComplete:!0,onCascadeComplete:!0,onCascadeLedger:!0,onTrailMigrationPhase:!0,onTrailLifecycleChanged:!0,onStackCleanupProgress:!0,onDetectionComplete:!0,onDetectionPhaseChange:!0,onStackTargets:!0,onSSOUrl:!0,onAuthComplete:!0,onOpenNextBuildStart:!0,onOpenNextProgress:!0,onOpenNextBuildComplete:!0,onOpenNextBuildError:!0,onFailureAnalysis:!0,onDeploymentFailure:!0,onError:!0,verbose:!0},t=Object.keys(e);export{t as ALL_CALLBACK_KEYS};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProgressEvent, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhaseEvent } from "./events.js";
|
|
2
2
|
import type { TrailLifecycleState } from "@fjall/util/config";
|
|
3
|
+
import type { DeploymentFailure } from "@fjall/util";
|
|
3
4
|
import type { FailureAnalysis } from "@fjall/util/aws";
|
|
4
5
|
import type { DetectionResult } from "./detection/detection.js";
|
|
5
6
|
import type { CascadeLedger } from "../orchestration/organisation/cascadeSummary.js";
|
|
@@ -275,6 +276,16 @@ export interface DeployCallbacks {
|
|
|
275
276
|
* webapp). Pairs with `onError`, which still carries the terminal Error.
|
|
276
277
|
*/
|
|
277
278
|
onFailureAnalysis?: (analysis: FailureAnalysis) => void;
|
|
279
|
+
/**
|
|
280
|
+
* @emittedBy engine — fired once at terminal failure with the classified
|
|
281
|
+
* `DeploymentFailure` record (taxonomy code/phase/fault, provider layer,
|
|
282
|
+
* remediation, excerpt; aiDocs design 2026-08-10-deployment-failure-taxonomy
|
|
283
|
+
* § 3). Sibling to `onFailureAnalysis`, which it will eventually subsume —
|
|
284
|
+
* the CFN analysis nests inside the record's `analysis` field. The same
|
|
285
|
+
* record is attached to the terminal Result error and read back via
|
|
286
|
+
* `getDeploymentFailure`.
|
|
287
|
+
*/
|
|
288
|
+
onDeploymentFailure?: (failure: DeploymentFailure) => void;
|
|
278
289
|
/** @emittedBy engine */
|
|
279
290
|
onError?: (error: Error) => void;
|
|
280
291
|
verbose?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var d=Object.defineProperty;var n=(t,e)=>d(t,"name",{value:e,configurable:!0});import{z as a}from"zod";import{randomBytes as f}from"crypto";import{readFile as m,writeFile as S,unlink as
|
|
1
|
+
var d=Object.defineProperty;var n=(t,e)=>d(t,"name",{value:e,configurable:!0});import{z as a}from"zod";import{randomBytes as f}from"crypto";import{readFile as m,writeFile as S,unlink as p,rename as g,mkdir as h}from"fs/promises";import{dirname as y,join as u}from"path";import{fileExists as F}from"@fjall/util/fsHelpers";import{logger as i}from"@fjall/util/logger";import{getErrorMessage as s,maskSensitiveOutput as w}from"@fjall/util";const j=a.object({hash:a.string(),deployedAt:a.string(),stackStatus:a.string().optional()}).strict(),x=a.object({cloudformationStackName:a.string(),hostedZoneId:a.string().optional(),directoryHash:a.string().optional()}).strict(),E=a.object({version:a.literal(1),lastDeployedAt:a.string().optional(),templateHashes:a.record(a.string(),j),domain:x.optional(),metadata:a.record(a.string(),a.unknown()).optional()}).strict(),A=".fjall-state.json";function c(t){return u(t,A)}n(c,"getStateFilePath");function b(t){return t.replace(/-/g,"")}n(b,"regionSuffix");function J(t,e,r){return u(t,`.fjall-state.cascade-${e}-${b(r)}.json`)}n(J,"getCascadeStateFilePath");async function H(t){if(!await F(t))return null;try{const e=await m(t,"utf-8"),r=JSON.parse(e),o=E.safeParse(r);return o.success?o.data:(i.debug("FjallState","State file failed schema validation",{path:t,issues:o.error.issues.map(l=>l.message)}),null)}catch(e){return i.debug("FjallState","Failed to read state file",{path:t,error:s(e)}),null}}n(H,"readStateFileAt");async function k(t,e){const r=`${t}.${Date.now()}-${f(4).toString("hex")}.tmp`;await h(y(t),{recursive:!0});try{await S(r,JSON.stringify(e,null,2),"utf-8"),await g(r,t)}catch(o){try{await p(r)}catch(l){i.debug("FjallState","Temp file cleanup failed (non-fatal)",{path:r,error:s(l)})}throw o}}n(k,"writeStateFileAt");async function M(t){return H(c(t))}n(M,"readStateFile");async function _(t,e){return k(c(t),e)}n(_,"writeStateFile");function z(){return{version:1,templateHashes:{}}}n(z,"createEmptyState");async function C(t){const e=c(t);try{await p(e)}catch(r){(typeof r=="object"&&r!==null&&"code"in r?r.code:void 0)!=="ENOENT"&&i.warn("FjallState","Failed to delete state file",{path:e,error:w(s(r))})}}n(C,"deleteStateFile");function L(t,e,r,o){return{...t,lastDeployedAt:new Date().toISOString(),templateHashes:{...t.templateHashes,[e]:{hash:r,deployedAt:new Date().toISOString(),...o!==void 0&&{stackStatus:o}}}}}n(L,"updateTemplateHash");export{E as FjallStateFileSchema,z as createEmptyState,C as deleteStateFile,J as getCascadeStateFilePath,c as getStateFilePath,M as readStateFile,H as readStateFileAt,b as regionSuffix,L as updateTemplateHash,_ as writeStateFile,k as writeStateFileAt};
|
|
@@ -73,6 +73,21 @@ export interface ECSCompleteEvent {
|
|
|
73
73
|
reason?: string;
|
|
74
74
|
finalRunningCount?: number;
|
|
75
75
|
finalDesiredCount?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Structured forensics for the failure classifier (mirrors how
|
|
78
|
+
* MigrationsCompleteEvent keeps exitCode alongside reason — the prose
|
|
79
|
+
* `reason` alone destroys stopCode/rolloutState for downstream consumers).
|
|
80
|
+
*/
|
|
81
|
+
/** Rollout state of the supervised deployment when monitoring ended ("FAILED" = circuit breaker verdict). */
|
|
82
|
+
rolloutState?: string;
|
|
83
|
+
/** True when ECS replaced the in-flight deployment before it completed. */
|
|
84
|
+
replaced?: boolean;
|
|
85
|
+
/** Distinct tasks from the new revision that stopped during the rollout. */
|
|
86
|
+
stoppedTaskCount?: number;
|
|
87
|
+
/** ECS stopCode of the most recent stopped task (e.g. "TaskFailedToStart"). */
|
|
88
|
+
stopCode?: string;
|
|
89
|
+
/** stoppedReason of the most recent stopped task, masked at emit. */
|
|
90
|
+
stoppedReason?: string;
|
|
76
91
|
}
|
|
77
92
|
export interface MigrationsStartEvent {
|
|
78
93
|
family: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/deploy-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.1.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fjall-tech/fjall.git",
|
|
@@ -96,15 +96,15 @@
|
|
|
96
96
|
"@aws-sdk/client-ssm": "^3.1098.0",
|
|
97
97
|
"@aws-sdk/client-sso-admin": "^3.1098.0",
|
|
98
98
|
"@aws-sdk/client-sts": "^3.1098.0",
|
|
99
|
-
"@fjall/generator": "^
|
|
100
|
-
"@fjall/util": "^
|
|
99
|
+
"@fjall/generator": "^10.1.1",
|
|
100
|
+
"@fjall/util": "^10.1.1",
|
|
101
101
|
"@smithy/node-http-handler": "^4.9.13",
|
|
102
102
|
"aws-cdk": "^2.1134.0",
|
|
103
103
|
"tsx": "^4.23.1",
|
|
104
104
|
"zod": "^4.4.3"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
|
-
"@fjall/components-infrastructure": ">=
|
|
107
|
+
"@fjall/components-infrastructure": ">=10.0.0 <11.0.0"
|
|
108
108
|
},
|
|
109
109
|
"peerDependenciesMeta": {
|
|
110
110
|
"@fjall/components-infrastructure": {
|