@fjall/deploy-core 2.29.0 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.minified +1 -1
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/application/applicationDeploy.js +1 -1
- package/dist/src/orchestration/application/dockerBuildHelper.js +1 -1
- package/dist/src/orchestration/application/openNextBuild.d.ts +1 -1
- package/dist/src/orchestration/application/openNextBuild.js +3 -3
- package/dist/src/orchestration/builders/frameworkRegistry.js +1 -1
- package/dist/src/orchestration/builders/index.d.ts +1 -0
- package/dist/src/orchestration/builders/index.js +1 -1
- package/dist/src/orchestration/builders/openNextBuilder.js +1 -1
- package/dist/src/orchestration/builders/staticSiteBuilder.d.ts +27 -0
- package/dist/src/orchestration/builders/staticSiteBuilder.js +2 -0
- package/dist/src/orchestration/spawnHelpers.d.ts +9 -0
- package/dist/src/orchestration/spawnHelpers.js +1 -1
- package/dist/src/types/deployEvent.d.ts +10 -3
- package/dist/src/types/deployEvent.js +1 -1
- package/dist/src/types/detection/patternTypes.d.ts +9 -4
- package/dist/src/types/detection/patternTypes.js +1 -1
- package/dist/src/types/frameworkBuilder.d.ts +14 -0
- package/dist/src/types/index.d.ts +36 -2
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/operations.d.ts +2 -1
- package/package.json +5 -4
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
214 files minified at 2026-07-15T07:08:50.570Z
|
package/dist/src/index.d.ts
CHANGED
|
@@ -32,7 +32,9 @@ export type { RemediationVerbWithSurgery } from "./types/index.js";
|
|
|
32
32
|
export type { DriftVerdict, DriftSuspect, DriftFinding, DriftJournalRecord } from "./types/index.js";
|
|
33
33
|
export type { StepId, InfrastructureStepName, StepDefinition, StepDeploymentType, Operation, StepContext } from "./types/index.js";
|
|
34
34
|
export type { DeploymentContext, StepOutput, ApplicationDeploymentContext, CallerIdentity, StackOutput, StackOutputsRecord, ValidationResult, DetectionResult, ProgressCallbacks, ApplicationStack, OrganisationType, DeploymentOperation, ApplicationOperation, OrganisationOperation, DeployOrderOptions, ParallelDeployGroupKey, ParallelDestroyGroupKey, OpenNextPattern, AppResourceFlags, ParallelDeploymentResult, ParallelDeployGroup, ParallelOperation, ParallelOperationType, ParallelOperationState, ApplicationErrorType, StackDeploymentData, StackDeploymentOptions, ApplicationDeploymentData, ApplicationDestructionData, FjallStateFile, TemplateHashEntry } from "./types/index.js";
|
|
35
|
-
export { ProgressReporter, APPLICATION_STACKS, ORGANISATION_TYPES, APPLICATION_DEPLOY_ORDER, APPLICATION_DESTROY_ORDER, OPENNEXT_DEPLOY_ORDER, OPENNEXT_DESTROY_ORDER, PARALLEL_DEPLOY_GROUPS, PARALLEL_DESTROY_GROUPS, OPENNEXT_PARALLEL_GROUPS, PARALLEL_OPERATION_TYPES, isApplicationOperation, isOrganisationOperation, getParallelDeployGroups, getParallelDestroyGroups, getApplicationDeployOrder, getApplicationDestroyOrder, getApplicationStackName, getOrganisationStackName, isApplicationStack, isQuarantineDetail, isRetainedBucketsDetail, getApplicationStepName, getApplicationStepId, toPascalCase, isOpenNextPattern, OPENNEXT_PATTERNS,
|
|
35
|
+
export { ProgressReporter, APPLICATION_STACKS, ORGANISATION_TYPES, APPLICATION_DEPLOY_ORDER, APPLICATION_DESTROY_ORDER, OPENNEXT_DEPLOY_ORDER, OPENNEXT_DESTROY_ORDER, PARALLEL_DEPLOY_GROUPS, PARALLEL_DESTROY_GROUPS, OPENNEXT_PARALLEL_GROUPS, PARALLEL_OPERATION_TYPES, isApplicationOperation, isOrganisationOperation, getParallelDeployGroups, getParallelDestroyGroups, getApplicationDeployOrder, getApplicationDestroyOrder, getApplicationStackName, getOrganisationStackName, isApplicationStack, isQuarantineDetail, isRetainedBucketsDetail, getApplicationStepName, getApplicationStepId, toPascalCase, isOpenNextPattern, OPENNEXT_PATTERNS, STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME, ApplicationError, wrapApplicationError, stubCallerIdentity } from "./types/index.js";
|
|
36
|
+
export { deriveResourcesFromManifestStacks } from "./types/detection/patternDetection.js";
|
|
37
|
+
export { FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, regionSuffix } from "./types/config/FjallState.js";
|
|
36
38
|
export { CloudFormationEventMonitor } from "./aws/index.js";
|
|
37
39
|
export type { AwsClientLike, EventLogWriter, EventFailureAnalyser, EventLogWriterFactory, EventMonitorDeps } from "./aws/index.js";
|
|
38
40
|
export { CdkService, CdkArgumentBuilder, CdkProcessManager, CdkEventMonitor, startStackMonitoring, DEFAULT_DEPLOY_TIMEOUT_MS, isCdkError, formatInfrastructureError, getStructuralHint, getSourceContext, hasCdkDifferences, parseDiffOutput, CloudFormationService, CloudFormationError, EcsService, EcsError, EcsServiceResolver, type CfnExportsClient, TemplateHashService, TemplateHashError, type TemplateComparisonResult, CdkContextBuilder, emitProgress, PROGRESS_MESSAGES, parseBuildPhase, buildStepContextBuildConfig, convertCloudFormationOutputsToRecord, type CloudFormationOutput, ApplicationStackService } from "./services/index.js";
|
|
@@ -81,7 +83,7 @@ export { resolveBuildSecrets, resolveSecretRefValue, resolveBuildSecretSessionPr
|
|
|
81
83
|
export type { ResolveBuildArgsContext, ResolveBuildArgsResult, SourcedBuildArgResolver, BuildSecretRef, BuildSecretSessionContext, DeploySessionContext, ValidateBuildGroupInput, BuildGroupMemberInputs } from "./orchestration/index.js";
|
|
82
84
|
export type { FrameworkBuilder, FrameworkDetection, BuildPlan, BuildCommand, BuildCallbacks, DetectionContext, BuildOptions } from "./types/index.js";
|
|
83
85
|
export { FrameworkRegistry, type ResolvedBuilder } from "./orchestration/index.js";
|
|
84
|
-
export { openNextBuilder, dockerBuilder } from "./orchestration/index.js";
|
|
86
|
+
export { openNextBuilder, staticSiteBuilder, dockerBuilder } from "./orchestration/index.js";
|
|
85
87
|
export { StepRegistry, getDestroyStepId } from "./steps/index.js";
|
|
86
88
|
export { buildDeployPlan, computeDeployPlan, computeAssemblyDigest, digestHead, classifyImpact, derivePropertyChanges, isDataLoss, isStatefulResourceType, renderPlanSummary, renderPlanLines, toWirePlanChanges, signApprovalToken, verifyApprovalToken, DEFAULT_APPROVAL_TTL_MS, APPROVAL_TOKEN_PATTERN, runApprovalGate } from "./orchestration/index.js";
|
|
87
89
|
export type { DeployPlan, DeployPlanResourceChange, StackTemplatePair, CfnTemplateReader, ComputeDeployPlanParams, ComputeDeployPlanStack, ImpactClassification, SignApprovalTokenOptions, SignedApprovalToken, VerifyApprovalTokenOptions, VerifyApprovalTokenResult, RunApprovalGateParams, ApprovalGateOutcome } from "./orchestration/index.js";
|
package/dist/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as o,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as i,DEPLOYMENT_EVENT_STATUS_REASON_MAX as a,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as s,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as n,CASCADE_PHASES as c,CASCADE_ACCOUNT_STATUSES as E}from"./types/index.js";import{DeployEventSchema as l,StepProgressSchema as T,DeployResourceSchema as p,PlanChangeSchema as A,PlanPropertyChangeSchema as R,ChangeCountsSchema as _,DEPLOY_EVENT_CONTRACT as m,DEPLOY_EVENT_CONTRACT_MAJOR as u,DEPLOY_EVENT_CONTRACT_MINOR as d,SUPPORTED_CONTRACT_MARKERS as P,DEPLOY_EVENT_ID_MAX as O,DEPLOY_EVENT_NAME_MAX as D,DEPLOY_EVENT_MESSAGE_MAX as f,DEPLOY_EVENT_STATUS_REASON_MAX as C,DEPLOY_EVENT_ERROR_MESSAGE_MAX as N,DEPLOY_EVENT_TRAIL_DETAIL_MAX as g,DEPLOY_EVENT_OUTPUT_MAX as L,DEPLOY_EVENT_ARN_MAX as I,DEPLOY_EVENT_URL_MAX as y,STEP_COMPLETE_STATUSES as h,LOG_LEVELS as v,STACK_CLEANUP_PHASES as x,CASCADE_ACCOUNT_PHASES as F,DEPLOY_RESULTS as M,DETECTION_PHASES as U,PHASE_STATUSES as k,BUILDERS as b,CASCADE_OUTCOME_RESULTS as V,PLAN_ACTIONS as Y,REPLACEMENT_MODES as B,APPROVAL_KINDS as G,APPROVAL_DECISIONS as K,ALL_PROGRESS_KINDS as X,createDeployEmitter as H,parseDeployEvent as J,parseDeployContractVersion as w}from"./types/index.js";import{SimpleAwsProvider as Q}from"./aws/index.js";import{checkTargetReadiness as q,describeTargetReadinessReason as Z,buildTargetUnreadyAdvisory as z,buildTargetSetUnreadyAdvisory as $,probeAccountStackExists as ee}from"./aws/index.js";import{checkRegionEnabled as te,regionDisabledMessage as oe}from"./aws/index.js";import{ensureOrganisationExists as ae,describeOrganisation as se,enablePolicyTypes as ne,enableServiceAccess as ce,SERVICE_PRINCIPALS as Ee,enableRamSharing as Se,activateTrustedAccess as le,enableIpamDelegatedAdmin as Te,updateBackupGlobalSettings as pe,listAccounts as Ae,findAccount as Re,createAccount as _e,ensureOrganisationalUnitsExist as me,placeAccountsInOUs as ue,buildAccountToOUMap as de,findDevelopmentOuId as Pe,activateCostAllocationTags as Oe,checkIdentityCentreStatus as De,snapshotIdentityCentre as fe,composeSdkAbortSignal as Ce,extractErrorName as Ne,isAborted as ge,DEFAULT_MAX_PAGES as Le,IDENTITY_STORE_PAGE_SIZE as Ie,drainPages as ye,isOULeaf as he,registerSecurityDelegates as ve,SECURITY_SERVICE_PRINCIPALS as xe,enableCentralisedRootAccess as Fe,ROOT_ACCESS_FEATURES as Me,RootAccessEnablementError as Ue}from"./aws/index.js";import{STEP_IDS as be,STEP_NAMES as Ve,INFRASTRUCTURE_STEP_NAMES as Ye,INFRA_STEP_NAME as Be}from"./types/index.js";import{RemediationVerbSchema as Ke,REMEDIATION_VERB_GLOSS as Xe,DestructionFindingSchema as He,DestructionTicketResourceSchema as Je,DestructionTicketSchema as we,DestructionConsentSchema as je,DestructionOutcomeSchema as Qe,DESTRUCTION_FINDINGS as We,CONSENT_VERDICTS as qe,TICKET_VERDICT_SOURCES as Ze,TicketVerdictSourceSchema as ze}from"./types/index.js";import{DRIFT_VERDICTS as er,DriftVerdictSchema as rr,DriftSuspectSchema as tr,DriftFindingSchema as or,DriftJournalRecordSchema as ir,verbsForDriftVerdict as ar}from"./types/index.js";import{REMEDIATION_PHASES as nr,RemediationPhaseSchema as cr,RemediationTargetSchema as Er,RemediationFlipProofSchema as Sr,RemediationJournalRecordSchema as lr,RemediationVerbWithSurgerySchema as Tr,remediationPhaseRank as pr,remediationPlaceholderPhysicalId as Ar,isRemediationPlaceholderPhysicalId as Rr}from"./types/index.js";import{ProgressReporter as mr,APPLICATION_STACKS as ur,ORGANISATION_TYPES as dr,APPLICATION_DEPLOY_ORDER as Pr,APPLICATION_DESTROY_ORDER as Or,OPENNEXT_DEPLOY_ORDER as Dr,OPENNEXT_DESTROY_ORDER as fr,PARALLEL_DEPLOY_GROUPS as Cr,PARALLEL_DESTROY_GROUPS as Nr,OPENNEXT_PARALLEL_GROUPS as gr,PARALLEL_OPERATION_TYPES as Lr,isApplicationOperation as Ir,isOrganisationOperation as yr,getParallelDeployGroups as hr,getParallelDestroyGroups as vr,getApplicationDeployOrder as xr,getApplicationDestroyOrder as Fr,getApplicationStackName as Mr,getOrganisationStackName as Ur,isApplicationStack as kr,isQuarantineDetail as br,isRetainedBucketsDetail as Vr,getApplicationStepName as Yr,getApplicationStepId as Br,toPascalCase as Gr,isOpenNextPattern as Kr,OPENNEXT_PATTERNS as Xr,deriveResourcesFromManifestStacks as Hr,STACK_NOT_FOUND_PATTERN as Jr,STACK_FAILED_STATE_PATTERN as wr,CDK_NO_STACKS_MATCH as jr,INFRASTRUCTURE_FILENAME as Qr,ApplicationError as Wr,wrapApplicationError as qr,FjallStateFileSchema as Zr,readStateFile as zr,writeStateFile as $r,createEmptyState as et,deleteStateFile as rt,updateTemplateHash as tt,getStateFilePath as ot,stubCallerIdentity as it}from"./types/index.js";import{CloudFormationEventMonitor as st}from"./aws/index.js";import{CdkService as ct,CdkArgumentBuilder as Et,CdkProcessManager as St,CdkEventMonitor as lt,startStackMonitoring as Tt,DEFAULT_DEPLOY_TIMEOUT_MS as pt,isCdkError as At,formatInfrastructureError as Rt,getStructuralHint as _t,getSourceContext as mt,hasCdkDifferences as ut,parseDiffOutput as dt,CloudFormationService as Pt,CloudFormationError as Ot,EcsService as Dt,EcsError as ft,EcsServiceResolver as Ct,TemplateHashService as Nt,TemplateHashError as gt,CdkContextBuilder as Lt,emitProgress as It,PROGRESS_MESSAGES as yt,parseBuildPhase as ht,buildStepContextBuildConfig as vt,convertCloudFormationOutputsToRecord as xt,ApplicationStackService as Ft}from"./services/index.js";import{CdkError as Ut}from"./types/errors/index.js";import{BaseServiceError as bt,ValidationError as Vt,AuthError as Yt,AwsError as Bt,DeploymentError as Gt,NetworkError as Kt,FileSystemError as Xt,ConfigError as Ht,toServiceError as Jt}from"./types/errors/index.js";import{filterDangerousEnvVars as jt,maskSensitiveOutput as Qt,parseShellArgs as Wt,sleep as qt}from"@fjall/util";import{artefactOutputKey as zt,DeployModeSchema as $t,ServiceArtefactSchema as eo,ServiceArtefactsSchema as ro}from"@fjall/util";import{hasDockerfile as oo}from"./util/dockerfileDetection.js";import{sleepAbortable as ao}from"./util/sleepAbortable.js";import{createSequencedCallbacks as no}from"./util/sequencedCallbacks.js";import{fileExists as Eo}from"@fjall/util/fsHelpers";import{success as lo,failure as To,isSuccess as po,isFailure as Ao}from"@fjall/generator";import{deploy as _o}from"./orchestration/index.js";import{destroy as uo}from"./orchestration/index.js";import{restart as Oo,probeSecretsDrift as Do,computeSecretsDrift as fo,deriveStaleParameters as Co,extractConsumedSsmParameters as No}from"./orchestration/index.js";import{partitionAccounts as Lo}from"./orchestration/index.js";import{buildRegionList as yo,buildAccountRegionPairs as ho,cascadeHomeRegion as vo,cascadeOperationKey as xo}from"./orchestration/index.js";import{projectScalarSummary as Mo,projectAccountRows as Uo}from"./orchestration/index.js";import{reconcileProviderAccounts as bo,mergeReconciledProviderAccounts as Vo}from"./orchestration/index.js";import{decideNextTransition as Bo,reconcileTrailMigration as Go,decommissionMemberTrailStorage as Ko,ORG_TRAIL_BUCKET_OUTPUT_KEY as Xo,TRAIL_BUCKET_OUTPUT_KEY as Ho,TRAIL_KEY_ARN_OUTPUT_KEY as Jo}from"./orchestration/index.js";import{classifyDriftFailure as jo,fetchLastOperationEvents as Qo,DriftProbe as Wo,clearDriftSuspects as qo,defaultDriftJournalDir as Zo,readDriftSuspects as zo,recordDriftSuspects as $o,detectStackDrift as ei,runDriftPreFlight as ri,formatDriftPreFlightBlock as ti,DRIFT_PREFLIGHT_TRIGGER_STATUSES as oi,DRIFT_PREFLIGHT_BUDGET_MS as ii}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as si,computeRemediationOpId as ni,defaultRemediationJournalDir as ci,findRemediationJournalByOpId as Ei,listActiveRemediationOps as Si,listActiveRemediationOpsForContext as li,readRemediationJournal as Ti,sweepExpiredRemediationJournals as pi,writeRemediationJournal as Ai,REMEDIATION_JOURNAL_RETENTION_DAYS as Ri,captureRemediationForensics as _i,defaultRemediationForensicsDir as mi,applyRetainFlip as ui,composeFlipCapabilities as di,computeTemplateDigest as Pi,deriveRetainFlipTemplate as Oi,findMarkedResourcesByOpId as Di,proveFlipMetadataOnly as fi,readRetainFlipState as Ci,verifyRetainFlipDiff as Ni,FORGET_MARKER_KEY as gi,FORGET_FLIP_SPEC as Li,RECREATE_MARKER_KEY as Ii,assessForgetResumability as yi,completeForgetAfterConverge as hi,completeForgetAfterDeploy as vi,formatRecreateInFlightCures as xi,partitionPreFlightByRemediation as Fi,runForgetSurgery as Mi,synthTemplateDeclaresResource as Ui,runRecreateSurgery as ki,snapshotPolicyForType as bi,SNAPSHOT_CAPABLE_RESOURCE_TYPES as Vi,runRecreatePreFlight as Yi,deriveRemovalTemplate as Bi,findRemovalDeletionFailures as Gi,proveRemovalTargetsOnly as Ki,advertisableDriftVerbs as Xi,buildDriftRepairTicket as Hi,runDriftRepairGate as Ji,formatPinOutcomeDetail as wi,pinProbeCoverage as ji,renderPinReportLines as Qi,runPinRemediation as Wi,composePostFailureRepairOffer as qi,formatDriftRepairOffer as Zi,DriftRepairAvailableError as zi,checkDeployPathStackAvailability as $i,isDeployPathBlockingStatus as ea,StackUnavailableError as ra,assertLeaseBeforeStack as ta,LeaseDeniedError as oa}from"./orchestration/index.js";import{unlockBucket as aa,unlockQueue as sa}from"./orchestration/index.js";import{triageBucketPolicy as ca,isEnforceSslStatement as Ea,toResourcePolicyStatements as Sa,restoreBucketPolicy as la,synthesiseEnforceSslDocument as Ta,ensureEnforceSsl as pa,restoreAndReconcileQuarantinedBucket as Aa}from"./orchestration/index.js";import{verifyOrgTrailDelivery as _a}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as ua,isRootTaskPolicyArn as da,ROOT_TASK_POLICY_ARNS as Pa,MAX_ROOT_SESSION_SECONDS as Oa}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as fa,flattenAccountsToEnvironments as Ca,extractAllAccountNames as Na,accountsConfigToOUTree as ga,isStringArray as La,isAccountsConfig as Ia,isOuOnlyAccountBucket as ya,OU_ONLY_ACCOUNT_BUCKETS as ha}from"./orchestration/index.js";import{runOpenNextBuild as xa}from"./orchestration/index.js";import{runOrganisationSetup as Ma,ORG_SETUP_PHASES as Ua}from"./orchestration/index.js";import{resolveBuildSecrets as ba,resolveSecretRefValue as Va,resolveBuildSecretSessionProvider as Ya,sourcedRefsFromBuildArgs as Ba,resolveBuildArgs as Ga,buildBuildSecretSessionPolicy as Ka,buildDeploySessionPolicy as Xa,partitionForRegion as Ha,validateBuildGroup as Ja}from"./orchestration/index.js";import{FrameworkRegistry as ja}from"./orchestration/index.js";import{openNextBuilder as Wa,dockerBuilder as qa}from"./orchestration/index.js";import{StepRegistry as za,getDestroyStepId as $a}from"./steps/index.js";import{buildDeployPlan as rs,computeDeployPlan as ts,computeAssemblyDigest as os,digestHead as is,classifyImpact as as,derivePropertyChanges as ss,isDataLoss as ns,isStatefulResourceType as cs,renderPlanSummary as Es,renderPlanLines as Ss,toWirePlanChanges as ls,signApprovalToken as Ts,verifyApprovalToken as ps,DEFAULT_APPROVAL_TTL_MS as As,APPROVAL_TOKEN_PATTERN as Rs,runApprovalGate as _s}from"./orchestration/index.js";import{runDestructionGate as us,buildDestructionTicket as ds,evaluateDestructionConsents as Ps,computeTicketDigest as Os,legalRemediationVerbs as Ds,executableRemediationVerbs as fs,advertisableRemediationVerbs as Cs,renderDestructionTicketLines as Ns,renderConsentVerdictLines as gs,loadDeployPlan as Ls,createMemoisedPlanLoader as Is}from"./orchestration/index.js";export{X as ALL_PROGRESS_KINDS,Pr as APPLICATION_DEPLOY_ORDER,Or as APPLICATION_DESTROY_ORDER,ur as APPLICATION_STACKS,K as APPROVAL_DECISIONS,G as APPROVAL_KINDS,Rs as APPROVAL_TOKEN_PATTERN,Wr as ApplicationError,Ft as ApplicationStackService,Yt as AuthError,Bt as AwsError,b as BUILDERS,bt as BaseServiceError,F as CASCADE_ACCOUNT_PHASES,E as CASCADE_ACCOUNT_STATUSES,V as CASCADE_OUTCOME_RESULTS,c as CASCADE_PHASES,jr as CDK_NO_STACKS_MATCH,qe as CONSENT_VERDICTS,Et as CdkArgumentBuilder,Lt as CdkContextBuilder,Ut as CdkError,lt as CdkEventMonitor,St as CdkProcessManager,ct as CdkService,_ as ChangeCountsSchema,Ot as CloudFormationError,st as CloudFormationEventMonitor,Pt as CloudFormationService,Ht as ConfigError,As as DEFAULT_APPROVAL_TTL_MS,pt as DEFAULT_DEPLOY_TIMEOUT_MS,Le as DEFAULT_MAX_PAGES,s as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,i as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,a as DEPLOYMENT_EVENT_STATUS_REASON_MAX,n as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,o as DEPLOYMENT_EVENT_TYPES,I as DEPLOY_EVENT_ARN_MAX,m as DEPLOY_EVENT_CONTRACT,u as DEPLOY_EVENT_CONTRACT_MAJOR,d as DEPLOY_EVENT_CONTRACT_MINOR,N as DEPLOY_EVENT_ERROR_MESSAGE_MAX,O as DEPLOY_EVENT_ID_MAX,f as DEPLOY_EVENT_MESSAGE_MAX,D as DEPLOY_EVENT_NAME_MAX,L as DEPLOY_EVENT_OUTPUT_MAX,C as DEPLOY_EVENT_STATUS_REASON_MAX,g as DEPLOY_EVENT_TRAIL_DETAIL_MAX,y as DEPLOY_EVENT_URL_MAX,M as DEPLOY_RESULTS,We as DESTRUCTION_FINDINGS,U as DETECTION_PHASES,ii as DRIFT_PREFLIGHT_BUDGET_MS,oi as DRIFT_PREFLIGHT_TRIGGER_STATUSES,er as DRIFT_VERDICTS,l as DeployEventSchema,$t as DeployModeSchema,p as DeployResourceSchema,Gt as DeploymentError,t as DeploymentEventSchema,je as DestructionConsentSchema,He as DestructionFindingSchema,Qe as DestructionOutcomeSchema,Je as DestructionTicketResourceSchema,we as DestructionTicketSchema,or as DriftFindingSchema,ir as DriftJournalRecordSchema,Wo as DriftProbe,zi as DriftRepairAvailableError,tr as DriftSuspectSchema,rr as DriftVerdictSchema,ft as EcsError,Dt as EcsService,Ct as EcsServiceResolver,Li as FORGET_FLIP_SPEC,gi as FORGET_MARKER_KEY,Xt as FileSystemError,Zr as FjallStateFileSchema,ja as FrameworkRegistry,Ie as IDENTITY_STORE_PAGE_SIZE,Qr as INFRASTRUCTURE_FILENAME,Ye as INFRASTRUCTURE_STEP_NAMES,Be as INFRA_STEP_NAME,v as LOG_LEVELS,oa as LeaseDeniedError,Oa as MAX_ROOT_SESSION_SECONDS,Kt as NetworkError,Dr as OPENNEXT_DEPLOY_ORDER,fr as OPENNEXT_DESTROY_ORDER,gr as OPENNEXT_PARALLEL_GROUPS,Xr as OPENNEXT_PATTERNS,dr as ORGANISATION_TYPES,Ua as ORG_SETUP_PHASES,Xo as ORG_TRAIL_BUCKET_OUTPUT_KEY,ha as OU_ONLY_ACCOUNT_BUCKETS,Cr as PARALLEL_DEPLOY_GROUPS,Nr as PARALLEL_DESTROY_GROUPS,Lr as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,Y as PLAN_ACTIONS,yt as PROGRESS_MESSAGES,A as PlanChangeSchema,R as PlanPropertyChangeSchema,mr as ProgressReporter,Ii as RECREATE_MARKER_KEY,Ri as REMEDIATION_JOURNAL_RETENTION_DAYS,nr as REMEDIATION_PHASES,Xe as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,Me as ROOT_ACCESS_FEATURES,Pa as ROOT_TASK_POLICY_ARNS,Sr as RemediationFlipProofSchema,lr as RemediationJournalRecordSchema,cr as RemediationPhaseSchema,Er as RemediationTargetSchema,Ke as RemediationVerbSchema,Tr as RemediationVerbWithSurgerySchema,Ue as RootAccessEnablementError,xe as SECURITY_SERVICE_PRINCIPALS,Ee as SERVICE_PRINCIPALS,Vi as SNAPSHOT_CAPABLE_RESOURCE_TYPES,x as STACK_CLEANUP_PHASES,wr as STACK_FAILED_STATE_PATTERN,Jr as STACK_NOT_FOUND_PATTERN,h as STEP_COMPLETE_STATUSES,be as STEP_IDS,Ve as STEP_NAMES,P as SUPPORTED_CONTRACT_MARKERS,eo as ServiceArtefactSchema,ro as ServiceArtefactsSchema,Q as SimpleAwsProvider,ra as StackUnavailableError,T as StepProgressSchema,za as StepRegistry,Ze as TICKET_VERDICT_SOURCES,Ho as TRAIL_BUCKET_OUTPUT_KEY,Jo as TRAIL_KEY_ARN_OUTPUT_KEY,gt as TemplateHashError,Nt as TemplateHashService,ze as TicketVerdictSourceSchema,Vt as ValidationError,ga as accountsConfigToOUTree,Oe as activateCostAllocationTags,le as activateTrustedAccess,Xi as advertisableDriftVerbs,Cs as advertisableRemediationVerbs,ui as applyRetainFlip,si as archiveCompletedRemediationJournal,zt as artefactOutputKey,ta as assertLeaseBeforeStack,yi as assessForgetResumability,ua as assumeRootForTask,ho as buildAccountRegionPairs,de as buildAccountToOUMap,Ka as buildBuildSecretSessionPolicy,rs as buildDeployPlan,Xa as buildDeploySessionPolicy,ds as buildDestructionTicket,Hi as buildDriftRepairTicket,yo as buildRegionList,vt as buildStepContextBuildConfig,$ as buildTargetSetUnreadyAdvisory,z as buildTargetUnreadyAdvisory,_i as captureRemediationForensics,vo as cascadeHomeRegion,xo as cascadeOperationKey,$i as checkDeployPathStackAvailability,De as checkIdentityCentreStatus,te as checkRegionEnabled,q as checkTargetReadiness,jo as classifyDriftFailure,as as classifyImpact,qo as clearDriftSuspects,hi as completeForgetAfterConverge,vi as completeForgetAfterDeploy,di as composeFlipCapabilities,qi as composePostFailureRepairOffer,Ce as composeSdkAbortSignal,os as computeAssemblyDigest,ts as computeDeployPlan,ni as computeRemediationOpId,fo as computeSecretsDrift,Pi as computeTemplateDigest,Os as computeTicketDigest,xt as convertCloudFormationOutputsToRecord,_e as createAccount,H as createDeployEmitter,et as createEmptyState,Is as createMemoisedPlanLoader,no as createSequencedCallbacks,Bo as decideNextTransition,Ko as decommissionMemberTrailStorage,Zo as defaultDriftJournalDir,mi as defaultRemediationForensicsDir,ci as defaultRemediationJournalDir,rt as deleteStateFile,_o as deploy,ss as derivePropertyChanges,Bi as deriveRemovalTemplate,Hr as deriveResourcesFromManifestStacks,Oi as deriveRetainFlipTemplate,Co as deriveStaleParameters,se as describeOrganisation,Z as describeTargetReadinessReason,uo as destroy,ei as detectStackDrift,is as digestHead,qa as dockerBuilder,ye as drainPages,It as emitProgress,Fe as enableCentralisedRootAccess,Te as enableIpamDelegatedAdmin,ne as enablePolicyTypes,Se as enableRamSharing,ce as enableServiceAccess,pa as ensureEnforceSsl,ae as ensureOrganisationExists,me as ensureOrganisationalUnitsExist,Ps as evaluateDestructionConsents,fs as executableRemediationVerbs,Na as extractAllAccountNames,No as extractConsumedSsmParameters,Ne as extractErrorName,To as failure,Qo as fetchLastOperationEvents,Eo as fileExists,jt as filterDangerousEnvVars,Re as findAccount,Pe as findDevelopmentOuId,Di as findMarkedResourcesByOpId,Ei as findRemediationJournalByOpId,Gi as findRemovalDeletionFailures,Ca as flattenAccountsToEnvironments,ti as formatDriftPreFlightBlock,Zi as formatDriftRepairOffer,Rt as formatInfrastructureError,wi as formatPinOutcomeDetail,xi as formatRecreateInFlightCures,xr as getApplicationDeployOrder,Fr as getApplicationDestroyOrder,Mr as getApplicationStackName,Br as getApplicationStepId,Yr as getApplicationStepName,$a as getDestroyStepId,Ur as getOrganisationStackName,hr as getParallelDeployGroups,vr as getParallelDestroyGroups,mt as getSourceContext,ot as getStateFilePath,_t as getStructuralHint,ut as hasCdkDifferences,oo as hasDockerfile,ge as isAborted,Ia as isAccountsConfig,Ir as isApplicationOperation,kr as isApplicationStack,At as isCdkError,ns as isDataLoss,ea as isDeployPathBlockingStatus,Ea as isEnforceSslStatement,Ao as isFailure,he as isOULeaf,Kr as isOpenNextPattern,yr as isOrganisationOperation,ya as isOuOnlyAccountBucket,br as isQuarantineDetail,Rr as isRemediationPlaceholderPhysicalId,Vr as isRetainedBucketsDetail,da as isRootTaskPolicyArn,cs as isStatefulResourceType,La as isStringArray,po as isSuccess,Ds as legalRemediationVerbs,Ae as listAccounts,Si as listActiveRemediationOps,li as listActiveRemediationOpsForContext,Ls as loadDeployPlan,Qt as maskSensitiveOutput,Vo as mergeReconciledProviderAccounts,Wa as openNextBuilder,fa as parseAccountsConfiguration,ht as parseBuildPhase,w as parseDeployContractVersion,J as parseDeployEvent,dt as parseDiffOutput,Wt as parseShellArgs,Lo as partitionAccounts,Ha as partitionForRegion,Fi as partitionPreFlightByRemediation,ji as pinProbeCoverage,ue as placeAccountsInOUs,ee as probeAccountStackExists,Do as probeSecretsDrift,Uo as projectAccountRows,Mo as projectScalarSummary,fi as proveFlipMetadataOnly,Ki as proveRemovalTargetsOnly,zo as readDriftSuspects,Ti as readRemediationJournal,Ci as readRetainFlipState,zr as readStateFile,bo as reconcileProviderAccounts,Go as reconcileTrailMigration,$o as recordDriftSuspects,oe as regionDisabledMessage,ve as registerSecurityDelegates,pr as remediationPhaseRank,Ar as remediationPlaceholderPhysicalId,gs as renderConsentVerdictLines,Ns as renderDestructionTicketLines,Qi as renderPinReportLines,Ss as renderPlanLines,Es as renderPlanSummary,Ga as resolveBuildArgs,Ya as resolveBuildSecretSessionProvider,ba as resolveBuildSecrets,Va as resolveSecretRefValue,Oo as restart,Aa as restoreAndReconcileQuarantinedBucket,la as restoreBucketPolicy,_s as runApprovalGate,us as runDestructionGate,ri as runDriftPreFlight,Ji as runDriftRepairGate,Mi as runForgetSurgery,xa as runOpenNextBuild,Ma as runOrganisationSetup,Wi as runPinRemediation,Yi as runRecreatePreFlight,ki as runRecreateSurgery,Ts as signApprovalToken,qt as sleep,ao as sleepAbortable,fe as snapshotIdentityCentre,bi as snapshotPolicyForType,Ba as sourcedRefsFromBuildArgs,Tt as startStackMonitoring,it as stubCallerIdentity,lo as success,pi as sweepExpiredRemediationJournals,Ui as synthTemplateDeclaresResource,Ta as synthesiseEnforceSslDocument,Gr as toPascalCase,Sa as toResourcePolicyStatements,Jt as toServiceError,ls as toWirePlanChanges,ca as triageBucketPolicy,aa as unlockBucket,sa as unlockQueue,pe as updateBackupGlobalSettings,tt as updateTemplateHash,Ja as validateBuildGroup,ar as verbsForDriftVerdict,ps as verifyApprovalToken,_a as verifyOrgTrailDelivery,Ni as verifyRetainFlipDiff,qr as wrapApplicationError,Ai as writeRemediationJournal,$r as writeStateFile};
|
|
1
|
+
import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as o,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as i,DEPLOYMENT_EVENT_STATUS_REASON_MAX as a,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as s,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as n,CASCADE_PHASES as c,CASCADE_ACCOUNT_STATUSES as E}from"./types/index.js";import{DeployEventSchema as l,StepProgressSchema as p,DeployResourceSchema as T,PlanChangeSchema as A,PlanPropertyChangeSchema as R,ChangeCountsSchema as _,DEPLOY_EVENT_CONTRACT as m,DEPLOY_EVENT_CONTRACT_MAJOR as u,DEPLOY_EVENT_CONTRACT_MINOR as d,SUPPORTED_CONTRACT_MARKERS as P,DEPLOY_EVENT_ID_MAX as O,DEPLOY_EVENT_NAME_MAX as D,DEPLOY_EVENT_MESSAGE_MAX as f,DEPLOY_EVENT_STATUS_REASON_MAX as C,DEPLOY_EVENT_ERROR_MESSAGE_MAX as N,DEPLOY_EVENT_TRAIL_DETAIL_MAX as g,DEPLOY_EVENT_OUTPUT_MAX as L,DEPLOY_EVENT_ARN_MAX as I,DEPLOY_EVENT_URL_MAX as y,STEP_COMPLETE_STATUSES as h,LOG_LEVELS as v,STACK_CLEANUP_PHASES as x,CASCADE_ACCOUNT_PHASES as F,DEPLOY_RESULTS as M,DETECTION_PHASES as U,PHASE_STATUSES as k,BUILDERS as b,CASCADE_OUTCOME_RESULTS as V,PLAN_ACTIONS as Y,REPLACEMENT_MODES as B,APPROVAL_KINDS as G,APPROVAL_DECISIONS as K,ALL_PROGRESS_KINDS as X,createDeployEmitter as H,parseDeployEvent as J,parseDeployContractVersion as w}from"./types/index.js";import{SimpleAwsProvider as Q}from"./aws/index.js";import{checkTargetReadiness as q,describeTargetReadinessReason as Z,buildTargetUnreadyAdvisory as z,buildTargetSetUnreadyAdvisory as $,probeAccountStackExists as ee}from"./aws/index.js";import{checkRegionEnabled as te,regionDisabledMessage as oe}from"./aws/index.js";import{ensureOrganisationExists as ae,describeOrganisation as se,enablePolicyTypes as ne,enableServiceAccess as ce,SERVICE_PRINCIPALS as Ee,enableRamSharing as Se,activateTrustedAccess as le,enableIpamDelegatedAdmin as pe,updateBackupGlobalSettings as Te,listAccounts as Ae,findAccount as Re,createAccount as _e,ensureOrganisationalUnitsExist as me,placeAccountsInOUs as ue,buildAccountToOUMap as de,findDevelopmentOuId as Pe,activateCostAllocationTags as Oe,checkIdentityCentreStatus as De,snapshotIdentityCentre as fe,composeSdkAbortSignal as Ce,extractErrorName as Ne,isAborted as ge,DEFAULT_MAX_PAGES as Le,IDENTITY_STORE_PAGE_SIZE as Ie,drainPages as ye,isOULeaf as he,registerSecurityDelegates as ve,SECURITY_SERVICE_PRINCIPALS as xe,enableCentralisedRootAccess as Fe,ROOT_ACCESS_FEATURES as Me,RootAccessEnablementError as Ue}from"./aws/index.js";import{STEP_IDS as be,STEP_NAMES as Ve,INFRASTRUCTURE_STEP_NAMES as Ye,INFRA_STEP_NAME as Be}from"./types/index.js";import{RemediationVerbSchema as Ke,REMEDIATION_VERB_GLOSS as Xe,DestructionFindingSchema as He,DestructionTicketResourceSchema as Je,DestructionTicketSchema as we,DestructionConsentSchema as je,DestructionOutcomeSchema as Qe,DESTRUCTION_FINDINGS as We,CONSENT_VERDICTS as qe,TICKET_VERDICT_SOURCES as Ze,TicketVerdictSourceSchema as ze}from"./types/index.js";import{DRIFT_VERDICTS as er,DriftVerdictSchema as rr,DriftSuspectSchema as tr,DriftFindingSchema as or,DriftJournalRecordSchema as ir,verbsForDriftVerdict as ar}from"./types/index.js";import{REMEDIATION_PHASES as nr,RemediationPhaseSchema as cr,RemediationTargetSchema as Er,RemediationFlipProofSchema as Sr,RemediationJournalRecordSchema as lr,RemediationVerbWithSurgerySchema as pr,remediationPhaseRank as Tr,remediationPlaceholderPhysicalId as Ar,isRemediationPlaceholderPhysicalId as Rr}from"./types/index.js";import{ProgressReporter as mr,APPLICATION_STACKS as ur,ORGANISATION_TYPES as dr,APPLICATION_DEPLOY_ORDER as Pr,APPLICATION_DESTROY_ORDER as Or,OPENNEXT_DEPLOY_ORDER as Dr,OPENNEXT_DESTROY_ORDER as fr,PARALLEL_DEPLOY_GROUPS as Cr,PARALLEL_DESTROY_GROUPS as Nr,OPENNEXT_PARALLEL_GROUPS as gr,PARALLEL_OPERATION_TYPES as Lr,isApplicationOperation as Ir,isOrganisationOperation as yr,getParallelDeployGroups as hr,getParallelDestroyGroups as vr,getApplicationDeployOrder as xr,getApplicationDestroyOrder as Fr,getApplicationStackName as Mr,getOrganisationStackName as Ur,isApplicationStack as kr,isQuarantineDetail as br,isRetainedBucketsDetail as Vr,getApplicationStepName as Yr,getApplicationStepId as Br,toPascalCase as Gr,isOpenNextPattern as Kr,OPENNEXT_PATTERNS as Xr,STACK_NOT_FOUND_PATTERN as Hr,STACK_FAILED_STATE_PATTERN as Jr,CDK_NO_STACKS_MATCH as wr,INFRASTRUCTURE_FILENAME as jr,ApplicationError as Qr,wrapApplicationError as Wr,stubCallerIdentity as qr}from"./types/index.js";import{deriveResourcesFromManifestStacks as zr}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as et,readStateFile as rt,writeStateFile as tt,createEmptyState as ot,deleteStateFile as it,updateTemplateHash as at,getStateFilePath as st,regionSuffix as nt}from"./types/config/FjallState.js";import{CloudFormationEventMonitor as Et}from"./aws/index.js";import{CdkService as lt,CdkArgumentBuilder as pt,CdkProcessManager as Tt,CdkEventMonitor as At,startStackMonitoring as Rt,DEFAULT_DEPLOY_TIMEOUT_MS as _t,isCdkError as mt,formatInfrastructureError as ut,getStructuralHint as dt,getSourceContext as Pt,hasCdkDifferences as Ot,parseDiffOutput as Dt,CloudFormationService as ft,CloudFormationError as Ct,EcsService as Nt,EcsError as gt,EcsServiceResolver as Lt,TemplateHashService as It,TemplateHashError as yt,CdkContextBuilder as ht,emitProgress as vt,PROGRESS_MESSAGES as xt,parseBuildPhase as Ft,buildStepContextBuildConfig as Mt,convertCloudFormationOutputsToRecord as Ut,ApplicationStackService as kt}from"./services/index.js";import{CdkError as Vt}from"./types/errors/index.js";import{BaseServiceError as Bt,ValidationError as Gt,AuthError as Kt,AwsError as Xt,DeploymentError as Ht,NetworkError as Jt,FileSystemError as wt,ConfigError as jt,toServiceError as Qt}from"./types/errors/index.js";import{filterDangerousEnvVars as qt,maskSensitiveOutput as Zt,parseShellArgs as zt,sleep as $t}from"@fjall/util";import{artefactOutputKey as ro,DeployModeSchema as to,ServiceArtefactSchema as oo,ServiceArtefactsSchema as io}from"@fjall/util";import{hasDockerfile as so}from"./util/dockerfileDetection.js";import{sleepAbortable as co}from"./util/sleepAbortable.js";import{createSequencedCallbacks as So}from"./util/sequencedCallbacks.js";import{fileExists as po}from"@fjall/util/fsHelpers";import{success as Ao,failure as Ro,isSuccess as _o,isFailure as mo}from"@fjall/generator";import{deploy as Po}from"./orchestration/index.js";import{destroy as Do}from"./orchestration/index.js";import{restart as Co,probeSecretsDrift as No,computeSecretsDrift as go,deriveStaleParameters as Lo,extractConsumedSsmParameters as Io}from"./orchestration/index.js";import{partitionAccounts as ho}from"./orchestration/index.js";import{buildRegionList as xo,buildAccountRegionPairs as Fo,cascadeHomeRegion as Mo,cascadeOperationKey as Uo}from"./orchestration/index.js";import{projectScalarSummary as bo,projectAccountRows as Vo}from"./orchestration/index.js";import{reconcileProviderAccounts as Bo,mergeReconciledProviderAccounts as Go}from"./orchestration/index.js";import{decideNextTransition as Xo,reconcileTrailMigration as Ho,decommissionMemberTrailStorage as Jo,ORG_TRAIL_BUCKET_OUTPUT_KEY as wo,TRAIL_BUCKET_OUTPUT_KEY as jo,TRAIL_KEY_ARN_OUTPUT_KEY as Qo}from"./orchestration/index.js";import{classifyDriftFailure as qo,fetchLastOperationEvents as Zo,DriftProbe as zo,clearDriftSuspects as $o,defaultDriftJournalDir as ei,readDriftSuspects as ri,recordDriftSuspects as ti,detectStackDrift as oi,runDriftPreFlight as ii,formatDriftPreFlightBlock as ai,DRIFT_PREFLIGHT_TRIGGER_STATUSES as si,DRIFT_PREFLIGHT_BUDGET_MS as ni}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as Ei,computeRemediationOpId as Si,defaultRemediationJournalDir as li,findRemediationJournalByOpId as pi,listActiveRemediationOps as Ti,listActiveRemediationOpsForContext as Ai,readRemediationJournal as Ri,sweepExpiredRemediationJournals as _i,writeRemediationJournal as mi,REMEDIATION_JOURNAL_RETENTION_DAYS as ui,captureRemediationForensics as di,defaultRemediationForensicsDir as Pi,applyRetainFlip as Oi,composeFlipCapabilities as Di,computeTemplateDigest as fi,deriveRetainFlipTemplate as Ci,findMarkedResourcesByOpId as Ni,proveFlipMetadataOnly as gi,readRetainFlipState as Li,verifyRetainFlipDiff as Ii,FORGET_MARKER_KEY as yi,FORGET_FLIP_SPEC as hi,RECREATE_MARKER_KEY as vi,assessForgetResumability as xi,completeForgetAfterConverge as Fi,completeForgetAfterDeploy as Mi,formatRecreateInFlightCures as Ui,partitionPreFlightByRemediation as ki,runForgetSurgery as bi,synthTemplateDeclaresResource as Vi,runRecreateSurgery as Yi,snapshotPolicyForType as Bi,SNAPSHOT_CAPABLE_RESOURCE_TYPES as Gi,runRecreatePreFlight as Ki,deriveRemovalTemplate as Xi,findRemovalDeletionFailures as Hi,proveRemovalTargetsOnly as Ji,advertisableDriftVerbs as wi,buildDriftRepairTicket as ji,runDriftRepairGate as Qi,formatPinOutcomeDetail as Wi,pinProbeCoverage as qi,renderPinReportLines as Zi,runPinRemediation as zi,composePostFailureRepairOffer as $i,formatDriftRepairOffer as ea,DriftRepairAvailableError as ra,checkDeployPathStackAvailability as ta,isDeployPathBlockingStatus as oa,StackUnavailableError as ia,assertLeaseBeforeStack as aa,LeaseDeniedError as sa}from"./orchestration/index.js";import{unlockBucket as ca,unlockQueue as Ea}from"./orchestration/index.js";import{triageBucketPolicy as la,isEnforceSslStatement as pa,toResourcePolicyStatements as Ta,restoreBucketPolicy as Aa,synthesiseEnforceSslDocument as Ra,ensureEnforceSsl as _a,restoreAndReconcileQuarantinedBucket as ma}from"./orchestration/index.js";import{verifyOrgTrailDelivery as da}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as Oa,isRootTaskPolicyArn as Da,ROOT_TASK_POLICY_ARNS as fa,MAX_ROOT_SESSION_SECONDS as Ca}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as ga,flattenAccountsToEnvironments as La,extractAllAccountNames as Ia,accountsConfigToOUTree as ya,isStringArray as ha,isAccountsConfig as va,isOuOnlyAccountBucket as xa,OU_ONLY_ACCOUNT_BUCKETS as Fa}from"./orchestration/index.js";import{runOpenNextBuild as Ua}from"./orchestration/index.js";import{runOrganisationSetup as ba,ORG_SETUP_PHASES as Va}from"./orchestration/index.js";import{resolveBuildSecrets as Ba,resolveSecretRefValue as Ga,resolveBuildSecretSessionProvider as Ka,sourcedRefsFromBuildArgs as Xa,resolveBuildArgs as Ha,buildBuildSecretSessionPolicy as Ja,buildDeploySessionPolicy as wa,partitionForRegion as ja,validateBuildGroup as Qa}from"./orchestration/index.js";import{FrameworkRegistry as qa}from"./orchestration/index.js";import{openNextBuilder as za,staticSiteBuilder as $a,dockerBuilder as es}from"./orchestration/index.js";import{StepRegistry as ts,getDestroyStepId as os}from"./steps/index.js";import{buildDeployPlan as as,computeDeployPlan as ss,computeAssemblyDigest as ns,digestHead as cs,classifyImpact as Es,derivePropertyChanges as Ss,isDataLoss as ls,isStatefulResourceType as ps,renderPlanSummary as Ts,renderPlanLines as As,toWirePlanChanges as Rs,signApprovalToken as _s,verifyApprovalToken as ms,DEFAULT_APPROVAL_TTL_MS as us,APPROVAL_TOKEN_PATTERN as ds,runApprovalGate as Ps}from"./orchestration/index.js";import{runDestructionGate as Ds,buildDestructionTicket as fs,evaluateDestructionConsents as Cs,computeTicketDigest as Ns,legalRemediationVerbs as gs,executableRemediationVerbs as Ls,advertisableRemediationVerbs as Is,renderDestructionTicketLines as ys,renderConsentVerdictLines as hs,loadDeployPlan as vs,createMemoisedPlanLoader as xs}from"./orchestration/index.js";export{X as ALL_PROGRESS_KINDS,Pr as APPLICATION_DEPLOY_ORDER,Or as APPLICATION_DESTROY_ORDER,ur as APPLICATION_STACKS,K as APPROVAL_DECISIONS,G as APPROVAL_KINDS,ds as APPROVAL_TOKEN_PATTERN,Qr as ApplicationError,kt as ApplicationStackService,Kt as AuthError,Xt as AwsError,b as BUILDERS,Bt as BaseServiceError,F as CASCADE_ACCOUNT_PHASES,E as CASCADE_ACCOUNT_STATUSES,V as CASCADE_OUTCOME_RESULTS,c as CASCADE_PHASES,wr as CDK_NO_STACKS_MATCH,qe as CONSENT_VERDICTS,pt as CdkArgumentBuilder,ht as CdkContextBuilder,Vt as CdkError,At as CdkEventMonitor,Tt as CdkProcessManager,lt as CdkService,_ as ChangeCountsSchema,Ct as CloudFormationError,Et as CloudFormationEventMonitor,ft as CloudFormationService,jt as ConfigError,us as DEFAULT_APPROVAL_TTL_MS,_t as DEFAULT_DEPLOY_TIMEOUT_MS,Le as DEFAULT_MAX_PAGES,s as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,i as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,a as DEPLOYMENT_EVENT_STATUS_REASON_MAX,n as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,o as DEPLOYMENT_EVENT_TYPES,I as DEPLOY_EVENT_ARN_MAX,m as DEPLOY_EVENT_CONTRACT,u as DEPLOY_EVENT_CONTRACT_MAJOR,d as DEPLOY_EVENT_CONTRACT_MINOR,N as DEPLOY_EVENT_ERROR_MESSAGE_MAX,O as DEPLOY_EVENT_ID_MAX,f as DEPLOY_EVENT_MESSAGE_MAX,D as DEPLOY_EVENT_NAME_MAX,L as DEPLOY_EVENT_OUTPUT_MAX,C as DEPLOY_EVENT_STATUS_REASON_MAX,g as DEPLOY_EVENT_TRAIL_DETAIL_MAX,y as DEPLOY_EVENT_URL_MAX,M as DEPLOY_RESULTS,We as DESTRUCTION_FINDINGS,U as DETECTION_PHASES,ni as DRIFT_PREFLIGHT_BUDGET_MS,si as DRIFT_PREFLIGHT_TRIGGER_STATUSES,er as DRIFT_VERDICTS,l as DeployEventSchema,to as DeployModeSchema,T as DeployResourceSchema,Ht as DeploymentError,t as DeploymentEventSchema,je as DestructionConsentSchema,He as DestructionFindingSchema,Qe as DestructionOutcomeSchema,Je as DestructionTicketResourceSchema,we as DestructionTicketSchema,or as DriftFindingSchema,ir as DriftJournalRecordSchema,zo as DriftProbe,ra as DriftRepairAvailableError,tr as DriftSuspectSchema,rr as DriftVerdictSchema,gt as EcsError,Nt as EcsService,Lt as EcsServiceResolver,hi as FORGET_FLIP_SPEC,yi as FORGET_MARKER_KEY,wt as FileSystemError,et as FjallStateFileSchema,qa as FrameworkRegistry,Ie as IDENTITY_STORE_PAGE_SIZE,jr as INFRASTRUCTURE_FILENAME,Ye as INFRASTRUCTURE_STEP_NAMES,Be as INFRA_STEP_NAME,v as LOG_LEVELS,sa as LeaseDeniedError,Ca as MAX_ROOT_SESSION_SECONDS,Jt as NetworkError,Dr as OPENNEXT_DEPLOY_ORDER,fr as OPENNEXT_DESTROY_ORDER,gr as OPENNEXT_PARALLEL_GROUPS,Xr as OPENNEXT_PATTERNS,dr as ORGANISATION_TYPES,Va as ORG_SETUP_PHASES,wo as ORG_TRAIL_BUCKET_OUTPUT_KEY,Fa as OU_ONLY_ACCOUNT_BUCKETS,Cr as PARALLEL_DEPLOY_GROUPS,Nr as PARALLEL_DESTROY_GROUPS,Lr as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,Y as PLAN_ACTIONS,xt as PROGRESS_MESSAGES,A as PlanChangeSchema,R as PlanPropertyChangeSchema,mr as ProgressReporter,vi as RECREATE_MARKER_KEY,ui as REMEDIATION_JOURNAL_RETENTION_DAYS,nr as REMEDIATION_PHASES,Xe as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,Me as ROOT_ACCESS_FEATURES,fa as ROOT_TASK_POLICY_ARNS,Sr as RemediationFlipProofSchema,lr as RemediationJournalRecordSchema,cr as RemediationPhaseSchema,Er as RemediationTargetSchema,Ke as RemediationVerbSchema,pr as RemediationVerbWithSurgerySchema,Ue as RootAccessEnablementError,xe as SECURITY_SERVICE_PRINCIPALS,Ee as SERVICE_PRINCIPALS,Gi as SNAPSHOT_CAPABLE_RESOURCE_TYPES,x as STACK_CLEANUP_PHASES,Jr as STACK_FAILED_STATE_PATTERN,Hr as STACK_NOT_FOUND_PATTERN,h as STEP_COMPLETE_STATUSES,be as STEP_IDS,Ve as STEP_NAMES,P as SUPPORTED_CONTRACT_MARKERS,oo as ServiceArtefactSchema,io as ServiceArtefactsSchema,Q as SimpleAwsProvider,ia as StackUnavailableError,p as StepProgressSchema,ts as StepRegistry,Ze as TICKET_VERDICT_SOURCES,jo as TRAIL_BUCKET_OUTPUT_KEY,Qo as TRAIL_KEY_ARN_OUTPUT_KEY,yt as TemplateHashError,It as TemplateHashService,ze as TicketVerdictSourceSchema,Gt as ValidationError,ya as accountsConfigToOUTree,Oe as activateCostAllocationTags,le as activateTrustedAccess,wi as advertisableDriftVerbs,Is as advertisableRemediationVerbs,Oi as applyRetainFlip,Ei as archiveCompletedRemediationJournal,ro as artefactOutputKey,aa as assertLeaseBeforeStack,xi as assessForgetResumability,Oa as assumeRootForTask,Fo as buildAccountRegionPairs,de as buildAccountToOUMap,Ja as buildBuildSecretSessionPolicy,as as buildDeployPlan,wa as buildDeploySessionPolicy,fs as buildDestructionTicket,ji as buildDriftRepairTicket,xo as buildRegionList,Mt as buildStepContextBuildConfig,$ as buildTargetSetUnreadyAdvisory,z as buildTargetUnreadyAdvisory,di as captureRemediationForensics,Mo as cascadeHomeRegion,Uo as cascadeOperationKey,ta as checkDeployPathStackAvailability,De as checkIdentityCentreStatus,te as checkRegionEnabled,q as checkTargetReadiness,qo as classifyDriftFailure,Es as classifyImpact,$o as clearDriftSuspects,Fi as completeForgetAfterConverge,Mi as completeForgetAfterDeploy,Di as composeFlipCapabilities,$i as composePostFailureRepairOffer,Ce as composeSdkAbortSignal,ns as computeAssemblyDigest,ss as computeDeployPlan,Si as computeRemediationOpId,go as computeSecretsDrift,fi as computeTemplateDigest,Ns as computeTicketDigest,Ut as convertCloudFormationOutputsToRecord,_e as createAccount,H as createDeployEmitter,ot as createEmptyState,xs as createMemoisedPlanLoader,So as createSequencedCallbacks,Xo as decideNextTransition,Jo as decommissionMemberTrailStorage,ei as defaultDriftJournalDir,Pi as defaultRemediationForensicsDir,li as defaultRemediationJournalDir,it as deleteStateFile,Po as deploy,Ss as derivePropertyChanges,Xi as deriveRemovalTemplate,zr as deriveResourcesFromManifestStacks,Ci as deriveRetainFlipTemplate,Lo as deriveStaleParameters,se as describeOrganisation,Z as describeTargetReadinessReason,Do as destroy,oi as detectStackDrift,cs as digestHead,es as dockerBuilder,ye as drainPages,vt as emitProgress,Fe as enableCentralisedRootAccess,pe as enableIpamDelegatedAdmin,ne as enablePolicyTypes,Se as enableRamSharing,ce as enableServiceAccess,_a as ensureEnforceSsl,ae as ensureOrganisationExists,me as ensureOrganisationalUnitsExist,Cs as evaluateDestructionConsents,Ls as executableRemediationVerbs,Ia as extractAllAccountNames,Io as extractConsumedSsmParameters,Ne as extractErrorName,Ro as failure,Zo as fetchLastOperationEvents,po as fileExists,qt as filterDangerousEnvVars,Re as findAccount,Pe as findDevelopmentOuId,Ni as findMarkedResourcesByOpId,pi as findRemediationJournalByOpId,Hi as findRemovalDeletionFailures,La as flattenAccountsToEnvironments,ai as formatDriftPreFlightBlock,ea as formatDriftRepairOffer,ut as formatInfrastructureError,Wi as formatPinOutcomeDetail,Ui as formatRecreateInFlightCures,xr as getApplicationDeployOrder,Fr as getApplicationDestroyOrder,Mr as getApplicationStackName,Br as getApplicationStepId,Yr as getApplicationStepName,os as getDestroyStepId,Ur as getOrganisationStackName,hr as getParallelDeployGroups,vr as getParallelDestroyGroups,Pt as getSourceContext,st as getStateFilePath,dt as getStructuralHint,Ot as hasCdkDifferences,so as hasDockerfile,ge as isAborted,va as isAccountsConfig,Ir as isApplicationOperation,kr as isApplicationStack,mt as isCdkError,ls as isDataLoss,oa as isDeployPathBlockingStatus,pa as isEnforceSslStatement,mo as isFailure,he as isOULeaf,Kr as isOpenNextPattern,yr as isOrganisationOperation,xa as isOuOnlyAccountBucket,br as isQuarantineDetail,Rr as isRemediationPlaceholderPhysicalId,Vr as isRetainedBucketsDetail,Da as isRootTaskPolicyArn,ps as isStatefulResourceType,ha as isStringArray,_o as isSuccess,gs as legalRemediationVerbs,Ae as listAccounts,Ti as listActiveRemediationOps,Ai as listActiveRemediationOpsForContext,vs as loadDeployPlan,Zt as maskSensitiveOutput,Go as mergeReconciledProviderAccounts,za as openNextBuilder,ga as parseAccountsConfiguration,Ft as parseBuildPhase,w as parseDeployContractVersion,J as parseDeployEvent,Dt as parseDiffOutput,zt as parseShellArgs,ho as partitionAccounts,ja as partitionForRegion,ki as partitionPreFlightByRemediation,qi as pinProbeCoverage,ue as placeAccountsInOUs,ee as probeAccountStackExists,No as probeSecretsDrift,Vo as projectAccountRows,bo as projectScalarSummary,gi as proveFlipMetadataOnly,Ji as proveRemovalTargetsOnly,ri as readDriftSuspects,Ri as readRemediationJournal,Li as readRetainFlipState,rt as readStateFile,Bo as reconcileProviderAccounts,Ho as reconcileTrailMigration,ti as recordDriftSuspects,oe as regionDisabledMessage,nt as regionSuffix,ve as registerSecurityDelegates,Tr as remediationPhaseRank,Ar as remediationPlaceholderPhysicalId,hs as renderConsentVerdictLines,ys as renderDestructionTicketLines,Zi as renderPinReportLines,As as renderPlanLines,Ts as renderPlanSummary,Ha as resolveBuildArgs,Ka as resolveBuildSecretSessionProvider,Ba as resolveBuildSecrets,Ga as resolveSecretRefValue,Co as restart,ma as restoreAndReconcileQuarantinedBucket,Aa as restoreBucketPolicy,Ps as runApprovalGate,Ds as runDestructionGate,ii as runDriftPreFlight,Qi as runDriftRepairGate,bi as runForgetSurgery,Ua as runOpenNextBuild,ba as runOrganisationSetup,zi as runPinRemediation,Ki as runRecreatePreFlight,Yi as runRecreateSurgery,_s as signApprovalToken,$t as sleep,co as sleepAbortable,fe as snapshotIdentityCentre,Bi as snapshotPolicyForType,Xa as sourcedRefsFromBuildArgs,Rt as startStackMonitoring,$a as staticSiteBuilder,qr as stubCallerIdentity,Ao as success,_i as sweepExpiredRemediationJournals,Vi as synthTemplateDeclaresResource,Ra as synthesiseEnforceSslDocument,Gr as toPascalCase,Ta as toResourcePolicyStatements,Qt as toServiceError,Rs as toWirePlanChanges,la as triageBucketPolicy,ca as unlockBucket,Ea as unlockQueue,Te as updateBackupGlobalSettings,at as updateTemplateHash,Qa as validateBuildGroup,ar as verbsForDriftVerdict,ms as verifyApprovalToken,da as verifyOrgTrailDelivery,Ii as verifyRetainFlipDiff,Wr as wrapApplicationError,mi as writeRemediationJournal,tt as writeStateFile};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as ie}from"path";import{CloudFormationClient as he}from"@aws-sdk/client-cloudformation";import{EC2Client as Se}from"@aws-sdk/client-ec2";import{success as E,failure as d}from"@fjall/generator";import{logger as M}from"@fjall/util/logger";import{ImageTagSchema as be,getErrorMessage as se,imageTagParameterName as we,maskSensitiveOutput as y}from"@fjall/util";import{parseDockerServicesFromManifest as Te}from"@fjall/util/manifest";import{stubCallerIdentity as Ne}from"../../types/deployment/index.js";import{getApplicationDeployOrder as Ee,getApplicationStackName as I,getApplicationStepName as ce,getApplicationStepId as le,APPLICATION_STACKS as P}from"../../types/operations.js";import{CdkContextBuilder as Pe}from"../../services/supporting/CdkContextBuilder.js";import{buildParamsContext as ve,bootstrapOrFail as De}from"../contextHelpers.js";import{runDetectionPipeline as Re}from"./detectionPipeline.js";import{STEP_IDS as G,STEP_NAMES as Ie}from"../../types/stepDefinitions.js";import{StepRegistry as Ce}from"../../steps/stepRegistry.js";import{checkTargetReadiness as Oe}from"../../aws/targetReadiness.js";import{cascadeHomeRegion as Ae}from"../organisation/cascadeHelpers.js";import{withStepLifecycle as Le}from"../stepLifecycle.js";import{DOCKER_BUILD_STEP_NAME as de,runDockerBuild as Me}from"./dockerBuildHelper.js";import{getParallelPhase2Stacks as Fe,getStackNamesToDeploy as $e,deployParallelPhase as xe,deployStackSequential as Be,runDockerPreCompute as je,createBuildCallbacks as Ge}from"./applicationDeployHelpers.js";import{captureDatabaseConnectionOutputs as _e,captureServiceTaskDefinitions as Ue,reconcileDatabaseEndpointChange as He}from"./databaseEndpointReconcile.js";import{deployCodeOnly as Ke}from"./codeOnlyDeploy.js";import{checkDeployPathStackAvailability as ue}from"../activeDeploymentGuard.js";import{assertLeaseBeforeStack as _}from"./leaseGate.js";import{collectFullDeployArtefacts as We}from"./artefactCollection.js";import{CfnRegistryService as qe}from"../../services/infrastructure/CfnRegistryService.js";import{ChangeSetProbe as ze}from"../../services/infrastructure/changeSetProbe.js";import{runApprovalGate as Je}from"./approvalGate.js";import{buildDestructionTicket as Ye,runDestructionGate as Qe}from"./destructionGate.js";import{DESTRUCTION_RESUME_TTL_MS as Ve,signApprovalToken as Xe}from"./plan/approvalToken.js";import{computeAssemblyDigest as Ze}from"./plan/assemblyDigest.js";import{createMemoisedPlanLoader as et}from"./plan/loadDeployPlan.js";import{runDriftPreFlightGate as tt}from"../drift/preFlightGate.js";import{completeForgetAfterDeploy as rt}from"../remediation/forgetResource.js";import{composePostFailureRepairOffer as pe}from"../remediation/postFailureRepairOffer.js";import{renderPinReportLines as at,runPinRemediation as nt}from"../remediation/pinRemediation.js";import{runRecreatePreFlight as ot}from"../remediation/recreatePreFlight.js";import{runRecreateSurgery as it}from"../remediation/recreateResource.js";const F="applicationDeploy";function st(e){const a=Object.entries(e);if(a.length===0)return;const n={};for(const[t,i]of a){const h=we(t);n[h]=i}return n}function ct(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 a=Object.entries(e.serviceImageTags);if(a.length===0)return d(new Error("serviceImageTags must name at least one service"));for(const[n,t]of a){const i=be.safeParse(t);if(!i.success)return d(new Error(`serviceImageTags.${n} is not a valid image tag: ${i.error.message}`))}}return E(void 0)}function ge(e,a,n){if(e.onStackTargets===void 0||n.length===0)return;const t=a.awsProvider.getAccountId(),i=a.awsProvider.getRegion();e.onStackTargets(n.map(h=>({stackName:h,...t!==""?{accountId:t}:{},...i!==""?{region:i}:{}})))}async function qt(e,a,n){const{callbacks:t,options:i}=e,h=Date.now(),$=i?.mode??(i?.imageTag||i?.serviceImageTags?"rollback":i?.deployOnly?"code-only":"full");if($==="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 J=ct(i);if(!J.success){const r=y(J.error.message),o=new Error(r);return t.onError?.(o),d(o)}const x=Pe.buildDeploymentContext({deployType:"application",target:n.appName,path:n.path,region:a.awsProvider.getRegion(),callerIdentity:Ne(a.awsProvider.getAccountId()),...ve({orgConfig:e.orgConfig,identity:e.identity,skipOidc:e.options?.skipOidc})},{verbose:i?.verbose,infraOnly:i?.infraOnly},e.orgConfig),b=a.frameworkRegistry.resolve({appPath:n.path});let B;const C=$==="rollback";if(b&&!C){B=b.builder.plan({appPath:n.path},b.detection);const r=Ge(t),o=await b.builder.build(n.path,B,r,{skipBuild:i?.skipBuild,infraOnly:i?.infraOnly});if(!o.success){const s=new Error(y(o.error.message));return t.onError?.(s),d(s)}}if($==="code-only"||C){t.onLog?.(C?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=ie(n.path,"cdk.out"),o=Te(r),s=o.length>0,p=b?.detection.hasDockerfile===!0,l=s||p;M.debug(F,"Deploy-only branch entered",{mode:$,imageTag:i?.imageTag,serviceImageTags:i?.serviceImageTags,appName:n.appName,appPath:n.path,cdkOutPath:r,dockerProviderAvailable:e.dockerProvider!==void 0,builderName:b?.builder.name,hasDockerfileFromManifest:s,hasDockerfileFromDisk:p,hasDockerfile:l,manifestDockerServiceCount:o.length,manifestDockerPaths:o.map(m=>m.docker.path)}),!s&&!p&&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 u=await ue([I(n.appName,P.COMPUTE)],a.cfnService,e.abortSignal);if(!u.success)return t.onError?.(u.error),d(u.error);ge(t,a,[I(n.appName,P.COMPUTE)]);let k={};if(!C&&e.dockerProvider!==void 0&&l){M.debug(F,"Running Docker build before code-only deploy",{source:s?"manifest":"disk"});const m=await Me(e,a,n,t);if(!m.success)return d(m.error);k=m.data.contentHashTagsByService}else M.debug(F,"Skipping Docker build",{reason:C?"rollback":e.dockerProvider===void 0?"no dockerProvider":"no Dockerfile detected"});const c=await _(e.assertLeaseForStack,I(n.appName,P.COMPUTE),e.abortSignal);return c!==void 0?(t.onError?.(c),d(c)):Ke(e,a,n,k)}t.onLog?.("Analysing infrastructure\u2026","info");const U=await Re(n,a,x,t);if(!U.success){const r=new Error(y(U.error.message));return t.onError?.(r),d(r)}const f=U.data;try{await t.onDetectionComplete?.({...f,builderName:b?.builder.name??"unknown"})}catch(r){const o=new Error(y(se(r)));return t.onError?.(o),d(o)}const fe={deploymentType:"application",operation:"deploy",deployOnly:!1,infraOnly:i?.infraOnly??!1,hasDockerfile:f.hasDockerfile,pattern:f.pattern,resources:f.resources,...b&&{builderName:b.builder.name}},Y=Ce.getSteps(fe),Q=Y.findIndex(r=>r.id===G.TARGET_READINESS),V=await Le(t,{stepId:G.TARGET_READINESS,stepName:Ie.TARGET_READINESS,...Q>=0&&{stepIndex:Q,totalSteps:Y.length}},async()=>{if(i?.skipReadinessCheck)return t.onLog?.("Skipping target readiness check (--skip-readiness-check)","warn"),{kind:"skipped",data:void 0};const r=a.awsProvider.getAccountId(),o=e.orgConfig?.providerAccounts.find(u=>u.id===r)?.name,s=a.awsProvider.getCredentials(),p=Ae(e.orgConfig),l=await Oe({cloudFormation:a.awsProvider.getClient(he),ec2:new Se({region:p,...s!==void 0&&{credentials:s}})},{id:r,...o!==void 0&&{name:o}},a.awsProvider.getRegion(),e.orgConfig,e.abortSignal);return l.success?l.data.ready?{kind:"completed",data:void 0}:{kind:"error",error:new Error(y(l.data.advisory))}:{kind:"error",error:new Error(y(l.error.message))}},e.abortSignal);if(!V.success)return V;const w=B?B.deployOrder:Ee({pattern:f.pattern,resources:f.resources}),v=w.length,X=f.hasDockerfile&&e.dockerProvider!==void 0&&w.includes(P.COMPUTE)&&i?.infraOnly!==!0;if(!f.hasDifferences&&!i?.force&&!X){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=f.hasDockerfile&&e.dockerProvider!==void 0&&w.includes(P.COMPUTE);for(let s=0;s<w.length;s++){const p=w[s];r&&p===P.COMPUTE&&(t.onStepStart?.(G.DOCKER_OPERATIONS,de),t.onStepComplete?.(G.DOCKER_OPERATIONS,de,"skipped"));const l=le(p,"deploy"),u=ce(p,"deploy");t.onStepStart?.(l,u,s,v),t.onStepComplete?.(l,u,"skipped",s,v)}const o=await a.stackService.resolveWebsiteUrl(n.appName);return E({target:n.appName,deploymentType:"application",outputs:o?{websiteUrl:o}:void 0,noChanges:!0,artefacts:[],durationMs:Date.now()-h})}const H=ie(n.path,"cdk.out"),N=$e({deployOrder:w,stackChanges:f.stackChanges,appName:n.appName,force:i?.force===!0,computeBuildPossible:X});ge(t,a,[...N]);const K=await ue([...N],a.cfnService,e.abortSignal);if(!K.success)return t.onError?.(K.error),d(K.error);const Z=Ze(f.currentHashes),W=et({cfnService:a.cfnService,cdkOutPath:H,changedStacks:[...N],assemblyDigest:Z,registry:new qe(a.awsProvider),changeSetProbe:new ze(a.awsProvider),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}),q=await tt(a.awsProvider,{stackNames:[...N],cdkOutPath:H,cfnService:a.cfnService,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(q.kind==="blocked"){const r=new Error(q.message);return t.onError?.(r),d(r)}const ee=q.verifiedAbsentByNecessity??[],te=e.approvalGate!==void 0||i?.approvalToken!==void 0&&i.approvalToken!==""||i?.planOnly===!0;if(te){const r=await Je({approvalGate:e.approvalGate,options:i??{},target:n.appName,cdkOutPath:H,detection:{stackChanges:f.stackChanges,currentHashes:f.currentHashes},cfnService:a.cfnService,loadPlan:W,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!r.success)return r;const o=r.data;if(o.kind==="rejected")return t.onLog?.(`Deploy rejected: ${y(o.reason)}`,"warn"),E({target:n.appName,deploymentType:"application",rejected:!0,artefacts:[],...o.planDetail!==void 0?{planDetail:o.planDetail}:{},durationMs:Date.now()-h});if(o.kind==="awaiting"){const s=await W(),p=s.success?Ye(s.data,ee):void 0;return E({target:n.appName,deploymentType:"application",awaitingApproval:!0,approvalToken:o.approvalToken,assemblyDigest:o.assemblyDigest,planDetail:o.planDetail,...p!==void 0?{destructionTicket:p}:{},artefacts:[],durationMs:Date.now()-h})}}const T=await Qe({loadPlan:W,options:i??{},target:n.appName,callbacks:t,verifiedAbsentByNecessity:ee,...e.destructionConsentGate!==void 0?{consentGate:e.destructionConsentGate}:{}});if(!T.success)return t.onError?.(T.error),d(T.error);if(T.data.kind==="withheld"){const r=te?Xe({assemblyDigest:Z,ttlMs:Ve}):void 0;return E({target:n.appName,deploymentType:"application",destructionPending:!0,destructionTicket:T.data.ticket,destructionOutcome:T.data.outcome,destructionHaltReasons:T.data.reasons,...r!==void 0?{destructionResumeToken:r.token,destructionResumeExpiresAt:r.expiresAt}:{},artefacts:[],durationMs:Date.now()-h})}if(T.data.kind==="proceed"){const{ticket:r,verbsByPhysicalName:o}=T.data,s=r.resources.filter(l=>o.get(l.physicalName)==="pin");if(s.length>0){t.onLog?.(`Pin remediation for ${n.appName}: probing live value(s) for ${s.length} consented pin(s) \u2014 deploy stopped for config write-back; nothing was applied`,"warn");const l=await nt(a.awsProvider,{targets:s.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 at(l))t.onLog?.(u,"warn");return s.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"),E({target:n.appName,deploymentType:"application",pinPending:!0,pinReport:l,pinDeferredConsents:r.resources.length-s.length,destructionTicket:r,artefacts:[],durationMs:Date.now()-h})}const p=r.resources.filter(l=>l.finding==="pinned-name-replacement"&&o.get(l.physicalName)==="recreate");if(p.length>0){const l=new Map;for(const c of p){const m=l.get(c.stack)??[];m.push(c),l.set(c.stack,m)}const u=await ot(a.awsProvider,{stacks:[...l].map(([c,m])=>({stackName:c,targets:m.map(S=>({logicalId:S.logicalId,resourceType:S.resourceType,physicalId:S.physicalName}))})),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!u.success){const c=new Error(y(u.error.message));return t.onError?.(c),d(c)}const k=[];for(const[c,m]of l){const S=await _(e.assertLeaseForStack,c,e.abortSignal,"destroy");if(S!==void 0)return k.length>0&&t.onLog?.(`Surgery already completed on ${k.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`,"warn"),t.onError?.(S),d(S);const R=m.map(g=>g.physicalName);t.onLog?.(`Recreate remediation for ${n.appName}: orchestrating the pinned-name replacement of ${R.join(", ")} on ${c}`,"warn");const L=await it(a.awsProvider,{stackName:c,targets:m.map(g=>({logicalId:g.logicalId,resourceType:g.resourceType,physicalId:g.physicalName})),appName:n.appName,consentedPhysicalNames:R,doneJournalPolicy:"archive-and-restart",plannedReplacementLogicalIds:m.map(g=>g.logicalId),onProgress:g=>t.onLog?.(g,"info"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!L.success){const g=k.length>0?` Surgery already completed on ${k.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`:"",j=new Error(y(`${L.error.message}${g}`));return t.onError?.(j),d(j)}k.push(`${c} (${R.join(", ")})`)}}}const re=await De(a,x,t);if(!re.success)return re;const ae=I(n.appName,P.DATABASE),z=N.has(ae),me=z?await _e(a.cfnService,n.appName):void 0,ke=z?await Ue(a.ecsResolver,a.ecsService,n.appName):void 0,O={},A=new Map;let ne;const D=async()=>{!z||!A.has(ae)||await He({appName:n.appName,connectionOutputsBefore:me,serviceTaskDefinitionsBefore:ke,services:{cfnService:a.cfnService,ecsService:a.ecsService,ecsResolver:a.ecsResolver},callbacks:t,...e.confirmDatabaseEndpointRestart!==void 0?{confirmRestart:e.confirmDatabaseEndpointRestart}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}})};for(let r=0;r<w.length;r++){const o=w[r],s=I(n.appName,o),p=le(o,"deploy"),l=ce(o,"deploy");if(!N.has(s)){t.onStepStart?.(p,l,r,v),t.onLog?.(`Skipping ${o} \u2014 no changes detected`,"info"),t.onStepComplete?.(p,l,"skipped",r,v);continue}const u=await _(e.assertLeaseForStack,s,e.abortSignal);if(u!==void 0)return await D(),t.onError?.(u),d(u);const k=Fe(w,r,n.appName,N);if(k.length>=2){const g=await xe(k,n,a,x,t,r,v,f,O,A);if(!g.success)return await D(),d(await pe(a.awsProvider,{stackNames:k.map(j=>I(n.appName,j)),appName:n.appName,originalError:g.error,cfnService:a.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));r+=k.length-1;continue}const c=await je(o,e,a,n,t,f.hasDockerfile);if(c!==null&&!c.success)return await D(),d(c.error);c!==null&&c.success&&(ne=c.data);const m=c!==null&&c.success?c.data.contentHashTagsByService:{},S=st(m);if(c!==null){const g=await _(e.assertLeaseForStack,s,e.abortSignal);if(g!==void 0)return await D(),t.onError?.(g),d(g)}const R=await Be(o,a,x,t,r,v,O,S!==void 0?{parameters:S}:void 0);if(!R.success)return await D(),d(await pe(a.awsProvider,{stackNames:[s],appName:n.appName,originalError:R.error,cfnService:a.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));const L=f.currentHashes.get(s);L&&A.set(s,L)}if(await D(),A.size>0){const r=await a.hashService.updateStateAfterDeploy(n.path,A);if(!r.success){const o=y(r.error.message);M.debug(F,"Failed to update state file",{error:o}),t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy unchanged stacks: ${o}`,"warn")}}const oe=await a.stackService.resolveWebsiteUrl(n.appName);oe&&(O.websiteUrl=oe);const ye=await We(a,n.appName,ne,t);return await rt(a.awsProvider,{stackNames:[...N],appName:n.appName,onLog:(r,o)=>t.onLog?.(r,o),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}).catch(r=>{M.debug(F,"Forget completion sweep failed",{error:y(se(r))})}),E({target:n.appName,deploymentType:"application",outputs:Object.keys(O).length>0?O:void 0,artefacts:ye,durationMs:Date.now()-h})}export{qt as deployApplication,ge as emitStackTargets};
|
|
1
|
+
import{join as ie}from"path";import{CloudFormationClient as he}from"@aws-sdk/client-cloudformation";import{EC2Client as Se}from"@aws-sdk/client-ec2";import{success as E,failure as d}from"@fjall/generator";import{logger as M}from"@fjall/util/logger";import{ImageTagSchema as be,getErrorMessage as se,imageTagParameterName as we,maskSensitiveOutput as y}from"@fjall/util";import{parseDockerServicesFromManifest as Te}from"@fjall/util/manifest";import{stubCallerIdentity as Ne}from"../../types/deployment/index.js";import{getApplicationDeployOrder as Ee,getApplicationStackName as I,getApplicationStepName as ce,getApplicationStepId as le,APPLICATION_STACKS as P}from"../../types/operations.js";import{CdkContextBuilder as Pe}from"../../services/supporting/CdkContextBuilder.js";import{buildParamsContext as ve,bootstrapOrFail as De}from"../contextHelpers.js";import{runDetectionPipeline as Re}from"./detectionPipeline.js";import{STEP_IDS as G,STEP_NAMES as Ie}from"../../types/stepDefinitions.js";import{StepRegistry as Ce}from"../../steps/stepRegistry.js";import{checkTargetReadiness as Oe}from"../../aws/targetReadiness.js";import{cascadeHomeRegion as Ae}from"../organisation/cascadeHelpers.js";import{withStepLifecycle as Le}from"../stepLifecycle.js";import{DOCKER_BUILD_STEP_NAME as de,runDockerBuild as Me}from"./dockerBuildHelper.js";import{getParallelPhase2Stacks as Fe,getStackNamesToDeploy as $e,deployParallelPhase as xe,deployStackSequential as Be,runDockerPreCompute as je,createBuildCallbacks as Ge}from"./applicationDeployHelpers.js";import{captureDatabaseConnectionOutputs as _e,captureServiceTaskDefinitions as Ue,reconcileDatabaseEndpointChange as He}from"./databaseEndpointReconcile.js";import{deployCodeOnly as Ke}from"./codeOnlyDeploy.js";import{checkDeployPathStackAvailability as ue}from"../activeDeploymentGuard.js";import{assertLeaseBeforeStack as _}from"./leaseGate.js";import{collectFullDeployArtefacts as We}from"./artefactCollection.js";import{CfnRegistryService as qe}from"../../services/infrastructure/CfnRegistryService.js";import{ChangeSetProbe as ze}from"../../services/infrastructure/changeSetProbe.js";import{runApprovalGate as Je}from"./approvalGate.js";import{buildDestructionTicket as Ye,runDestructionGate as Qe}from"./destructionGate.js";import{DESTRUCTION_RESUME_TTL_MS as Ve,signApprovalToken as Xe}from"./plan/approvalToken.js";import{computeAssemblyDigest as Ze}from"./plan/assemblyDigest.js";import{createMemoisedPlanLoader as et}from"./plan/loadDeployPlan.js";import{runDriftPreFlightGate as tt}from"../drift/preFlightGate.js";import{completeForgetAfterDeploy as rt}from"../remediation/forgetResource.js";import{composePostFailureRepairOffer as ge}from"../remediation/postFailureRepairOffer.js";import{renderPinReportLines as at,runPinRemediation as nt}from"../remediation/pinRemediation.js";import{runRecreatePreFlight as ot}from"../remediation/recreatePreFlight.js";import{runRecreateSurgery as it}from"../remediation/recreateResource.js";const F="applicationDeploy";function st(e){const a=Object.entries(e);if(a.length===0)return;const n={};for(const[t,i]of a){const h=we(t);n[h]=i}return n}function ct(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 a=Object.entries(e.serviceImageTags);if(a.length===0)return d(new Error("serviceImageTags must name at least one service"));for(const[n,t]of a){const i=be.safeParse(t);if(!i.success)return d(new Error(`serviceImageTags.${n} is not a valid image tag: ${i.error.message}`))}}return E(void 0)}function pe(e,a,n){if(e.onStackTargets===void 0||n.length===0)return;const t=a.awsProvider.getAccountId(),i=a.awsProvider.getRegion();e.onStackTargets(n.map(h=>({stackName:h,...t!==""?{accountId:t}:{},...i!==""?{region:i}:{}})))}async function qt(e,a,n){const{callbacks:t,options:i}=e,h=Date.now(),$=i?.mode??(i?.imageTag||i?.serviceImageTags?"rollback":i?.deployOnly?"code-only":"full");if($==="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 J=ct(i);if(!J.success){const r=y(J.error.message),o=new Error(r);return t.onError?.(o),d(o)}const x=Pe.buildDeploymentContext({deployType:"application",target:n.appName,path:n.path,region:a.awsProvider.getRegion(),callerIdentity:Ne(a.awsProvider.getAccountId()),...ve({orgConfig:e.orgConfig,identity:e.identity,skipOidc:e.options?.skipOidc})},{verbose:i?.verbose,infraOnly:i?.infraOnly},e.orgConfig),b=a.frameworkRegistry.resolve({appPath:n.path});let B;const C=$==="rollback";if(b&&!C){B=b.builder.plan({appPath:n.path},b.detection);const r=Ge(t),o=await b.builder.build(n.path,B,r,{skipBuild:i?.skipBuild,infraOnly:i?.infraOnly,...e.abortSignal!==void 0&&{abortSignal:e.abortSignal}});if(!o.success){const s=new Error(y(o.error.message));return t.onError?.(s),d(s)}}if($==="code-only"||C){t.onLog?.(C?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=ie(n.path,"cdk.out"),o=Te(r),s=o.length>0,g=b?.detection.hasDockerfile===!0,l=s||g;M.debug(F,"Deploy-only branch entered",{mode:$,imageTag:i?.imageTag,serviceImageTags:i?.serviceImageTags,appName:n.appName,appPath:n.path,cdkOutPath:r,dockerProviderAvailable:e.dockerProvider!==void 0,builderName:b?.builder.name,hasDockerfileFromManifest:s,hasDockerfileFromDisk:g,hasDockerfile:l,manifestDockerServiceCount:o.length,manifestDockerPaths:o.map(m=>m.docker.path)}),!s&&!g&&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 u=await ue([I(n.appName,P.COMPUTE)],a.cfnService,e.abortSignal);if(!u.success)return t.onError?.(u.error),d(u.error);pe(t,a,[I(n.appName,P.COMPUTE)]);let k={};if(!C&&e.dockerProvider!==void 0&&l){M.debug(F,"Running Docker build before code-only deploy",{source:s?"manifest":"disk"});const m=await Me(e,a,n,t);if(!m.success)return d(m.error);k=m.data.contentHashTagsByService}else M.debug(F,"Skipping Docker build",{reason:C?"rollback":e.dockerProvider===void 0?"no dockerProvider":"no Dockerfile detected"});const c=await _(e.assertLeaseForStack,I(n.appName,P.COMPUTE),e.abortSignal);return c!==void 0?(t.onError?.(c),d(c)):Ke(e,a,n,k)}t.onLog?.("Analysing infrastructure\u2026","info");const U=await Re(n,a,x,t);if(!U.success){const r=new Error(y(U.error.message));return t.onError?.(r),d(r)}const f=U.data;try{await t.onDetectionComplete?.({...f,builderName:b?.builder.name??"unknown"})}catch(r){const o=new Error(y(se(r)));return t.onError?.(o),d(o)}const fe={deploymentType:"application",operation:"deploy",deployOnly:!1,infraOnly:i?.infraOnly??!1,hasDockerfile:f.hasDockerfile,pattern:f.pattern,resources:f.resources,...b&&{builderName:b.builder.name}},Y=Ce.getSteps(fe),Q=Y.findIndex(r=>r.id===G.TARGET_READINESS),V=await Le(t,{stepId:G.TARGET_READINESS,stepName:Ie.TARGET_READINESS,...Q>=0&&{stepIndex:Q,totalSteps:Y.length}},async()=>{if(i?.skipReadinessCheck)return t.onLog?.("Skipping target readiness check (--skip-readiness-check)","warn"),{kind:"skipped",data:void 0};const r=a.awsProvider.getAccountId(),o=e.orgConfig?.providerAccounts.find(u=>u.id===r)?.name,s=a.awsProvider.getCredentials(),g=Ae(e.orgConfig),l=await Oe({cloudFormation:a.awsProvider.getClient(he),ec2:new Se({region:g,...s!==void 0&&{credentials:s}})},{id:r,...o!==void 0&&{name:o}},a.awsProvider.getRegion(),e.orgConfig,e.abortSignal);return l.success?l.data.ready?{kind:"completed",data:void 0}:{kind:"error",error:new Error(y(l.data.advisory))}:{kind:"error",error:new Error(y(l.error.message))}},e.abortSignal);if(!V.success)return V;const w=B?B.deployOrder:Ee({pattern:f.pattern,resources:f.resources}),v=w.length,X=f.hasDockerfile&&e.dockerProvider!==void 0&&w.includes(P.COMPUTE)&&i?.infraOnly!==!0;if(!f.hasDifferences&&!i?.force&&!X){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=f.hasDockerfile&&e.dockerProvider!==void 0&&w.includes(P.COMPUTE);for(let s=0;s<w.length;s++){const g=w[s];r&&g===P.COMPUTE&&(t.onStepStart?.(G.DOCKER_OPERATIONS,de),t.onStepComplete?.(G.DOCKER_OPERATIONS,de,"skipped"));const l=le(g,"deploy"),u=ce(g,"deploy");t.onStepStart?.(l,u,s,v),t.onStepComplete?.(l,u,"skipped",s,v)}const o=await a.stackService.resolveWebsiteUrl(n.appName);return E({target:n.appName,deploymentType:"application",outputs:o?{websiteUrl:o}:void 0,noChanges:!0,artefacts:[],durationMs:Date.now()-h})}const H=ie(n.path,"cdk.out"),N=$e({deployOrder:w,stackChanges:f.stackChanges,appName:n.appName,force:i?.force===!0,computeBuildPossible:X});pe(t,a,[...N]);const K=await ue([...N],a.cfnService,e.abortSignal);if(!K.success)return t.onError?.(K.error),d(K.error);const Z=Ze(f.currentHashes),W=et({cfnService:a.cfnService,cdkOutPath:H,changedStacks:[...N],assemblyDigest:Z,registry:new qe(a.awsProvider),changeSetProbe:new ze(a.awsProvider),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}),q=await tt(a.awsProvider,{stackNames:[...N],cdkOutPath:H,cfnService:a.cfnService,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(q.kind==="blocked"){const r=new Error(q.message);return t.onError?.(r),d(r)}const ee=q.verifiedAbsentByNecessity??[],te=e.approvalGate!==void 0||i?.approvalToken!==void 0&&i.approvalToken!==""||i?.planOnly===!0;if(te){const r=await Je({approvalGate:e.approvalGate,options:i??{},target:n.appName,cdkOutPath:H,detection:{stackChanges:f.stackChanges,currentHashes:f.currentHashes},cfnService:a.cfnService,loadPlan:W,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!r.success)return r;const o=r.data;if(o.kind==="rejected")return t.onLog?.(`Deploy rejected: ${y(o.reason)}`,"warn"),E({target:n.appName,deploymentType:"application",rejected:!0,artefacts:[],...o.planDetail!==void 0?{planDetail:o.planDetail}:{},durationMs:Date.now()-h});if(o.kind==="awaiting"){const s=await W(),g=s.success?Ye(s.data,ee):void 0;return E({target:n.appName,deploymentType:"application",awaitingApproval:!0,approvalToken:o.approvalToken,assemblyDigest:o.assemblyDigest,planDetail:o.planDetail,...g!==void 0?{destructionTicket:g}:{},artefacts:[],durationMs:Date.now()-h})}}const T=await Qe({loadPlan:W,options:i??{},target:n.appName,callbacks:t,verifiedAbsentByNecessity:ee,...e.destructionConsentGate!==void 0?{consentGate:e.destructionConsentGate}:{}});if(!T.success)return t.onError?.(T.error),d(T.error);if(T.data.kind==="withheld"){const r=te?Xe({assemblyDigest:Z,ttlMs:Ve}):void 0;return E({target:n.appName,deploymentType:"application",destructionPending:!0,destructionTicket:T.data.ticket,destructionOutcome:T.data.outcome,destructionHaltReasons:T.data.reasons,...r!==void 0?{destructionResumeToken:r.token,destructionResumeExpiresAt:r.expiresAt}:{},artefacts:[],durationMs:Date.now()-h})}if(T.data.kind==="proceed"){const{ticket:r,verbsByPhysicalName:o}=T.data,s=r.resources.filter(l=>o.get(l.physicalName)==="pin");if(s.length>0){t.onLog?.(`Pin remediation for ${n.appName}: probing live value(s) for ${s.length} consented pin(s) \u2014 deploy stopped for config write-back; nothing was applied`,"warn");const l=await nt(a.awsProvider,{targets:s.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 at(l))t.onLog?.(u,"warn");return s.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"),E({target:n.appName,deploymentType:"application",pinPending:!0,pinReport:l,pinDeferredConsents:r.resources.length-s.length,destructionTicket:r,artefacts:[],durationMs:Date.now()-h})}const g=r.resources.filter(l=>l.finding==="pinned-name-replacement"&&o.get(l.physicalName)==="recreate");if(g.length>0){const l=new Map;for(const c of g){const m=l.get(c.stack)??[];m.push(c),l.set(c.stack,m)}const u=await ot(a.awsProvider,{stacks:[...l].map(([c,m])=>({stackName:c,targets:m.map(S=>({logicalId:S.logicalId,resourceType:S.resourceType,physicalId:S.physicalName}))})),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!u.success){const c=new Error(y(u.error.message));return t.onError?.(c),d(c)}const k=[];for(const[c,m]of l){const S=await _(e.assertLeaseForStack,c,e.abortSignal,"destroy");if(S!==void 0)return k.length>0&&t.onLog?.(`Surgery already completed on ${k.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`,"warn"),t.onError?.(S),d(S);const R=m.map(p=>p.physicalName);t.onLog?.(`Recreate remediation for ${n.appName}: orchestrating the pinned-name replacement of ${R.join(", ")} on ${c}`,"warn");const L=await it(a.awsProvider,{stackName:c,targets:m.map(p=>({logicalId:p.logicalId,resourceType:p.resourceType,physicalId:p.physicalName})),appName:n.appName,consentedPhysicalNames:R,doneJournalPolicy:"archive-and-restart",plannedReplacementLogicalIds:m.map(p=>p.logicalId),onProgress:p=>t.onLog?.(p,"info"),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(!L.success){const p=k.length>0?` Surgery already completed on ${k.join("; ")} \u2014 those resources were removed and re-running the deploy resumes their journals and re-creates them.`:"",j=new Error(y(`${L.error.message}${p}`));return t.onError?.(j),d(j)}k.push(`${c} (${R.join(", ")})`)}}}const re=await De(a,x,t);if(!re.success)return re;const ae=I(n.appName,P.DATABASE),z=N.has(ae),me=z?await _e(a.cfnService,n.appName):void 0,ke=z?await Ue(a.ecsResolver,a.ecsService,n.appName):void 0,O={},A=new Map;let ne;const D=async()=>{!z||!A.has(ae)||await He({appName:n.appName,connectionOutputsBefore:me,serviceTaskDefinitionsBefore:ke,services:{cfnService:a.cfnService,ecsService:a.ecsService,ecsResolver:a.ecsResolver},callbacks:t,...e.confirmDatabaseEndpointRestart!==void 0?{confirmRestart:e.confirmDatabaseEndpointRestart}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}})};for(let r=0;r<w.length;r++){const o=w[r],s=I(n.appName,o),g=le(o,"deploy"),l=ce(o,"deploy");if(!N.has(s)){t.onStepStart?.(g,l,r,v),t.onLog?.(`Skipping ${o} \u2014 no changes detected`,"info"),t.onStepComplete?.(g,l,"skipped",r,v);continue}const u=await _(e.assertLeaseForStack,s,e.abortSignal);if(u!==void 0)return await D(),t.onError?.(u),d(u);const k=Fe(w,r,n.appName,N);if(k.length>=2){const p=await xe(k,n,a,x,t,r,v,f,O,A);if(!p.success)return await D(),d(await ge(a.awsProvider,{stackNames:k.map(j=>I(n.appName,j)),appName:n.appName,originalError:p.error,cfnService:a.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));r+=k.length-1;continue}const c=await je(o,e,a,n,t,f.hasDockerfile);if(c!==null&&!c.success)return await D(),d(c.error);c!==null&&c.success&&(ne=c.data);const m=c!==null&&c.success?c.data.contentHashTagsByService:{},S=st(m);if(c!==null){const p=await _(e.assertLeaseForStack,s,e.abortSignal);if(p!==void 0)return await D(),t.onError?.(p),d(p)}const R=await Be(o,a,x,t,r,v,O,S!==void 0?{parameters:S}:void 0);if(!R.success)return await D(),d(await ge(a.awsProvider,{stackNames:[s],appName:n.appName,originalError:R.error,cfnService:a.cfnService,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}));const L=f.currentHashes.get(s);L&&A.set(s,L)}if(await D(),A.size>0){const r=await a.hashService.updateStateAfterDeploy(n.path,A);if(!r.success){const o=y(r.error.message);M.debug(F,"Failed to update state file",{error:o}),t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy unchanged stacks: ${o}`,"warn")}}const oe=await a.stackService.resolveWebsiteUrl(n.appName);oe&&(O.websiteUrl=oe);const ye=await We(a,n.appName,ne,t);return await rt(a.awsProvider,{stackNames:[...N],appName:n.appName,onLog:(r,o)=>t.onLog?.(r,o),...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}}).catch(r=>{M.debug(F,"Forget completion sweep failed",{error:y(se(r))})}),E({target:n.appName,deploymentType:"application",outputs:Object.keys(O).length>0?O:void 0,artefacts:ye,durationMs:Date.now()-h})}export{qt as deployApplication,pe as emitStackTargets};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isAbsolute as F,join as L,dirname as M,resolve as _}from"node:path";import{existsSync as K}from"node:fs";import{success as N,failure as h}from"@fjall/generator";import{deriveContentHashTag as W,maskSensitiveOutput as b,toKebab as x}from"@fjall/util";import{evaluateBakeGuard as z,evaluateResolvedBuildArgValues as X,acknowledgedBuildArgKeys as Y,buildCacheRepositoryName as H,BAKE_GUARD_EXPOSURE_CLAUSE as q}from"@fjall/util/docker";import{runWithBoundedConcurrency as J,resolveBuildConcurrency as Q}from"@fjall/util/buildConcurrency";import{logger as T}from"@fjall/util/logger";import{parseDockerServicesFromManifest as Z}from"@fjall/util/manifest";import{STEP_IDS as A}from"../../types/stepDefinitions.js";import{isAborted as U}from"../../aws/organisations/types.js";import{resolveBuildSecrets as ee,resolveSecretRefValue as re,resolveBuildSecretSessionProvider as te,sourcedRefsFromBuildArgs as ne}from"./buildSecretResolver.js";import{partitionForRegion as oe}from"./buildSecretSession.js";import{resolveBuildArgs as ie}from"./buildArgResolver.js";import{validateBuildGroup as se}from"./buildGroupValidator.js";import{ensureBuildCacheRepository as ae}from"./ecrCacheRepository.js";const I="dockerBuildHelper",C="Building and pushing Docker image";function de(e,n,t){const r=L(n,e);if(K(r))return{path:r,base:n};if(t!==""&&t!==n){const i=L(t,e);if(K(i))return{path:i,base:t}}return{path:r,base:n}}function ue(e,n,t){const r=e.docker.path,i=e.docker.context;let s,a;if(F(r))s=r,a=n;else{const p=de(r,n,t);s=p.path,a=p.base}return{buildContext:i?F(i)?_(i):_(a,i):_(M(s)),dockerfilePath:s,target:e.docker.target,resolvedViaFallback:a!==n}}function ce(e){return`${e.buildContext}|${e.dockerfilePath}|${e.target??""}`}function le(e,n){return`Dockerfile not found for service '${e}' at ${n}. Checked the synth directory and the working directory. If your Dockerfile lives at the project root with the CDK app in a subdirectory, set an absolute docker.context (the build context must share the Dockerfile's directory).`}function fe(e){return e.startsWith("cn-")?"amazonaws.com.cn":"amazonaws.com"}function G(e,n){return`${e}.dkr.ecr.${n}.${fe(n)}`}function ge(e,n,t){return`${G(e,n)}/${x(t)}`}function me(e,n,t){return`${G(e,n)}/${H(x(t))}`}function pe(e,n,t){const r=new Map;for(const i of e){const s=ue(i,n,t),a=ce(s),m=r.get(a);m?m.members.push(i):r.set(a,{identity:s,members:[i]})}return Array.from(r.values())}async function he(e,n,t,r,i){const s=await e.buildAndPush({appName:n.appName,appPath:n.path,region:t,accountId:r},(a,m,p,S)=>{i.onDockerProgress?.(b(a),m,p,S)});return s.success?N({imageUri:s.data.imageUri,imageTag:s.data.imageTag}):h(s.error)}function j(){return{contentHashTagsByService:{},imageDigestsByService:{}}}async function be(e,n,t,r,i,s,a,m,p,S,w,l,E){const c=e.members[0];if(!K(e.identity.dockerfilePath))return h(new Error(le(c.name,e.identity.dockerfilePath)));e.identity.resolvedViaFallback&&m.onLog?.(`Building service '${c.name}' from ${e.identity.dockerfilePath} (resolved at the project root).`,"info");const y=[...c.docker.buildSecrets??[],...E??[]],v=se({serviceName:c.name,dockerfilePath:e.identity.dockerfilePath,buildContext:e.identity.buildContext,...e.identity.target!==void 0&&{target:e.identity.target},...c.docker.buildArgs!==void 0&&{buildArgs:c.docker.buildArgs},...y.length>0&&{buildSecrets:y},members:e.members.map(o=>({serviceName:o.name,...o.docker.buildArgs!==void 0&&{buildArgs:o.docker.buildArgs},...o.docker.buildSecrets!==void 0&&{buildSecrets:o.docker.buildSecrets}}))});if(!v.success)return h(v.error);const k=z(c.docker.buildArgs,x(t.appName));for(const o of k.warnings)m.onLog?.(b(o.message),"warn");if(k.findings.length>0)return h(new Error(b(k.findings.map(o=>o.message).join(" "))));const d=y,f=ne(c.docker.buildArgs),D={appName:t.appName,region:r,accountId:i,partition:oe(r)},$=await te(p,[...d,...f],D);if(!$.success)return h($.error);const O=$.data,R=await ie({manifestBuildArgs:c.docker.buildArgs,serviceDir:e.identity.buildContext,appDir:t.path,...w!==void 0&&{stage:w},shellEnv:process.env,...l!==void 0&&{flagBuildArgs:l},resolveSourcedValue:(o,P)=>re(O,{id:o,...P},S)});if(!R.success)return h(R.error);const B=R.data.buildArgs;for(const o of R.data.inferredDotenvKeys)m.onLog?.(b(`buildArg "${o}" was auto-declared from a .env file and will be baked into the image \u2014 ${q}.`),"warn");const u=X(B,x(t.appName),Y(c.docker.buildArgs));if(u.length>0)return h(new Error(b(u.map(o=>o.message).join(" "))));let g;if(d.length>0){const o=await ee(O,d,S);if(!o.success)return h(o.error);g=o.data}try{if(U(S))return h(new Error(`Build of service '${c.name}' was aborted before the docker build started`));const o={appName:t.appName,appPath:e.identity.buildContext,region:r,accountId:i,buildContext:e.identity.buildContext,dockerfilePath:e.identity.dockerfilePath,pushByDigest:!0,serviceName:c.name,...a!==void 0&&{cacheRepoUri:a},...e.identity.target!==void 0&&{target:e.identity.target},...Object.keys(B).length>0&&{buildArgs:B},...g!==void 0&&{buildSecrets:g.resolved}};return await ve(e,o,n,s,m)}finally{g!==void 0&&await g.cleanup().catch(()=>m.onLog?.("Build-secret cleanup failed.","warn"))}}async function ve(e,n,t,r,i){const s=await t.buildAndPush(n,(l,E,c,y)=>{i.onDockerProgress?.(b(l),E,c,y)});if(!s.success)return h(s.error);const a=s.data.imageDigest;if(typeof a!="string"||!a.startsWith("sha256:"))return h(new Error(`Buildx push succeeded but returned an invalid digest: ${b(String(a))}`));const m={},p={},S=[];for(const l of e.members){const E=l.docker.target,c=W(a,l.name,E);if(!c.success)return h(c.error);const y=c.data,v=l.name;m[v]=y,p[v]=a,S.push(`${r}:${y}`)}const w=await t.tagByDigest({sourceImage:r,digest:a,tags:S});return w.success?N({contentHashTagsByService:m,imageDigestsByService:p}):h(w.error)}async function Te(e,n,t,r){const i=e.dockerProvider;if(!i)return N(j());const s=n.awsProvider.getAccountId();if(!s)return r.onLog?.("Skipping Docker build \u2014 account ID not available","warn"),N(j());const a=n.awsProvider.getRegion(),m=L(t.path,"cdk.out"),p=Z(m),S=ge(s,a,t.appName);if(T.debug(I,"runDockerBuild starting",{appName:t.appName,appPath:t.path,accountId:s,region:a,cdkOutPath:m,manifestServiceCount:p.length,manifestServices:p.map(d=>({name:d.name,path:d.docker.path,context:d.docker.context,target:d.docker.target})),stepId:A.DOCKER_OPERATIONS,stepName:C}),r.onStepStart?.(A.DOCKER_OPERATIONS,C),p.length===0){r.onLog?.("Initialising ECR repository\u2026","info");const d=await i.initialiseECR({appName:t.appName,region:a,accountId:s});d.success||r.onLog?.(`ECR initialisation failed: ${b(d.error.message)}`,"warn"),r.onLog?.("Building and pushing Docker image\u2026","info");const f=await he(i,t,a,s,r);if(!f.success){T.debug(I,"Docker buildAndPush (legacy) failed",{appName:t.appName,error:b(f.error.message)}),r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const D=new Error(b(f.error.message));return r.onError?.(D),h(D)}return r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"completed"),r.onLog?.(`Docker image pushed: ${f.data.imageUri}`,"info"),N(j())}const w=await i.preflight?.();if(w!==void 0&&!w.success){r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const d=new Error(b(w.error.message));return r.onError?.(d),h(d)}const l=pe(p,t.path,e.workingDirectory);let E=me(s,a,t.appName);const c=await ae(n.awsProvider,H(x(t.appName)),e.abortSignal);c.success||(E=void 0,r.onLog?.(`Building without registry cache \u2014 ${c.error.message}`,"warn")),r.onLog?.(`Building and pushing ${p.length} service image(s) in ${l.length} group(s)\u2026`,"info");let y=!1;if(i.beginEcrSession!==void 0){const d=await i.beginEcrSession({accountId:s,region:a});if(!d.success){r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const f=new Error(b(d.error.message));return r.onError?.(f),h(f)}y=!0}const v=new AbortController,k=()=>v.abort();e.abortSignal!==void 0&&(e.abortSignal.aborted?v.abort():e.abortSignal.addEventListener("abort",k,{once:!0}));try{const d=()=>U(e.abortSignal)?"the deployment was cancelled":"a sibling group failed";let f;const D=Q(l.length),$=l.map((u,g)=>async()=>{const o=u.members.map(V=>V.name).join(", ");if(v.signal.aborted)throw new Error(`Build of group ${g+1}/${l.length} (${o}) was not started \u2014 ${d()}`);r.onLog?.(`Building group ${g+1}/${l.length} (${o})\u2026`,"info");const P=await be(u,i,t,a,s,S,E,r,n.awsProvider,v.signal,e.options?.environment,e.options?.flagBuildArgs,e.options?.flagBuildSecrets);if(!P.success)throw f===void 0&&(f={error:P.error,leader:u.members[0]?.name,members:o}),v.abort(),P.error;return P.data}),O=await J($,D,{abortOnFirstFailure:!0,abortSignal:v.signal});if(f===void 0)for(let u=0;u<l.length;u++){const g=O[u];if(!(g!==void 0&&g.success)){f={error:g!==void 0&&!g.success?g.error:new Error(`Build of group ${u+1}/${l.length} never ran \u2014 ${d()}`),leader:l[u].members[0]?.name,members:l[u].members.map(o=>o.name).join(", ")};break}}if(f!==void 0){T.debug(I,"Docker buildAndPush failed",{appName:t.appName,leader:f.leader,members:f.members,error:b(f.error.message)}),r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const u=new Error(b(f.error.message));return r.onError?.(u),h(u)}const R={},B={};for(const u of O)if(!(u===void 0||!u.success)){for(const[g,o]of Object.entries(u.data.contentHashTagsByService))R[g]=o;for(const[g,o]of Object.entries(u.data.imageDigestsByService))B[g]=o}return T.debug(I,"Docker buildAndPush succeeded",{appName:t.appName,services:p.map(u=>u.name),groupCount:l.length,contentHashTags:R}),r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"completed"),r.onLog?.(`Docker images pushed for ${p.length} service(s)`,"info"),N({contentHashTagsByService:R,imageDigestsByService:B,repoUri:S})}finally{e.abortSignal?.removeEventListener("abort",k),y&&i.endEcrSession!==void 0&&await i.endEcrSession().catch(d=>{T.debug(I,"endEcrSession cleanup failed",{error:b(d instanceof Error?d.message:String(d))})})}}export{C as DOCKER_BUILD_STEP_NAME,j as emptyBuildProducts,Te as runDockerBuild};
|
|
1
|
+
import{isAbsolute as H,join as _,dirname as M,resolve as K}from"node:path";import{existsSync as j}from"node:fs";import{success as P,failure as h}from"@fjall/generator";import{deriveContentHashTag as z,maskSensitiveOutput as b,toKebab as x}from"@fjall/util";import{evaluateBakeGuard as X,evaluateResolvedBuildArgValues as Y,acknowledgedBuildArgKeys as q,createBakeWarningDeduper as J,buildCacheRepositoryName as U,BAKE_GUARD_EXPOSURE_CLAUSE as Q}from"@fjall/util/docker";import{runWithBoundedConcurrency as Z,resolveBuildConcurrency as ee}from"@fjall/util/buildConcurrency";import{logger as T}from"@fjall/util/logger";import{parseDockerServicesFromManifest as re}from"@fjall/util/manifest";import{STEP_IDS as A}from"../../types/stepDefinitions.js";import{isAborted as G}from"../../aws/organisations/types.js";import{resolveBuildSecrets as te,resolveSecretRefValue as ne,resolveBuildSecretSessionProvider as oe,sourcedRefsFromBuildArgs as ie}from"./buildSecretResolver.js";import{partitionForRegion as se}from"./buildSecretSession.js";import{resolveBuildArgs as ae}from"./buildArgResolver.js";import{validateBuildGroup as de}from"./buildGroupValidator.js";import{ensureBuildCacheRepository as ce}from"./ecrCacheRepository.js";const I="dockerBuildHelper",C="Building and pushing Docker image";function ue(e,n,t){const r=_(n,e);if(j(r))return{path:r,base:n};if(t!==""&&t!==n){const i=_(t,e);if(j(i))return{path:i,base:t}}return{path:r,base:n}}function le(e,n,t){const r=e.docker.path,i=e.docker.context;let s,a;if(H(r))s=r,a=n;else{const p=ue(r,n,t);s=p.path,a=p.base}return{buildContext:i?H(i)?K(i):K(a,i):K(M(s)),dockerfilePath:s,target:e.docker.target,resolvedViaFallback:a!==n}}function fe(e){return`${e.buildContext}|${e.dockerfilePath}|${e.target??""}`}function ge(e,n){return`Dockerfile not found for service '${e}' at ${n}. Checked the synth directory and the working directory. If your Dockerfile lives at the project root with the CDK app in a subdirectory, set an absolute docker.context (the build context must share the Dockerfile's directory).`}function me(e){return e.startsWith("cn-")?"amazonaws.com.cn":"amazonaws.com"}function V(e,n){return`${e}.dkr.ecr.${n}.${me(n)}`}function pe(e,n,t){return`${V(e,n)}/${x(t)}`}function he(e,n,t){return`${V(e,n)}/${U(x(t))}`}function be(e,n,t){const r=new Map;for(const i of e){const s=le(i,n,t),a=fe(s),m=r.get(a);m?m.members.push(i):r.set(a,{identity:s,members:[i]})}return Array.from(r.values())}async function ve(e,n,t,r,i){const s=await e.buildAndPush({appName:n.appName,appPath:n.path,region:t,accountId:r},(a,m,p,y)=>{i.onDockerProgress?.(b(a),m,p,y)});return s.success?P({imageUri:s.data.imageUri,imageTag:s.data.imageTag}):h(s.error)}function F(){return{contentHashTagsByService:{},imageDigestsByService:{}}}async function Se(e,n,t,r,i,s,a,m,p,y,E,f,R,w){const l=e.members[0];if(!j(e.identity.dockerfilePath))return h(new Error(ge(l.name,e.identity.dockerfilePath)));e.identity.resolvedViaFallback&&m.onLog?.(`Building service '${l.name}' from ${e.identity.dockerfilePath} (resolved at the project root).`,"info");const v=[...l.docker.buildSecrets??[],...R??[]],N=de({serviceName:l.name,dockerfilePath:e.identity.dockerfilePath,buildContext:e.identity.buildContext,...e.identity.target!==void 0&&{target:e.identity.target},...l.docker.buildArgs!==void 0&&{buildArgs:l.docker.buildArgs},...v.length>0&&{buildSecrets:v},members:e.members.map(o=>({serviceName:o.name,...o.docker.buildArgs!==void 0&&{buildArgs:o.docker.buildArgs},...o.docker.buildSecrets!==void 0&&{buildSecrets:o.docker.buildSecrets}}))});if(!N.success)return h(N.error);const d=X(l.docker.buildArgs,x(t.appName));for(const o of d.warnings){const S=b(o.message);w(S)&&m.onLog?.(S,"warn")}if(d.findings.length>0)return h(new Error(b(d.findings.map(o=>o.message).join(" "))));const u=v,D=ie(l.docker.buildArgs),L={appName:t.appName,region:r,accountId:i,partition:se(r)},$=await oe(p,[...u,...D],L);if(!$.success)return h($.error);const O=$.data,k=await ae({manifestBuildArgs:l.docker.buildArgs,serviceDir:e.identity.buildContext,appDir:t.path,...E!==void 0&&{stage:E},shellEnv:process.env,...f!==void 0&&{flagBuildArgs:f},resolveSourcedValue:(o,S)=>ne(O,{id:o,...S},y)});if(!k.success)return h(k.error);const B=k.data.buildArgs;for(const o of k.data.inferredDotenvKeys){const S=b(`buildArg "${o}" was auto-declared from a .env file and will be baked into the image \u2014 ${Q}.`);w(S)&&m.onLog?.(S,"warn")}const c=Y(B,x(t.appName),q(l.docker.buildArgs));if(c.length>0)return h(new Error(b(c.map(o=>o.message).join(" "))));let g;if(u.length>0){const o=await te(O,u,y);if(!o.success)return h(o.error);g=o.data}try{if(G(y))return h(new Error(`Build of service '${l.name}' was aborted before the docker build started`));const o={appName:t.appName,appPath:e.identity.buildContext,region:r,accountId:i,buildContext:e.identity.buildContext,dockerfilePath:e.identity.dockerfilePath,pushByDigest:!0,serviceName:l.name,...a!==void 0&&{cacheRepoUri:a},...e.identity.target!==void 0&&{target:e.identity.target},...Object.keys(B).length>0&&{buildArgs:B},...g!==void 0&&{buildSecrets:g.resolved}};return await ye(e,o,n,s,m)}finally{g!==void 0&&await g.cleanup().catch(()=>m.onLog?.("Build-secret cleanup failed.","warn"))}}async function ye(e,n,t,r,i){const s=await t.buildAndPush(n,(f,R,w,l)=>{i.onDockerProgress?.(b(f),R,w,l)});if(!s.success)return h(s.error);const a=s.data.imageDigest;if(typeof a!="string"||!a.startsWith("sha256:"))return h(new Error(`Buildx push succeeded but returned an invalid digest: ${b(String(a))}`));const m={},p={},y=[];for(const f of e.members){const R=f.docker.target,w=z(a,f.name,R);if(!w.success)return h(w.error);const l=w.data,v=f.name;m[v]=l,p[v]=a,y.push(`${r}:${l}`)}const E=await t.tagByDigest({sourceImage:r,digest:a,tags:y});return E.success?P({contentHashTagsByService:m,imageDigestsByService:p}):h(E.error)}async function Le(e,n,t,r){const i=e.dockerProvider;if(!i)return P(F());const s=n.awsProvider.getAccountId();if(!s)return r.onLog?.("Skipping Docker build \u2014 account ID not available","warn"),P(F());const a=n.awsProvider.getRegion(),m=_(t.path,"cdk.out"),p=re(m),y=pe(s,a,t.appName);if(T.debug(I,"runDockerBuild starting",{appName:t.appName,appPath:t.path,accountId:s,region:a,cdkOutPath:m,manifestServiceCount:p.length,manifestServices:p.map(d=>({name:d.name,path:d.docker.path,context:d.docker.context,target:d.docker.target})),stepId:A.DOCKER_OPERATIONS,stepName:C}),r.onStepStart?.(A.DOCKER_OPERATIONS,C),p.length===0){r.onLog?.("Initialising ECR repository\u2026","info");const d=await i.initialiseECR({appName:t.appName,region:a,accountId:s});d.success||r.onLog?.(`ECR initialisation failed: ${b(d.error.message)}`,"warn"),r.onLog?.("Building and pushing Docker image\u2026","info");const u=await ve(i,t,a,s,r);if(!u.success){T.debug(I,"Docker buildAndPush (legacy) failed",{appName:t.appName,error:b(u.error.message)}),r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const D=new Error(b(u.error.message));return r.onError?.(D),h(D)}return r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"completed"),r.onLog?.(`Docker image pushed: ${u.data.imageUri}`,"info"),P(F())}const E=await i.preflight?.();if(E!==void 0&&!E.success){r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const d=new Error(b(E.error.message));return r.onError?.(d),h(d)}const f=be(p,t.path,e.workingDirectory);let R=he(s,a,t.appName);const w=await ce(n.awsProvider,U(x(t.appName)),e.abortSignal);w.success||(R=void 0,r.onLog?.(`Building without registry cache \u2014 ${w.error.message}`,"warn")),r.onLog?.(`Building and pushing ${p.length} service image(s) in ${f.length} group(s)\u2026`,"info");let l=!1;if(i.beginEcrSession!==void 0){const d=await i.beginEcrSession({accountId:s,region:a});if(!d.success){r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const u=new Error(b(d.error.message));return r.onError?.(u),h(u)}l=!0}const v=new AbortController,N=()=>v.abort();e.abortSignal!==void 0&&(e.abortSignal.aborted?v.abort():e.abortSignal.addEventListener("abort",N,{once:!0}));try{const d=()=>G(e.abortSignal)?"the deployment was cancelled":"a sibling group failed";let u;const D=ee(f.length),L=J(),$=f.map((c,g)=>async()=>{const o=c.members.map(W=>W.name).join(", ");if(v.signal.aborted)throw new Error(`Build of group ${g+1}/${f.length} (${o}) was not started \u2014 ${d()}`);r.onLog?.(`Building group ${g+1}/${f.length} (${o})\u2026`,"info");const S=await Se(c,i,t,a,s,y,R,r,n.awsProvider,v.signal,e.options?.environment,e.options?.flagBuildArgs,e.options?.flagBuildSecrets,L);if(!S.success)throw u===void 0&&(u={error:S.error,leader:c.members[0]?.name,members:o}),v.abort(),S.error;return S.data}),O=await Z($,D,{abortOnFirstFailure:!0,abortSignal:v.signal});if(u===void 0)for(let c=0;c<f.length;c++){const g=O[c];if(!(g!==void 0&&g.success)){u={error:g!==void 0&&!g.success?g.error:new Error(`Build of group ${c+1}/${f.length} never ran \u2014 ${d()}`),leader:f[c].members[0]?.name,members:f[c].members.map(o=>o.name).join(", ")};break}}if(u!==void 0){T.debug(I,"Docker buildAndPush failed",{appName:t.appName,leader:u.leader,members:u.members,error:b(u.error.message)}),r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"error");const c=new Error(b(u.error.message));return r.onError?.(c),h(c)}const k={},B={};for(const c of O)if(!(c===void 0||!c.success)){for(const[g,o]of Object.entries(c.data.contentHashTagsByService))k[g]=o;for(const[g,o]of Object.entries(c.data.imageDigestsByService))B[g]=o}return T.debug(I,"Docker buildAndPush succeeded",{appName:t.appName,services:p.map(c=>c.name),groupCount:f.length,contentHashTags:k}),r.onStepComplete?.(A.DOCKER_OPERATIONS,C,"completed"),r.onLog?.(`Docker images pushed for ${p.length} service(s)`,"info"),P({contentHashTagsByService:k,imageDigestsByService:B,repoUri:y})}finally{e.abortSignal?.removeEventListener("abort",N),l&&i.endEcrSession!==void 0&&await i.endEcrSession().catch(d=>{T.debug(I,"endEcrSession cleanup failed",{error:b(d instanceof Error?d.message:String(d))})})}}export{C as DOCKER_BUILD_STEP_NAME,F as emptyBuildProducts,Le as runDockerBuild};
|
|
@@ -25,4 +25,4 @@ export declare const IMPORT_MAP_TIMEOUT_MS = 30000;
|
|
|
25
25
|
* `deployOnly` early-return check, so built artefacts are available
|
|
26
26
|
* for CDK synth.
|
|
27
27
|
*/
|
|
28
|
-
export declare function runOpenNextBuild(operation: ApplicationOperation, pattern: string | null | undefined, callbacks: DeployCallbacks, options?: DeployOptions): Promise<Result<void>>;
|
|
28
|
+
export declare function runOpenNextBuild(operation: ApplicationOperation, pattern: string | null | undefined, callbacks: DeployCallbacks, options?: DeployOptions, abortSignal?: AbortSignal): Promise<Result<void>>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createRequire as
|
|
2
|
-
${m}`))}return c.debug("openNextBuild","Payload import map generated",{appPath:s}),n.onOpenNextProgress?.(
|
|
3
|
-
${
|
|
1
|
+
import{createRequire as $}from"module";import{existsSync as O,statSync as v,rmSync as S}from"fs";import{join as f}from"path";import{success as l,failure as o}from"@fjall/generator";import{filterDangerousEnvVars as E,maskSensitiveOutput as u,parseShellArgs as b}from"@fjall/util";import{logger as c}from"@fjall/util/logger";import{isOpenNextPattern as T}from"../../types/detection/patternDetection.js";import{spawnWithTimeout as P}from"../spawnHelpers.js";const x="@opennextjs/aws",w=6e5,M=3e4;function D(s){const n=$(f(s,"package.json"));let e;try{e=n.resolve.paths(x)}catch(r){return o(new Error(`Cannot determine module search paths for ${x}. Ensure it is installed in your project. (${r instanceof Error?r.message:String(r)})`))}if(!e||e.length===0)return o(new Error(`Cannot determine module search paths for ${x}. Ensure it is installed in your project.`));for(const r of e){const p=f(r,"@opennextjs","aws");try{if(v(p).isDirectory()){const t=f(r,".bin","open-next");if(!O(t)){c.debug("openNextBuild","Package found but binary missing",{nodeModulesPath:r,binPath:t});continue}return c.debug("openNextBuild","Resolved OpenNext binary",{binPath:t}),l(t)}}catch(i){c.debug("openNextBuild","Package not at location",{nodeModulesPath:r,error:String(i)})}}return o(new Error(`Cannot find ${x} package. Ensure it is installed in your project: npm install ${x}`))}function N(s){const n=f(s,".open-next");if(O(n))try{S(n,{recursive:!0,force:!0}),c.debug("openNextBuild","Cleaned up stale .open-next directory",{path:n})}catch(e){c.debug("openNextBuild","Failed to clean up .open-next",{error:String(e)})}}function B(s,n,e,r){switch(s.type){case"timeout":return e?.(),r?.(n.timeoutMsg),o(new Error(n.timeoutMsg));case"aborted":return e?.(),r?.(n.abortedMsg),o(new Error(n.abortedMsg));case"enoent":return e?.(),r?.(n.enoentMsg),o(new Error(n.enoentMsg));case"spawn_error":{const p=`${n.spawnErrorPrefix}: ${s.error.message}`;return e?.(),r?.(p),o(new Error(p))}default:return}}async function j(s,n,e){n.onOpenNextProgress?.(u("Generating Payload import map..."));const[r,...p]=b("npx payload generate:importmap"),i=E(globalThis.process.env),t=await P({command:r,args:p,cwd:s,env:{...i,FORCE_COLOR:"0"},timeout:M,...e!==void 0&&{abortSignal:e},onStdoutData:m=>{n.onOpenNextProgress?.(u(m.trim()))}}),g=B(t,{timeoutMsg:`Payload import map generation timed out after ${M/1e3} seconds`,abortedMsg:"Payload import map generation cancelled",enoentMsg:"Payload CLI not found. Ensure payload is installed: npm install payload",spawnErrorPrefix:"Failed to generate Payload import map"});if(g)return g;if(t.type!=="success")return o(new Error("Unexpected spawn result"));if(t.code!==0){const m=u(t.stderr||t.stdout);return o(new Error(`Payload import map generation failed (exit code ${t.code}):
|
|
2
|
+
${m}`))}return c.debug("openNextBuild","Payload import map generated",{appPath:s}),n.onOpenNextProgress?.(u("Payload import map generated")),l(void 0)}async function q(s,n,e,r,p){if(!T(n))return l(void 0);if(r?.skipBuild||r?.infraOnly)return c.debug("openNextBuild","Build skipped",{skipBuild:r?.skipBuild,infraOnly:r?.infraOnly}),e.onLog?.(r?.infraOnly?"Infrastructure-only mode \u2014 skipping OpenNext build":"Build skipped (--skip-build)","info"),l(void 0);const i=s.path;if(n==="payload"){const d=await j(i,e,p);if(!d.success)return e.onOpenNextBuildError?.(u(d.error.message)),N(i),o(d.error)}const t=D(i);if(!t.success)return e.onOpenNextBuildError?.(u(t.error.message)),o(t.error);const g=t.data;e.onOpenNextBuildStart?.(),e.onOpenNextProgress?.(u("Starting OpenNext build..."));const m=E(globalThis.process.env),h=f(i,"node_modules"),a=await P({command:g,args:["build"],cwd:i,env:{...m,FORCE_COLOR:"0",NODE_PATH:h,npm_config_loglevel:"error",PNPM_HOME:m.PNPM_HOME||""},timeout:w,...p!==void 0&&{abortSignal:p},onStdoutData:d=>{e.onOpenNextProgress?.(u(d.trim()))},onStderrData:d=>{e.onOpenNextProgress?.(u(d.trim()))}}),y=B(a,{timeoutMsg:`OpenNext build timed out after ${w/1e3} seconds`,abortedMsg:"OpenNext build cancelled",enoentMsg:"OpenNext binary not found. Ensure Node.js is installed and in PATH.",spawnErrorPrefix:"Failed to spawn OpenNext build"},()=>N(i),d=>e.onOpenNextBuildError?.(d));if(y)return y;if(a.type!=="success")return o(new Error("Unexpected spawn result"));if(a.code!==0){N(i);const d=u(a.stderr||a.stdout);return e.onOpenNextBuildError?.(`OpenNext build failed (exit code ${a.code})`),o(new Error(`OpenNext build failed (exit code ${a.code}):
|
|
3
|
+
${d}`))}const _=f(i,".open-next");return O(_)?(e.onOpenNextBuildComplete?.(),e.onOpenNextProgress?.(u("OpenNext build completed successfully")),l(void 0)):(e.onOpenNextBuildError?.("OpenNext build completed but .open-next directory not found"),o(new Error("OpenNext build completed but .open-next directory not found")))}export{w as BUILD_TIMEOUT_MS,M as IMPORT_MAP_TIMEOUT_MS,q as runOpenNextBuild};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openNextBuilder as
|
|
1
|
+
import{openNextBuilder as d}from"./openNextBuilder.js";import{staticSiteBuilder as n}from"./staticSiteBuilder.js";import{dockerBuilder as c}from"./dockerBuilder.js";class o{builders;constructor(e){this.builders=[...e].sort((r,t)=>r.priority-t.priority)}resolve(e,r){if(r){const t=this.builders.find(u=>u.name===r);if(!t)return null;const i=t.detect(e);return{builder:t,detection:{...i,detected:!0}}}for(const t of this.builders){const i=t.detect(e);if(i.detected)return{builder:t,detection:i}}return null}static createDefault(){return new o([d,n,c])}static create(e){return new o(e)}}export{o as FrameworkRegistry};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { dockerBuilder } from "./dockerBuilder.js";
|
|
2
2
|
export { openNextBuilder } from "./openNextBuilder.js";
|
|
3
|
+
export { staticSiteBuilder } from "./staticSiteBuilder.js";
|
|
3
4
|
export { FrameworkRegistry } from "./frameworkRegistry.js";
|
|
4
5
|
export type { ResolvedBuilder } from "./frameworkRegistry.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dockerBuilder as o}from"./dockerBuilder.js";import{openNextBuilder as
|
|
1
|
+
import{dockerBuilder as o}from"./dockerBuilder.js";import{openNextBuilder as i}from"./openNextBuilder.js";import{staticSiteBuilder as p}from"./staticSiteBuilder.js";import{FrameworkRegistry as d}from"./frameworkRegistry.js";export{d as FrameworkRegistry,o as dockerBuilder,i as openNextBuilder,p as staticSiteBuilder};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{basename as
|
|
1
|
+
import{basename as d}from"path";import{success as i,parseInfrastructure as l,isOpenNextPatternType as c}from"@fjall/generator";import{logger as f}from"@fjall/util/logger";import{OPENNEXT_DEPLOY_ORDER as m,OPENNEXT_DESTROY_ORDER as y}from"../../types/operations.js";import{readInfrastructureContent as x}from"../../types/detection/patternDetection.js";import{runOpenNextBuild as N,BUILD_TIMEOUT_MS as O,IMPORT_MAP_TIMEOUT_MS as B}from"../application/openNextBuild.js";function p(r){return{hasNetwork:!0,hasCompute:!0,hasDatabase:r,hasStorage:!0,hasMessaging:!0,hasCdn:!0}}const M={name:"opennext",priority:10,detect(r){const t={detected:!1,pattern:null,reason:"No OpenNext pattern found",resources:p(!1),hasDatabase:!1,hasDockerfile:!1},e=x(r.appPath);if(e===null||e==="")return{...t,reason:"No infrastructure.ts found"};const a=l(e).patternResources.find(o=>c(o.type));if(a===void 0)return{...t,reason:'No PatternFactory with type: "payload" or "nextjs" in infrastructure.ts'};if(a.type==="payload")return{detected:!0,pattern:"payload",reason:'PatternFactory with type: "payload" detected',resources:p(!0),hasDatabase:!0,hasDockerfile:!1};if(a.type==="nextjs"){const o=a.config.database!==void 0;return{detected:!0,pattern:"nextjs",reason:'PatternFactory with type: "nextjs" detected',resources:p(o),hasDatabase:o,hasDockerfile:!1}}return{...t,reason:"PatternFactory found but no recognised pattern type"}},plan(r,t){const e=t.pattern==="payload"?[{name:"payload-import-map",binary:"npx",args:["payload","generate:importmap"],timeoutMs:B}]:[];return{builderName:"opennext",deployOrder:m,destroyOrder:y,parallelDestroy:!0,preBuildCommands:e,buildCommand:{name:"open-next-build",binary:"open-next",args:["build"],timeoutMs:O},requiresDockerBuild:!1,resources:t.resources}},async build(r,t,e,n){if(n?.skipBuild||n?.infraOnly)return f.debug("openNextBuilder","Build skipped",{skipBuild:n.skipBuild,infraOnly:n.infraOnly}),i(void 0);const a={kind:"application",appName:d(r)||"app",path:r},u=t.preBuildCommands.some(s=>s.name==="payload-import-map")?"payload":"nextjs";return await N(a,u,{onOpenNextBuildStart:()=>e.onBuildStart?.("opennext"),onOpenNextProgress:s=>e.onBuildProgress?.("opennext",s),onOpenNextBuildComplete:()=>e.onBuildComplete?.("opennext"),onOpenNextBuildError:s=>e.onBuildError?.("opennext",s)},void 0,n?.abortSignal)}};export{M as openNextBuilder};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StaticSiteBuilder — FrameworkBuilder implementation for static-site apps.
|
|
3
|
+
*
|
|
4
|
+
* Detects a `type: "staticsite"` PatternFactory call in infrastructure.ts,
|
|
5
|
+
* produces a single-stack (Cdn) build plan, and runs the app's own build
|
|
6
|
+
* command to produce the static artefacts that CDK's BucketDeployment then
|
|
7
|
+
* uploads to S3.
|
|
8
|
+
*
|
|
9
|
+
* Priority 50 — strictly between OpenNext (10) and Docker (100). This is
|
|
10
|
+
* load-bearing: without it the Docker catch-all (priority 100) would claim
|
|
11
|
+
* the static site and emit a container deployment plan.
|
|
12
|
+
*
|
|
13
|
+
* Unlike OpenNext, the build command and its working directory are not
|
|
14
|
+
* hardcoded — they are the app's own, read out of infrastructure.ts with the
|
|
15
|
+
* generator's AST parser (`@fjall/generator` is already a dependency, and its
|
|
16
|
+
* barrel already pulls the parser in, so this costs nothing over a regex).
|
|
17
|
+
*/
|
|
18
|
+
import type { FrameworkBuilder } from "../../types/frameworkBuilder.js";
|
|
19
|
+
/** Default static-site build timeout: 10 minutes (mirrors the OpenNext budget) */
|
|
20
|
+
export declare const STATIC_BUILD_TIMEOUT_MS = 600000;
|
|
21
|
+
/**
|
|
22
|
+
* Static-site FrameworkBuilder.
|
|
23
|
+
*
|
|
24
|
+
* Priority 50 — checked after OpenNext (more specific) and before Docker
|
|
25
|
+
* (the fallback catch-all).
|
|
26
|
+
*/
|
|
27
|
+
export declare const staticSiteBuilder: FrameworkBuilder;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{existsSync as y}from"fs";import{resolve as f}from"path";import{success as m,failure as u,parseInfrastructure as p}from"@fjall/generator";import{filterDangerousEnvVars as b,maskSensitiveOutput as d,parseShellArgs as B}from"@fjall/util";import{logger as D}from"@fjall/util/logger";import{getApplicationDeployOrder as E,getApplicationDestroyOrder as h}from"../../types/operations.js";import{readInfrastructureContent as g}from"../../types/detection/patternDetection.js";import{spawnWithTimeout as w}from"../spawnHelpers.js";const O=6e5,S={hasNetwork:!1,hasCompute:!1,hasDatabase:!1,hasStorage:!1,hasMessaging:!1,hasCdn:!0};function C(o){return p(o).patternResources.some(r=>r.type==="staticsite")}function P(o){const r=g(o);if(r===null||r==="")return;const t=p(r).patternResources.find(n=>n.type==="staticsite");if(t===void 0||t.type!=="staticsite")return;const{source:i,build:s}=t.config,a=s?.command,c=s?.outputDir;if(!(i===void 0||i===""||a===void 0||a===""||c===void 0||c===""))return{source:i,command:a,outputDir:c}}const R={name:"staticsite",priority:50,detect(o){const r={detected:!1,pattern:null,reason:"No static-site pattern found",resources:S,hasDatabase:!1,hasDockerfile:!1},t=g(o.appPath);return t===null||t===""?{...r,reason:"No infrastructure.ts found"}:C(t)?{detected:!0,pattern:"staticsite",reason:'PatternFactory with type: "staticsite" detected',resources:S,hasDatabase:!1,hasDockerfile:!1}:{...r,reason:'No PatternFactory with type: "staticsite"'}},plan(o,r){const t=P(o.appPath);let i=null;if(t!==void 0){const[s,...a]=B(t.command);s!==void 0&&(i={name:"static-site-build",binary:s,args:a,timeoutMs:O,cwd:t.source})}return{builderName:"staticsite",deployOrder:E({resources:r.resources}),destroyOrder:h({resources:r.resources}),parallelDestroy:!1,preBuildCommands:[],buildCommand:i,requiresDockerBuild:!1,artefactDir:t?.outputDir,resources:r.resources}},async build(o,r,t,i){if(i?.skipBuild||i?.infraOnly)return D.debug("staticSiteBuilder","Build skipped",{skipBuild:i.skipBuild,infraOnly:i.infraOnly}),m(void 0);const{buildCommand:s}=r;if(s===null){const e='Static-site build command could not be read from infrastructure.ts. The pattern needs an inline build block \u2014 build: { command: "npm run build", outputDir: "out" } \u2014 with literal strings, not variables or expressions.';return t.onBuildError?.("staticsite",e),u(new Error(e))}const a=f(o,s.cwd??"."),c=b(globalThis.process.env);t.onBuildStart?.("staticsite"),t.onBuildProgress?.("staticsite",d("Starting static-site build..."));const n=await w({command:s.binary,args:[...s.args],cwd:a,env:{...c,FORCE_COLOR:"0"},timeout:s.timeoutMs,...i?.abortSignal!==void 0&&{abortSignal:i.abortSignal},onStdoutData:e=>t.onBuildProgress?.("staticsite",d(e.trim())),onStderrData:e=>t.onBuildProgress?.("staticsite",d(e.trim()))});if(n.type==="timeout"){const e=`Static-site build timed out after ${s.timeoutMs/1e3} seconds`;return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.type==="aborted"){const e="Static-site build cancelled";return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.type==="enoent"){const e=`Static-site build command not found: ${s.binary}. Ensure it is installed and in PATH.`;return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.type==="spawn_error"){const e=d(`Failed to spawn static-site build: ${n.error.message}`);return t.onBuildError?.("staticsite",e),u(new Error(e))}if(n.code!==0){const e=d(n.stderr||n.stdout);return t.onBuildError?.("staticsite",`Static-site build failed (exit code ${n.code})`),u(new Error(`Static-site build failed (exit code ${n.code}):
|
|
2
|
+
${e}`))}if(r.artefactDir!==void 0){const e=f(a,r.artefactDir);if(!y(e)){const l=`Static-site build completed but output directory '${r.artefactDir}' was not found`;return t.onBuildError?.("staticsite",l),u(new Error(l))}}return t.onBuildComplete?.("staticsite"),t.onBuildProgress?.("staticsite",d("Static-site build completed successfully")),m(void 0)}};export{O as STATIC_BUILD_TIMEOUT_MS,R as staticSiteBuilder};
|
|
@@ -18,6 +18,10 @@ export type SpawnResult = {
|
|
|
18
18
|
type: "timeout";
|
|
19
19
|
stdout: string;
|
|
20
20
|
stderr: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: "aborted";
|
|
23
|
+
stdout: string;
|
|
24
|
+
stderr: string;
|
|
21
25
|
} | {
|
|
22
26
|
type: "enoent";
|
|
23
27
|
error: Error;
|
|
@@ -35,6 +39,10 @@ export declare function destroyProcessStreams(childProcess: ReturnType<typeof sp
|
|
|
35
39
|
export declare function isEnoentError(err: unknown): err is NodeJS.ErrnoException;
|
|
36
40
|
/**
|
|
37
41
|
* Spawn a child process with timeout handling and stream collection.
|
|
42
|
+
*
|
|
43
|
+
* `abortSignal` is the caller's cancellation signal (`DeployParams.abortSignal`
|
|
44
|
+
* — Ctrl-C, or `fjall deployments cancel`). Without it a cancelled deploy still
|
|
45
|
+
* waits out the full build timeout, because nothing else can reach the child.
|
|
38
46
|
*/
|
|
39
47
|
export declare function spawnWithTimeout(options: {
|
|
40
48
|
command: string;
|
|
@@ -42,6 +50,7 @@ export declare function spawnWithTimeout(options: {
|
|
|
42
50
|
cwd: string;
|
|
43
51
|
env: Record<string, string | undefined>;
|
|
44
52
|
timeout: number;
|
|
53
|
+
abortSignal?: AbortSignal;
|
|
45
54
|
onStdoutData?: (data: string) => void;
|
|
46
55
|
onStderrData?: (data: string) => void;
|
|
47
56
|
}): Promise<SpawnResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as j}from"child_process";import{logger as l}from"@fjall/util/logger";function m(e){try{e.stdout?.destroy()}catch(s){l.debug("spawnHelpers","stdout destroy failed",{error:String(s)})}try{e.stderr?.destroy()}catch(s){l.debug("spawnHelpers","stderr destroy failed",{error:String(s)})}}function v(e){return e instanceof Error&&"code"in e&&e.code==="ENOENT"}function x(e){const{command:s,args:f,cwd:y,env:g,timeout:S,abortSignal:a,onStdoutData:b,onStderrData:E}=e;return new Promise(h=>{let c=!1;const r=t=>{c||(c=!0,h(t))};if(a?.aborted===!0){r({type:"aborted",stdout:"",stderr:""});return}const o=j(s,f,{cwd:y,shell:!1,stdio:["ignore","pipe","pipe"],env:g}),d=[],i=[];o.stdout?.on("data",t=>{const n=t.toString();d.push(n),b?.(n)}),o.stderr?.on("data",t=>{const n=t.toString();i.push(n),E?.(n)});const w=setTimeout(()=>{m(o),o.kill("SIGTERM"),u(),r({type:"timeout",stdout:d.join(""),stderr:i.join("")})},S),p=()=>{m(o),o.kill("SIGTERM"),u(),r({type:"aborted",stdout:d.join(""),stderr:i.join("")})},u=()=>{clearTimeout(w),a?.removeEventListener("abort",p)};a?.addEventListener("abort",p,{once:!0}),o.on("close",t=>{u(),r({type:"success",code:t??1,stdout:d.join(""),stderr:i.join("")})}),o.on("error",t=>{u(),v(t)?r({type:"enoent",error:t}):r({type:"spawn_error",error:t})})})}export{m as destroyProcessStreams,v as isEnoentError,x as spawnWithTimeout};
|
|
@@ -13,8 +13,12 @@
|
|
|
13
13
|
* `deploymentEventSchema.ts`, superseded in a later phase). They coexist during
|
|
14
14
|
* the migration; do not conflate them.
|
|
15
15
|
*
|
|
16
|
-
* Browser-safe:
|
|
17
|
-
* `@fjall/util/config`
|
|
16
|
+
* Browser-safe: imports only Zod, pure constant tuples, and the static const
|
|
17
|
+
* `TRAIL_LIFECYCLE_STATES` from `@fjall/util/config`. `config.js` DOES carry
|
|
18
|
+
* `import * as fs`/`import * as path`, but they are used only inside functions
|
|
19
|
+
* (never at module-eval), so importing this module accesses no Node builtin —
|
|
20
|
+
* see the eval-safety invariant in `./index.ts`. Keep the import to that static
|
|
21
|
+
* const; do not pull a config.js helper that touches fs/path into eval scope.
|
|
18
22
|
*/
|
|
19
23
|
import { z } from "zod";
|
|
20
24
|
/** The contract marker stamped on every event this build emits. */
|
|
@@ -64,7 +68,7 @@ export declare const DETECTION_PHASES: readonly ["detect", "synth", "hash", "val
|
|
|
64
68
|
/** started/completed — reused across the phase-boundary events in this contract. */
|
|
65
69
|
export declare const PHASE_STATUSES: readonly ["started", "completed"];
|
|
66
70
|
/** Build-pipeline kinds carried by the `build.*` events. */
|
|
67
|
-
export declare const BUILDERS: readonly ["docker", "buildpush", "opennext"];
|
|
71
|
+
export declare const BUILDERS: readonly ["docker", "buildpush", "opennext", "staticsite"];
|
|
68
72
|
/**
|
|
69
73
|
* Cascade per-target outcome. Mirrors the engine-side `CascadeOutcomeResult`
|
|
70
74
|
* (orchestration/organisation/cascadeSummary.ts); the wire ledger owns its own
|
|
@@ -314,6 +318,7 @@ export declare const DeployEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
314
318
|
progressKind: z.ZodLiteral<"build.started">;
|
|
315
319
|
builder: z.ZodEnum<{
|
|
316
320
|
docker: "docker";
|
|
321
|
+
staticsite: "staticsite";
|
|
317
322
|
buildpush: "buildpush";
|
|
318
323
|
opennext: "opennext";
|
|
319
324
|
}>;
|
|
@@ -331,6 +336,7 @@ export declare const DeployEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
331
336
|
progressKind: z.ZodLiteral<"build.progress">;
|
|
332
337
|
builder: z.ZodEnum<{
|
|
333
338
|
docker: "docker";
|
|
339
|
+
staticsite: "staticsite";
|
|
334
340
|
buildpush: "buildpush";
|
|
335
341
|
opennext: "opennext";
|
|
336
342
|
}>;
|
|
@@ -350,6 +356,7 @@ export declare const DeployEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
350
356
|
progressKind: z.ZodLiteral<"build.completed">;
|
|
351
357
|
builder: z.ZodEnum<{
|
|
352
358
|
docker: "docker";
|
|
359
|
+
staticsite: "staticsite";
|
|
353
360
|
buildpush: "buildpush";
|
|
354
361
|
opennext: "opennext";
|
|
355
362
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as e}from"zod";import{CASCADE_PHASES as h,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as E}from"./deploymentEventSchema.js";import{TRAIL_MIGRATION_PHASES as A,TRAIL_MIGRATION_STATUSES as C}from"./events.js";import{TRAIL_LIFECYCLE_STATES as p}from"@fjall/util/config";const Ue="fjall.deploy/1.1",Ve=1,Ye=1,_=["fjall.deploy/1.0","fjall.deploy/1.1"],a=256,o=256,s=2048,i=2048,n=4096,j=2048,m=8192,r=2048,g=4096,T=["completed","skipped","error","cancelled"],y=["info","debug","warn"],D=["emptying-bucket","deleting-stack","waiting","complete","error","quarantine-suspected","retained-buckets"],v=["bootstrap","synth","deploy","destroy"],P=["success","failure","cancelled","no-changes","rejected"],R=["detect","synth","hash","validate"],c=["started","completed"],l=["docker","buildpush","opennext"],d=["succeeded","skipped","failed"],N=["create","update","replace","delete","read","no-op"],K=["will","may","conditional","none"],O=["destructive","cost","policy"],f=["approved","rejected","expired","superseded"],u=e.object({create:e.number().int().nonnegative(),update:e.number().int().nonnegative(),replace:e.number().int().nonnegative(),delete:e.number().int().nonnegative(),read:e.number().int().nonnegative(),"no-op":e.number().int().nonnegative()}).strict(),L={create:!0,update:!0,replace:!0,delete:!0,read:!0,"no-op":!0},t={contract:e.enum(_),deploymentId:e.string().min(1).max(a),seq:e.number().int().nonnegative(),time:e.string().datetime()},x=e.object({index:e.number().int().nonnegative(),total:e.number().int().positive()}).strict(),b=e.object({id:e.string().max(a),name:e.string().max(o)}).strict(),k=e.object({logicalId:e.string().max(a),resourceType:e.string().max(a),status:e.string().max(64),displayName:e.string().max(o).optional(),category:e.enum(E).optional(),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),statusReason:e.string().max(i).optional(),physicalId:e.string().max(r).optional(),expectedDurationSeconds:e.number().nonnegative().optional()}).strict(),M=e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict(),I=e.object({path:e.string().max(512),forcesReplacement:e.boolean()}).strict(),U=e.object({address:e.string().max(512),resourceType:e.string().max(a),action:e.enum(N),stack:e.string().max(a).optional(),replacementMode:e.enum(K).optional(),dataLoss:e.boolean().optional(),propertyChanges:e.array(I).max(100).optional()}).strict(),S=e.object({accountId:e.string().max(a),error:e.string().max(n)}).strict(),V=e.object({platformDeployed:e.boolean(),platformSkipped:e.boolean(),platformFailed:e.boolean(),domainsDeployed:e.boolean(),accountsDeployed:e.number().int().nonnegative(),accountsSkipped:e.number().int().nonnegative(),accountsFailed:e.number().int().nonnegative(),errors:e.array(S).max(1e3)}).strict(),Y=e.object({accountId:e.string().max(a),accountName:e.string().max(o),region:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),B=e.object({accountId:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),G=e.object({members:e.array(Y).max(1e3),platform:B.optional(),domainsDeployed:e.boolean(),errors:e.array(S).max(1e3),totalDurationMs:e.number().nonnegative()}).strict(),X=e.object({bucketName:e.string().max(o),accountId:e.string().max(a).optional()}).strict(),w=e.object({retainedBuckets:e.array(e.string().max(o)).max(1e3),message:e.string().max(s)}).strict(),H=e.union([X,w]),q=e.object({stack:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional()}).strict(),F=e.object({accountId:e.string().max(a),region:e.string().max(a),profileName:e.string().max(o).optional()}).strict(),z=e.object({...t,progressKind:e.literal("step.started"),step:b,progress:x.optional()}).strict(),J=e.object({...t,progressKind:e.literal("step.completed"),step:b,status:e.enum(T),progress:x.optional(),errorMessage:e.string().max(n).optional()}).strict(),Q=e.object({...t,progressKind:e.literal("log"),level:e.enum(y),message:e.string().max(s)}).strict(),W=e.object({...t,progressKind:e.literal("output"),chunk:e.string().max(m)}).strict(),Z=e.object({...t,progressKind:e.literal("resource"),resource:k,scope:e.object({stack:e.string().max(a).optional(),operationKey:e.string().max(a).optional(),region:e.string().max(a).optional()}).strict().optional()}).strict(),$=e.object({...t,progressKind:e.literal("phase.parallel"),status:e.enum(c),stacks:e.array(e.string().max(a)).max(50),description:e.string().max(o).optional(),results:e.array(q).max(50).optional()}).strict(),ee=e.object({...t,progressKind:e.literal("build.started"),builder:e.enum(l),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),ecrRepositoryUri:e.string().max(r).optional()}).strict(),te=e.object({...t,progressKind:e.literal("build.progress"),builder:e.enum(l),message:e.string().max(s),serviceName:e.string().max(o).optional(),percentage:e.number().optional(),layerId:e.string().max(a).optional(),status:e.string().max(64).optional()}).strict(),ae=e.object({...t,progressKind:e.literal("build.completed"),builder:e.enum(l),success:e.boolean(),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),imageDigest:e.string().max(a).optional(),imageUri:e.string().max(g).optional(),ecrRepositoryArn:e.string().max(r).optional(),durationMs:e.number().nonnegative().optional(),error:e.string().max(n).optional()}).strict(),oe=e.object({...t,progressKind:e.literal("taskdef.registered"),serviceName:e.string().max(o),taskDefinitionArn:e.string().max(r),previousTaskDefinitionArn:e.string().max(r),revision:e.number().int().nonnegative(),family:e.string().max(o),imageDigest:e.string().max(a).optional()}).strict(),re=e.object({...t,progressKind:e.literal("ecs.update"),status:e.string().max(64),service:e.string().max(o).optional()}).strict(),se=e.object({...t,progressKind:e.literal("ecs.progress"),message:e.string().max(s),percentage:e.number().optional()}).strict(),ne=e.object({...t,progressKind:e.literal("ecs.completed"),serviceName:e.string().max(o),serviceArn:e.string().max(r),success:e.boolean(),taskDefinitionArn:e.string().max(r),durationMs:e.number().nonnegative(),reason:e.string().max(i).optional(),finalRunningCount:e.number().int().nonnegative().optional(),finalDesiredCount:e.number().int().nonnegative().optional()}).strict(),ie=e.object({...t,progressKind:e.literal("migrations.started"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),imageDigest:e.string().max(a)}).strict(),ce=e.object({...t,progressKind:e.literal("migrations.completed"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),success:e.boolean(),durationMs:e.number().nonnegative(),exitCode:e.number().int().optional(),reason:e.string().max(i).optional()}).strict(),le=e.object({...t,progressKind:e.literal("cdk.bootstrap"),status:e.string().max(s)}).strict(),pe=e.object({...t,progressKind:e.literal("cdk.output"),outputType:e.enum(["synth","diff"]),output:e.string().max(m)}).strict(),me=e.object({...t,progressKind:e.literal("detection.completed"),detection:M}).strict(),ge=e.object({...t,progressKind:e.literal("detection.phase"),phase:e.enum(R),status:e.enum(c)}).strict(),de=e.object({...t,progressKind:e.literal("cascade.started")}).strict(),ue=e.object({...t,progressKind:e.literal("cascade.accountsReconciled"),hasPlatformAccount:e.boolean(),hasMemberAccounts:e.boolean()}).strict(),xe=e.object({...t,progressKind:e.literal("cascade.orgChanges"),hasOrgChanges:e.boolean()}).strict(),be=e.object({...t,progressKind:e.literal("cascade.missingAccounts"),accountNames:e.array(e.string().max(o)).max(256)}).strict(),Se=e.object({...t,progressKind:e.literal("cascade.phase"),phase:e.enum(h),status:e.enum(c)}).strict(),he=e.object({...t,progressKind:e.literal("cascade.account.started"),operationKey:e.string().max(a),accountId:e.string().max(a),region:e.string().max(a),deployType:e.string().max(64).optional()}).strict(),Ee=e.object({...t,progressKind:e.literal("cascade.account.phase"),operationKey:e.string().max(a),phase:e.enum(v),region:e.string().max(a).optional()}).strict(),Ae=e.object({...t,progressKind:e.literal("cascade.account.completed"),operationKey:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional(),region:e.string().max(a).optional(),outputs:e.record(e.string().max(o),e.string().max(i)).optional(),skipped:e.boolean().optional()}).strict(),Ce=e.object({...t,progressKind:e.literal("cascade.completed"),result:V}).strict(),_e=e.object({...t,progressKind:e.literal("cascade.ledger"),ledger:G}).strict(),je=e.object({...t,progressKind:e.literal("trail.phase"),accountId:e.string().max(a),accountName:e.string().max(o),phase:e.enum(A),status:e.enum(C),detail:e.string().max(j).optional()}).strict(),Te=e.object({...t,progressKind:e.literal("trail.lifecycle"),accountId:e.string().max(a),to:e.enum(p),from:e.enum(p).optional()}).strict(),ye=e.object({...t,progressKind:e.literal("cleanup.progress"),stackName:e.string().max(a),phase:e.enum(D),detail:H.optional()}).strict(),De=e.object({...t,progressKind:e.literal("auth.ssoUrl"),url:e.string().max(g).nullable()}).strict(),ve=e.object({...t,progressKind:e.literal("auth.completed"),result:F.nullable()}).strict(),Pe=e.object({...t,progressKind:e.literal("error"),message:e.string().max(n),name:e.string().max(o).optional()}).strict(),Re=e.object({...t,progressKind:e.literal("deploy.completed"),result:e.enum(P),ok:e.boolean(),errorType:e.string().max(128).optional(),message:e.string().max(s)}).strict(),Ne=e.object({...t,progressKind:e.literal("plan.available"),plan:e.object({summary:e.string().max(s),changeCount:e.number().int().nonnegative(),hasDestructiveChanges:e.boolean(),changes:e.array(U).max(1e3).optional(),diffRef:e.string().max(512).optional(),iamBroadening:e.boolean().optional(),securityGroupBroadening:e.boolean().optional(),changeCountsByAction:u.optional()}).strict()}).strict(),Ke=e.object({...t,progressKind:e.literal("approval.awaiting"),approval:e.object({token:e.string().max(512),kind:e.enum(O),reason:e.string().max(s),expiresAt:e.string().datetime(),assemblyDigest:e.string().max(128).optional(),changeCounts:u.optional(),approvalClass:e.string().max(64).optional(),requiredApprovers:e.array(e.string().max(256)).max(50).optional()}).strict()}).strict(),Oe=e.object({...t,progressKind:e.literal("approval.resolved"),approval:e.object({token:e.string().max(512),decision:e.enum(f),actor:e.string().max(o).optional()}).strict()}).strict(),Be=e.discriminatedUnion("progressKind",[z,J,Q,W,Z,$,ee,te,ae,oe,re,se,ne,ie,ce,le,pe,me,ge,de,ue,xe,be,Se,he,Ee,Ae,Ce,_e,je,Te,ye,De,ve,Pe,Re,Ne,Ke,Oe]),fe={"step.started":!0,"step.completed":!0,log:!0,output:!0,resource:!0,"phase.parallel":!0,"build.started":!0,"build.progress":!0,"build.completed":!0,"taskdef.registered":!0,"ecs.update":!0,"ecs.progress":!0,"ecs.completed":!0,"migrations.started":!0,"migrations.completed":!0,"cdk.bootstrap":!0,"cdk.output":!0,"detection.completed":!0,"detection.phase":!0,"cascade.started":!0,"cascade.accountsReconciled":!0,"cascade.orgChanges":!0,"cascade.missingAccounts":!0,"cascade.phase":!0,"cascade.account.started":!0,"cascade.account.phase":!0,"cascade.account.completed":!0,"cascade.completed":!0,"cascade.ledger":!0,"trail.phase":!0,"trail.lifecycle":!0,"cleanup.progress":!0,"auth.ssoUrl":!0,"auth.completed":!0,error:!0,"deploy.completed":!0,"plan.available":!0,"approval.awaiting":!0,"approval.resolved":!0},Ge=Object.keys(fe);export{Ge as ALL_PROGRESS_KINDS,f as APPROVAL_DECISIONS,O as APPROVAL_KINDS,l as BUILDERS,v as CASCADE_ACCOUNT_PHASES,d as CASCADE_OUTCOME_RESULTS,u as ChangeCountsSchema,r as DEPLOY_EVENT_ARN_MAX,Ue as DEPLOY_EVENT_CONTRACT,Ve as DEPLOY_EVENT_CONTRACT_MAJOR,Ye as DEPLOY_EVENT_CONTRACT_MINOR,n as DEPLOY_EVENT_ERROR_MESSAGE_MAX,a as DEPLOY_EVENT_ID_MAX,s as DEPLOY_EVENT_MESSAGE_MAX,o as DEPLOY_EVENT_NAME_MAX,m as DEPLOY_EVENT_OUTPUT_MAX,i as DEPLOY_EVENT_STATUS_REASON_MAX,j as DEPLOY_EVENT_TRAIL_DETAIL_MAX,g as DEPLOY_EVENT_URL_MAX,P as DEPLOY_RESULTS,R as DETECTION_PHASES,Be as DeployEventSchema,k as DeployResourceSchema,y as LOG_LEVELS,c as PHASE_STATUSES,N as PLAN_ACTIONS,U as PlanChangeSchema,I as PlanPropertyChangeSchema,K as REPLACEMENT_MODES,D as STACK_CLEANUP_PHASES,T as STEP_COMPLETE_STATUSES,_ as SUPPORTED_CONTRACT_MARKERS,x as StepProgressSchema};
|
|
1
|
+
import{z as e}from"zod";import{CASCADE_PHASES as h,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as E}from"./deploymentEventSchema.js";import{TRAIL_MIGRATION_PHASES as A,TRAIL_MIGRATION_STATUSES as C}from"./events.js";import{TRAIL_LIFECYCLE_STATES as p}from"@fjall/util/config";const Ue="fjall.deploy/1.1",Ve=1,Ye=1,_=["fjall.deploy/1.0","fjall.deploy/1.1"],a=256,o=256,s=2048,i=2048,n=4096,j=2048,m=8192,r=2048,g=4096,T=["completed","skipped","error","cancelled"],y=["info","debug","warn"],D=["emptying-bucket","deleting-stack","waiting","complete","error","quarantine-suspected","retained-buckets"],v=["bootstrap","synth","deploy","destroy"],P=["success","failure","cancelled","no-changes","rejected"],R=["detect","synth","hash","validate"],c=["started","completed"],l=["docker","buildpush","opennext","staticsite"],d=["succeeded","skipped","failed"],N=["create","update","replace","delete","read","no-op"],K=["will","may","conditional","none"],O=["destructive","cost","policy"],f=["approved","rejected","expired","superseded"],u=e.object({create:e.number().int().nonnegative(),update:e.number().int().nonnegative(),replace:e.number().int().nonnegative(),delete:e.number().int().nonnegative(),read:e.number().int().nonnegative(),"no-op":e.number().int().nonnegative()}).strict(),L={create:!0,update:!0,replace:!0,delete:!0,read:!0,"no-op":!0},t={contract:e.enum(_),deploymentId:e.string().min(1).max(a),seq:e.number().int().nonnegative(),time:e.string().datetime()},x=e.object({index:e.number().int().nonnegative(),total:e.number().int().positive()}).strict(),b=e.object({id:e.string().max(a),name:e.string().max(o)}).strict(),k=e.object({logicalId:e.string().max(a),resourceType:e.string().max(a),status:e.string().max(64),displayName:e.string().max(o).optional(),category:e.enum(E).optional(),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),statusReason:e.string().max(i).optional(),physicalId:e.string().max(r).optional(),expectedDurationSeconds:e.number().nonnegative().optional()}).strict(),M=e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict(),I=e.object({path:e.string().max(512),forcesReplacement:e.boolean()}).strict(),U=e.object({address:e.string().max(512),resourceType:e.string().max(a),action:e.enum(N),stack:e.string().max(a).optional(),replacementMode:e.enum(K).optional(),dataLoss:e.boolean().optional(),propertyChanges:e.array(I).max(100).optional()}).strict(),S=e.object({accountId:e.string().max(a),error:e.string().max(n)}).strict(),V=e.object({platformDeployed:e.boolean(),platformSkipped:e.boolean(),platformFailed:e.boolean(),domainsDeployed:e.boolean(),accountsDeployed:e.number().int().nonnegative(),accountsSkipped:e.number().int().nonnegative(),accountsFailed:e.number().int().nonnegative(),errors:e.array(S).max(1e3)}).strict(),Y=e.object({accountId:e.string().max(a),accountName:e.string().max(o),region:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),B=e.object({accountId:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),G=e.object({members:e.array(Y).max(1e3),platform:B.optional(),domainsDeployed:e.boolean(),errors:e.array(S).max(1e3),totalDurationMs:e.number().nonnegative()}).strict(),X=e.object({bucketName:e.string().max(o),accountId:e.string().max(a).optional()}).strict(),w=e.object({retainedBuckets:e.array(e.string().max(o)).max(1e3),message:e.string().max(s)}).strict(),H=e.union([X,w]),q=e.object({stack:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional()}).strict(),F=e.object({accountId:e.string().max(a),region:e.string().max(a),profileName:e.string().max(o).optional()}).strict(),z=e.object({...t,progressKind:e.literal("step.started"),step:b,progress:x.optional()}).strict(),J=e.object({...t,progressKind:e.literal("step.completed"),step:b,status:e.enum(T),progress:x.optional(),errorMessage:e.string().max(n).optional()}).strict(),Q=e.object({...t,progressKind:e.literal("log"),level:e.enum(y),message:e.string().max(s)}).strict(),W=e.object({...t,progressKind:e.literal("output"),chunk:e.string().max(m)}).strict(),Z=e.object({...t,progressKind:e.literal("resource"),resource:k,scope:e.object({stack:e.string().max(a).optional(),operationKey:e.string().max(a).optional(),region:e.string().max(a).optional()}).strict().optional()}).strict(),$=e.object({...t,progressKind:e.literal("phase.parallel"),status:e.enum(c),stacks:e.array(e.string().max(a)).max(50),description:e.string().max(o).optional(),results:e.array(q).max(50).optional()}).strict(),ee=e.object({...t,progressKind:e.literal("build.started"),builder:e.enum(l),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),ecrRepositoryUri:e.string().max(r).optional()}).strict(),te=e.object({...t,progressKind:e.literal("build.progress"),builder:e.enum(l),message:e.string().max(s),serviceName:e.string().max(o).optional(),percentage:e.number().optional(),layerId:e.string().max(a).optional(),status:e.string().max(64).optional()}).strict(),ae=e.object({...t,progressKind:e.literal("build.completed"),builder:e.enum(l),success:e.boolean(),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),imageDigest:e.string().max(a).optional(),imageUri:e.string().max(g).optional(),ecrRepositoryArn:e.string().max(r).optional(),durationMs:e.number().nonnegative().optional(),error:e.string().max(n).optional()}).strict(),oe=e.object({...t,progressKind:e.literal("taskdef.registered"),serviceName:e.string().max(o),taskDefinitionArn:e.string().max(r),previousTaskDefinitionArn:e.string().max(r),revision:e.number().int().nonnegative(),family:e.string().max(o),imageDigest:e.string().max(a).optional()}).strict(),re=e.object({...t,progressKind:e.literal("ecs.update"),status:e.string().max(64),service:e.string().max(o).optional()}).strict(),se=e.object({...t,progressKind:e.literal("ecs.progress"),message:e.string().max(s),percentage:e.number().optional()}).strict(),ne=e.object({...t,progressKind:e.literal("ecs.completed"),serviceName:e.string().max(o),serviceArn:e.string().max(r),success:e.boolean(),taskDefinitionArn:e.string().max(r),durationMs:e.number().nonnegative(),reason:e.string().max(i).optional(),finalRunningCount:e.number().int().nonnegative().optional(),finalDesiredCount:e.number().int().nonnegative().optional()}).strict(),ie=e.object({...t,progressKind:e.literal("migrations.started"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),imageDigest:e.string().max(a)}).strict(),ce=e.object({...t,progressKind:e.literal("migrations.completed"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),success:e.boolean(),durationMs:e.number().nonnegative(),exitCode:e.number().int().optional(),reason:e.string().max(i).optional()}).strict(),le=e.object({...t,progressKind:e.literal("cdk.bootstrap"),status:e.string().max(s)}).strict(),pe=e.object({...t,progressKind:e.literal("cdk.output"),outputType:e.enum(["synth","diff"]),output:e.string().max(m)}).strict(),me=e.object({...t,progressKind:e.literal("detection.completed"),detection:M}).strict(),ge=e.object({...t,progressKind:e.literal("detection.phase"),phase:e.enum(R),status:e.enum(c)}).strict(),de=e.object({...t,progressKind:e.literal("cascade.started")}).strict(),ue=e.object({...t,progressKind:e.literal("cascade.accountsReconciled"),hasPlatformAccount:e.boolean(),hasMemberAccounts:e.boolean()}).strict(),xe=e.object({...t,progressKind:e.literal("cascade.orgChanges"),hasOrgChanges:e.boolean()}).strict(),be=e.object({...t,progressKind:e.literal("cascade.missingAccounts"),accountNames:e.array(e.string().max(o)).max(256)}).strict(),Se=e.object({...t,progressKind:e.literal("cascade.phase"),phase:e.enum(h),status:e.enum(c)}).strict(),he=e.object({...t,progressKind:e.literal("cascade.account.started"),operationKey:e.string().max(a),accountId:e.string().max(a),region:e.string().max(a),deployType:e.string().max(64).optional()}).strict(),Ee=e.object({...t,progressKind:e.literal("cascade.account.phase"),operationKey:e.string().max(a),phase:e.enum(v),region:e.string().max(a).optional()}).strict(),Ae=e.object({...t,progressKind:e.literal("cascade.account.completed"),operationKey:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional(),region:e.string().max(a).optional(),outputs:e.record(e.string().max(o),e.string().max(i)).optional(),skipped:e.boolean().optional()}).strict(),Ce=e.object({...t,progressKind:e.literal("cascade.completed"),result:V}).strict(),_e=e.object({...t,progressKind:e.literal("cascade.ledger"),ledger:G}).strict(),je=e.object({...t,progressKind:e.literal("trail.phase"),accountId:e.string().max(a),accountName:e.string().max(o),phase:e.enum(A),status:e.enum(C),detail:e.string().max(j).optional()}).strict(),Te=e.object({...t,progressKind:e.literal("trail.lifecycle"),accountId:e.string().max(a),to:e.enum(p),from:e.enum(p).optional()}).strict(),ye=e.object({...t,progressKind:e.literal("cleanup.progress"),stackName:e.string().max(a),phase:e.enum(D),detail:H.optional()}).strict(),De=e.object({...t,progressKind:e.literal("auth.ssoUrl"),url:e.string().max(g).nullable()}).strict(),ve=e.object({...t,progressKind:e.literal("auth.completed"),result:F.nullable()}).strict(),Pe=e.object({...t,progressKind:e.literal("error"),message:e.string().max(n),name:e.string().max(o).optional()}).strict(),Re=e.object({...t,progressKind:e.literal("deploy.completed"),result:e.enum(P),ok:e.boolean(),errorType:e.string().max(128).optional(),message:e.string().max(s)}).strict(),Ne=e.object({...t,progressKind:e.literal("plan.available"),plan:e.object({summary:e.string().max(s),changeCount:e.number().int().nonnegative(),hasDestructiveChanges:e.boolean(),changes:e.array(U).max(1e3).optional(),diffRef:e.string().max(512).optional(),iamBroadening:e.boolean().optional(),securityGroupBroadening:e.boolean().optional(),changeCountsByAction:u.optional()}).strict()}).strict(),Ke=e.object({...t,progressKind:e.literal("approval.awaiting"),approval:e.object({token:e.string().max(512),kind:e.enum(O),reason:e.string().max(s),expiresAt:e.string().datetime(),assemblyDigest:e.string().max(128).optional(),changeCounts:u.optional(),approvalClass:e.string().max(64).optional(),requiredApprovers:e.array(e.string().max(256)).max(50).optional()}).strict()}).strict(),Oe=e.object({...t,progressKind:e.literal("approval.resolved"),approval:e.object({token:e.string().max(512),decision:e.enum(f),actor:e.string().max(o).optional()}).strict()}).strict(),Be=e.discriminatedUnion("progressKind",[z,J,Q,W,Z,$,ee,te,ae,oe,re,se,ne,ie,ce,le,pe,me,ge,de,ue,xe,be,Se,he,Ee,Ae,Ce,_e,je,Te,ye,De,ve,Pe,Re,Ne,Ke,Oe]),fe={"step.started":!0,"step.completed":!0,log:!0,output:!0,resource:!0,"phase.parallel":!0,"build.started":!0,"build.progress":!0,"build.completed":!0,"taskdef.registered":!0,"ecs.update":!0,"ecs.progress":!0,"ecs.completed":!0,"migrations.started":!0,"migrations.completed":!0,"cdk.bootstrap":!0,"cdk.output":!0,"detection.completed":!0,"detection.phase":!0,"cascade.started":!0,"cascade.accountsReconciled":!0,"cascade.orgChanges":!0,"cascade.missingAccounts":!0,"cascade.phase":!0,"cascade.account.started":!0,"cascade.account.phase":!0,"cascade.account.completed":!0,"cascade.completed":!0,"cascade.ledger":!0,"trail.phase":!0,"trail.lifecycle":!0,"cleanup.progress":!0,"auth.ssoUrl":!0,"auth.completed":!0,error:!0,"deploy.completed":!0,"plan.available":!0,"approval.awaiting":!0,"approval.resolved":!0},Ge=Object.keys(fe);export{Ge as ALL_PROGRESS_KINDS,f as APPROVAL_DECISIONS,O as APPROVAL_KINDS,l as BUILDERS,v as CASCADE_ACCOUNT_PHASES,d as CASCADE_OUTCOME_RESULTS,u as ChangeCountsSchema,r as DEPLOY_EVENT_ARN_MAX,Ue as DEPLOY_EVENT_CONTRACT,Ve as DEPLOY_EVENT_CONTRACT_MAJOR,Ye as DEPLOY_EVENT_CONTRACT_MINOR,n as DEPLOY_EVENT_ERROR_MESSAGE_MAX,a as DEPLOY_EVENT_ID_MAX,s as DEPLOY_EVENT_MESSAGE_MAX,o as DEPLOY_EVENT_NAME_MAX,m as DEPLOY_EVENT_OUTPUT_MAX,i as DEPLOY_EVENT_STATUS_REASON_MAX,j as DEPLOY_EVENT_TRAIL_DETAIL_MAX,g as DEPLOY_EVENT_URL_MAX,P as DEPLOY_RESULTS,R as DETECTION_PHASES,Be as DeployEventSchema,k as DeployResourceSchema,y as LOG_LEVELS,c as PHASE_STATUSES,N as PLAN_ACTIONS,U as PlanChangeSchema,I as PlanPropertyChangeSchema,K as REPLACEMENT_MODES,D as STACK_CLEANUP_PHASES,T as STEP_COMPLETE_STATUSES,_ as SUPPORTED_CONTRACT_MARKERS,x as StepProgressSchema};
|
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
* These are safe for browser bundles. Filesystem-based detection functions
|
|
5
5
|
* remain in patternDetection.ts.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { isOpenNextPatternType, type OpenNextPatternType } from "@fjall/util/patterns";
|
|
8
|
+
/**
|
|
9
|
+
* The OpenNext accept-set is derived from `PATTERN_REGISTRY` in `@fjall/util`:
|
|
10
|
+
* a pattern is OpenNext-shaped iff its declared artefact is an OpenNext Lambda
|
|
11
|
+
* bundle. Re-listing the members here is how `staticsite` would silently join
|
|
12
|
+
* the OpenNext build path.
|
|
13
|
+
*/
|
|
14
|
+
export type OpenNextPattern = OpenNextPatternType;
|
|
9
15
|
export declare const OPENNEXT_PATTERNS: ReadonlySet<string>;
|
|
10
|
-
export declare
|
|
16
|
+
export declare const isOpenNextPattern: typeof isOpenNextPatternType;
|
|
11
17
|
export interface AppResourceFlags {
|
|
12
18
|
hasNetwork: boolean;
|
|
13
19
|
hasCompute: boolean;
|
|
@@ -16,4 +22,3 @@ export interface AppResourceFlags {
|
|
|
16
22
|
hasMessaging: boolean;
|
|
17
23
|
hasCdn: boolean;
|
|
18
24
|
}
|
|
19
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{OPENNEXT_PATTERN_TYPES as t,isOpenNextPatternType as e}from"@fjall/util/patterns";const T=new Set(t),n=e;export{T as OPENNEXT_PATTERNS,n as isOpenNextPattern};
|
|
@@ -40,6 +40,13 @@ export interface BuildPlan {
|
|
|
40
40
|
readonly buildCommand: BuildCommand | null;
|
|
41
41
|
/** Whether this plan requires a Docker build (standard apps with Dockerfile) */
|
|
42
42
|
readonly requiresDockerBuild: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Directory the build must produce, relative to the build command's `cwd`.
|
|
45
|
+
* Verified to exist after `build()` completes. Set by builders whose artefacts
|
|
46
|
+
* are uploaded to a bucket rather than containerised (static sites); the
|
|
47
|
+
* Docker/OpenNext builders leave it undefined.
|
|
48
|
+
*/
|
|
49
|
+
readonly artefactDir?: string;
|
|
43
50
|
/** Infrastructure requirements */
|
|
44
51
|
readonly resources: AppResourceFlags;
|
|
45
52
|
}
|
|
@@ -71,6 +78,13 @@ export interface BuildOptions {
|
|
|
71
78
|
readonly skipBuild?: boolean;
|
|
72
79
|
/** Only deploy infrastructure, skip application build */
|
|
73
80
|
readonly infraOnly?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* The deploy's cancellation signal (`DeployParams.abortSignal` — Ctrl-C, or
|
|
83
|
+
* `fjall deployments cancel`). A build can run for minutes; without the
|
|
84
|
+
* signal a cancelled deploy has no way to reach the child process and waits
|
|
85
|
+
* out the full build timeout before noticing.
|
|
86
|
+
*/
|
|
87
|
+
readonly abortSignal?: AbortSignal;
|
|
74
88
|
}
|
|
75
89
|
/** The FrameworkBuilder interface — detect/plan/build lifecycle */
|
|
76
90
|
export interface FrameworkBuilder {
|
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@fjall/deploy-core/types` — the BROWSER-SAFE type/schema barrel.
|
|
3
|
+
*
|
|
4
|
+
* INVARIANT: nothing re-exported here may ACCESS a Node builtin at MODULE-EVAL.
|
|
5
|
+
* The webapp imports this subpath from CLIENT-reachable modules (e.g.
|
|
6
|
+
* `app/types/approval-plan.ts`, `app/types/destruction-consent.ts`); Vite's dev
|
|
7
|
+
* esbuild bundles the whole barrel without tree-shaking and stubs each Node
|
|
8
|
+
* builtin with a shim that THROWS ON ACCESS, killing React hydration app-wide in
|
|
9
|
+
* dev — while prod Rollup tree-shakes the unused module out, so CI stays green
|
|
10
|
+
* and the breakage is invisible to CI (the 2026-07-07 incident). Two shapes trip
|
|
11
|
+
* the eval-time access: a NAMED builtin import (`import { readFileSync } from
|
|
12
|
+
* "fs"`) binds to the throwing shim at link time, and a top-level builtin call
|
|
13
|
+
* (`readFileSync(...)` at module scope) calls it immediately. A bare NAMESPACE
|
|
14
|
+
* import (`import * as fs from "fs"`) used only inside functions does NOT trip it
|
|
15
|
+
* — the shim is never accessed at eval.
|
|
16
|
+
*
|
|
17
|
+
* deploy-core's OWN re-exported modules are kept fully Node-builtin-free: the
|
|
18
|
+
* fs-based helpers (`deriveResourcesFromManifestStacks` with its named `fs`
|
|
19
|
+
* import; the FjallState IO functions with named `fs`/`crypto`) — the two
|
|
20
|
+
* modules that tripped the 2026-07-07 incident — are NOT re-exported here. Their
|
|
21
|
+
* server-only consumers import them straight from the LEAF modules
|
|
22
|
+
* (`./detection/patternDetection.js`, `./config/FjallState.js`) and the ROOT
|
|
23
|
+
* barrel (`../index.js`) re-exports them — never from here.
|
|
24
|
+
*
|
|
25
|
+
* One TOLERATED cross-package builtin edge: `deployEvent.js` imports the static
|
|
26
|
+
* const `TRAIL_LIFECYCLE_STATES` from `@fjall/util/config`, which carries
|
|
27
|
+
* `import * as fs`/`import * as path` used ONLY inside functions. That is
|
|
28
|
+
* import-safe (verified: esbuild-bundle this barrel for the browser with a
|
|
29
|
+
* throw-on-access builtin stub → importing it does not throw). FRAGILE: if
|
|
30
|
+
* `config.js` ever adds a top-level fs/path call or a named builtin import, this
|
|
31
|
+
* barrel breaks — `TRAIL_LIFECYCLE_STATES` should then move to a genuinely
|
|
32
|
+
* builtin-free `@fjall/util` module. Before adding a re-export here, prefer a
|
|
33
|
+
* Node-builtin-free module; if it transitively pulls a builtin, that builtin
|
|
34
|
+
* MUST be a namespace import never accessed at eval (`import type` is always
|
|
35
|
+
* fine — it is erased).
|
|
36
|
+
*/
|
|
1
37
|
export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, DEPLOYMENT_EVENT_STATUS_REASON_MAX, DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX, DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES, toCascadePhase } from "./deploymentEventSchema.js";
|
|
2
38
|
export type { DeploymentEvent, DeploymentEventType, DeploymentEventResourceCategory, DeploymentEventCascadePhase, DeploymentEventCascadeAccountStatus } from "./deploymentEventSchema.js";
|
|
3
39
|
export type { AwsCredentials, DeployIdentity, ScopedBuildSecretSessionMinter } from "./credentials.js";
|
|
@@ -32,11 +68,9 @@ export type { ParallelDeploymentResult, ParallelDeployGroup, ParallelOperation,
|
|
|
32
68
|
export { PARALLEL_OPERATION_TYPES } from "./deployment/index.js";
|
|
33
69
|
export type { OpenNextPattern, AppResourceFlags } from "./detection/patternTypes.js";
|
|
34
70
|
export { isOpenNextPattern, OPENNEXT_PATTERNS } from "./detection/patternTypes.js";
|
|
35
|
-
export { deriveResourcesFromManifestStacks } from "./detection/patternDetection.js";
|
|
36
71
|
export { STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME } from "./constants.js";
|
|
37
72
|
export { ApplicationError, wrapApplicationError, type ApplicationErrorType, type StackDeploymentData, type StackDeploymentOptions, type ApplicationDeploymentData, type ApplicationDestructionData } from "./application/index.js";
|
|
38
73
|
export type { FjallStateFile, TemplateHashEntry } from "./config/FjallState.js";
|
|
39
|
-
export { FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, regionSuffix } from "./config/FjallState.js";
|
|
40
74
|
export type { FrameworkBuilder, FrameworkDetection, BuildPlan, BuildCommand, BuildCallbacks, DetectionContext, BuildOptions } from "./frameworkBuilder.js";
|
|
41
75
|
export { STEP_IDS, STEP_NAMES, INFRASTRUCTURE_STEP_NAMES, INFRA_STEP_NAME } from "./stepDefinitions.js";
|
|
42
76
|
export type { StepId, InfrastructureStepName, StepDefinition, StepDeploymentType, Operation, StepContext } from "./stepDefinitions.js";
|
package/dist/src/types/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DeploymentEventSchema as S,DEPLOYMENT_EVENT_TYPES as
|
|
1
|
+
import{DeploymentEventSchema as S,DEPLOYMENT_EVENT_TYPES as _,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as T,DEPLOYMENT_EVENT_STATUS_REASON_MAX as A,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as t,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as r,CASCADE_PHASES as o,CASCADE_ACCOUNT_STATUSES as a,toCascadePhase as R}from"./deploymentEventSchema.js";import{isQuarantineDetail as P,isRetainedBucketsDetail as N}from"./callbacks.js";import{DeployEventSchema as D,StepProgressSchema as c,DeployResourceSchema as L,PlanChangeSchema as p,PlanPropertyChangeSchema as C,ChangeCountsSchema as n,DEPLOY_EVENT_CONTRACT as m,DEPLOY_EVENT_CONTRACT_MAJOR as I,DEPLOY_EVENT_CONTRACT_MINOR as s,SUPPORTED_CONTRACT_MARKERS as l,DEPLOY_EVENT_ID_MAX as M,DEPLOY_EVENT_NAME_MAX as h,DEPLOY_EVENT_MESSAGE_MAX as V,DEPLOY_EVENT_STATUS_REASON_MAX as U,DEPLOY_EVENT_ERROR_MESSAGE_MAX as Y,DEPLOY_EVENT_TRAIL_DETAIL_MAX as d,DEPLOY_EVENT_OUTPUT_MAX as f,DEPLOY_EVENT_ARN_MAX as g,DEPLOY_EVENT_URL_MAX as u,STEP_COMPLETE_STATUSES as x,LOG_LEVELS as G,STACK_CLEANUP_PHASES as X,CASCADE_ACCOUNT_PHASES as y,DEPLOY_RESULTS as F,DETECTION_PHASES as K,PHASE_STATUSES as k,BUILDERS as H,CASCADE_OUTCOME_RESULTS as b,PLAN_ACTIONS as v,REPLACEMENT_MODES as B,APPROVAL_KINDS as J,APPROVAL_DECISIONS as w,ALL_PROGRESS_KINDS as Q}from"./deployEvent.js";import{createDeployEmitter as j}from"./deployEmitter.js";import{parseDeployEvent as z,parseDeployContractVersion as Z}from"./deployEventParse.js";import{TRAIL_MIGRATION_PHASES as EE,TRAIL_MIGRATION_STATUSES as eE}from"./events.js";import{RemediationVerbSchema as _E,REMEDIATION_VERB_GLOSS as TE,DestructionFindingSchema as AE,DestructionTicketResourceSchema as tE,DestructionTicketSchema as rE,DestructionConsentSchema as oE,DestructionOutcomeSchema as aE,DESTRUCTION_FINDINGS as RE,CONSENT_VERDICTS as OE,TICKET_VERDICT_SOURCES as PE,TicketVerdictSourceSchema as NE}from"./destruction.js";import{DRIFT_VERDICTS as DE,DriftVerdictSchema as cE,DriftSuspectSchema as LE,DriftFindingSchema as pE,DriftJournalRecordSchema as CE,verbsForDriftVerdict as nE}from"./drift.js";import{REMEDIATION_PHASES as IE,RemediationPhaseSchema as sE,RemediationTargetSchema as lE,RemediationFlipProofSchema as ME,RemediationJournalRecordSchema as hE,RemediationVerbWithSurgerySchema as VE,remediationPhaseRank as UE,remediationPlaceholderPhysicalId as YE,isRemediationPlaceholderPhysicalId as dE}from"./remediation.js";import{stubCallerIdentity as gE}from"./deployment/index.js";import{ProgressReporter as xE}from"./ProgressEvent.js";import{APPLICATION_STACKS as XE,ORGANISATION_TYPES as yE,APPLICATION_DEPLOY_ORDER as FE,APPLICATION_DESTROY_ORDER as KE,OPENNEXT_DEPLOY_ORDER as kE,OPENNEXT_DESTROY_ORDER as HE,PARALLEL_DEPLOY_GROUPS as bE,PARALLEL_DESTROY_GROUPS as vE,OPENNEXT_PARALLEL_GROUPS as BE,isApplicationOperation as JE,isOrganisationOperation as wE,getParallelDeployGroups as QE,getParallelDestroyGroups as WE,getApplicationDeployOrder as jE,getApplicationDestroyOrder as qE,getApplicationStackName as zE,getOrganisationStackName as ZE,isApplicationStack as $E,getApplicationStepName as Ee,getApplicationStepId as ee,toPascalCase as Se}from"./operations.js";import{PARALLEL_OPERATION_TYPES as Te}from"./deployment/index.js";import{isOpenNextPattern as te,OPENNEXT_PATTERNS as re}from"./detection/patternTypes.js";import{STACK_NOT_FOUND_PATTERN as ae,STACK_FAILED_STATE_PATTERN as Re,CDK_NO_STACKS_MATCH as Oe,INFRASTRUCTURE_FILENAME as Pe}from"./constants.js";import{ApplicationError as ie,wrapApplicationError as De}from"./application/index.js";import{STEP_IDS as Le,STEP_NAMES as pe,INFRASTRUCTURE_STEP_NAMES as Ce,INFRA_STEP_NAME as ne}from"./stepDefinitions.js";export{Q as ALL_PROGRESS_KINDS,FE as APPLICATION_DEPLOY_ORDER,KE as APPLICATION_DESTROY_ORDER,XE as APPLICATION_STACKS,w as APPROVAL_DECISIONS,J as APPROVAL_KINDS,ie as ApplicationError,H as BUILDERS,y as CASCADE_ACCOUNT_PHASES,a as CASCADE_ACCOUNT_STATUSES,b as CASCADE_OUTCOME_RESULTS,o as CASCADE_PHASES,Oe as CDK_NO_STACKS_MATCH,OE as CONSENT_VERDICTS,n as ChangeCountsSchema,t as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,T as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,A as DEPLOYMENT_EVENT_STATUS_REASON_MAX,r as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,_ as DEPLOYMENT_EVENT_TYPES,g as DEPLOY_EVENT_ARN_MAX,m as DEPLOY_EVENT_CONTRACT,I as DEPLOY_EVENT_CONTRACT_MAJOR,s as DEPLOY_EVENT_CONTRACT_MINOR,Y as DEPLOY_EVENT_ERROR_MESSAGE_MAX,M as DEPLOY_EVENT_ID_MAX,V as DEPLOY_EVENT_MESSAGE_MAX,h as DEPLOY_EVENT_NAME_MAX,f as DEPLOY_EVENT_OUTPUT_MAX,U as DEPLOY_EVENT_STATUS_REASON_MAX,d as DEPLOY_EVENT_TRAIL_DETAIL_MAX,u as DEPLOY_EVENT_URL_MAX,F as DEPLOY_RESULTS,RE as DESTRUCTION_FINDINGS,K as DETECTION_PHASES,DE as DRIFT_VERDICTS,D as DeployEventSchema,L as DeployResourceSchema,S as DeploymentEventSchema,oE as DestructionConsentSchema,AE as DestructionFindingSchema,aE as DestructionOutcomeSchema,tE as DestructionTicketResourceSchema,rE as DestructionTicketSchema,pE as DriftFindingSchema,CE as DriftJournalRecordSchema,LE as DriftSuspectSchema,cE as DriftVerdictSchema,Pe as INFRASTRUCTURE_FILENAME,Ce as INFRASTRUCTURE_STEP_NAMES,ne as INFRA_STEP_NAME,G as LOG_LEVELS,kE as OPENNEXT_DEPLOY_ORDER,HE as OPENNEXT_DESTROY_ORDER,BE as OPENNEXT_PARALLEL_GROUPS,re as OPENNEXT_PATTERNS,yE as ORGANISATION_TYPES,bE as PARALLEL_DEPLOY_GROUPS,vE as PARALLEL_DESTROY_GROUPS,Te as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,v as PLAN_ACTIONS,p as PlanChangeSchema,C as PlanPropertyChangeSchema,xE as ProgressReporter,IE as REMEDIATION_PHASES,TE as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,ME as RemediationFlipProofSchema,hE as RemediationJournalRecordSchema,sE as RemediationPhaseSchema,lE as RemediationTargetSchema,_E as RemediationVerbSchema,VE as RemediationVerbWithSurgerySchema,X as STACK_CLEANUP_PHASES,Re as STACK_FAILED_STATE_PATTERN,ae as STACK_NOT_FOUND_PATTERN,x as STEP_COMPLETE_STATUSES,Le as STEP_IDS,pe as STEP_NAMES,l as SUPPORTED_CONTRACT_MARKERS,c as StepProgressSchema,PE as TICKET_VERDICT_SOURCES,EE as TRAIL_MIGRATION_PHASES,eE as TRAIL_MIGRATION_STATUSES,NE as TicketVerdictSourceSchema,j as createDeployEmitter,jE as getApplicationDeployOrder,qE as getApplicationDestroyOrder,zE as getApplicationStackName,ee as getApplicationStepId,Ee as getApplicationStepName,ZE as getOrganisationStackName,QE as getParallelDeployGroups,WE as getParallelDestroyGroups,JE as isApplicationOperation,$E as isApplicationStack,te as isOpenNextPattern,wE as isOrganisationOperation,P as isQuarantineDetail,dE as isRemediationPlaceholderPhysicalId,N as isRetainedBucketsDetail,Z as parseDeployContractVersion,z as parseDeployEvent,UE as remediationPhaseRank,YE as remediationPlaceholderPhysicalId,gE as stubCallerIdentity,R as toCascadePhase,Se as toPascalCase,nE as verbsForDriftVerdict,De as wrapApplicationError};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AppResourceFlags } from "./detection/patternTypes.js";
|
|
2
2
|
import { type StepId } from "./stepDefinitions.js";
|
|
3
3
|
import { toPascalCase } from "@fjall/util";
|
|
4
|
+
import type { PatternType } from "@fjall/generator";
|
|
4
5
|
/**
|
|
5
6
|
* Application infrastructure stacks
|
|
6
7
|
*/
|
|
@@ -157,7 +158,7 @@ export declare function getParallelDestroyGroups(): ReadonlyArray<(typeof PARALL
|
|
|
157
158
|
* Options for determining deployment order
|
|
158
159
|
*/
|
|
159
160
|
export interface DeployOrderOptions {
|
|
160
|
-
pattern?:
|
|
161
|
+
pattern?: PatternType | null;
|
|
161
162
|
resources?: AppResourceFlags;
|
|
162
163
|
}
|
|
163
164
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/deploy-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.30.0",
|
|
4
4
|
"description": "Shared deployment engine for Fjall — used by CLI and webapp worker",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"scripts": {
|
|
49
49
|
"clean": "rm -rf ./dist ./sourcemaps",
|
|
50
50
|
"build": "npm run clean && tsc && node ../scripts/minify-dist.mjs dist",
|
|
51
|
+
"prepack": "node ../scripts/check-dist-freshness.mjs",
|
|
51
52
|
"watch": "npm run build && tsc --watch --preserveWatchOutput",
|
|
52
53
|
"watch:only": "tsc --watch --preserveWatchOutput",
|
|
53
54
|
"typecheck": "tsc --noEmit",
|
|
@@ -83,8 +84,8 @@
|
|
|
83
84
|
"@aws-sdk/client-ssm": "^3.1038.0",
|
|
84
85
|
"@aws-sdk/client-sso-admin": "^3.1038.0",
|
|
85
86
|
"@aws-sdk/client-sts": "^3.1038.0",
|
|
86
|
-
"@fjall/generator": "^2.
|
|
87
|
-
"@fjall/util": "^2.
|
|
87
|
+
"@fjall/generator": "^2.30.0",
|
|
88
|
+
"@fjall/util": "^2.30.0",
|
|
88
89
|
"@smithy/node-http-handler": "^4.6.1",
|
|
89
90
|
"aws-cdk": "^2.1128.1",
|
|
90
91
|
"tsx": "^4.21.0",
|
|
@@ -95,5 +96,5 @@
|
|
|
95
96
|
"typescript": "^6.0.3",
|
|
96
97
|
"vitest": "^4.1.5"
|
|
97
98
|
},
|
|
98
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "ec35b16db566dfa5feb714c16f132c55b4663c86"
|
|
99
100
|
}
|