@fjall/deploy-core 2.30.3 → 2.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.minified +1 -1
- package/dist/src/aws/organisations/oidcProvider.js +1 -1
- package/dist/src/aws/utils/cloudformationEventHelpers.d.ts +2 -2
- package/dist/src/aws/utils/cloudformationEventHelpers.js +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/activeDeploymentGuard.d.ts +1 -1
- package/dist/src/orchestration/activeDeploymentGuard.js +3 -3
- package/dist/src/orchestration/application/applicationDeploy.js +1 -1
- package/dist/src/orchestration/application/applicationDeployHelpers.d.ts +2 -1
- package/dist/src/orchestration/application/applicationDeployHelpers.js +3 -3
- package/dist/src/orchestration/application/applicationDestroy.js +1 -1
- package/dist/src/orchestration/application/artefactCollection.d.ts +3 -2
- package/dist/src/orchestration/application/artefactCollection.js +1 -1
- package/dist/src/orchestration/application/codeOnlyDeploy.d.ts +0 -22
- package/dist/src/orchestration/application/codeOnlyDeploy.js +1 -1
- package/dist/src/orchestration/application/databaseEndpointReconcile.d.ts +2 -2
- package/dist/src/orchestration/application/databaseEndpointReconcile.js +1 -1
- package/dist/src/orchestration/application/destroyPreFlight.d.ts +33 -0
- package/dist/src/orchestration/application/destroyPreFlight.js +1 -0
- package/dist/src/orchestration/application/detectionPipeline.d.ts +1 -1
- package/dist/src/orchestration/application/detectionPipeline.js +1 -1
- package/dist/src/orchestration/application/dockerBuildHelper.js +1 -1
- package/dist/src/orchestration/application/lambdaCodeOnlyRollout.d.ts +42 -10
- package/dist/src/orchestration/application/lambdaCodeOnlyRollout.js +1 -1
- package/dist/src/orchestration/application/plan/computeDeployPlan.d.ts +1 -1
- package/dist/src/orchestration/application/plan/computeDeployPlan.js +1 -1
- package/dist/src/orchestration/application/serviceImageTagsRollback.d.ts +1 -1
- package/dist/src/orchestration/application/serviceImageTagsRollback.js +1 -1
- package/dist/src/orchestration/application/taskDefinitionRoll.d.ts +1 -1
- package/dist/src/orchestration/application/taskDefinitionRoll.js +1 -1
- package/dist/src/orchestration/destroy.js +1 -1
- package/dist/src/orchestration/drift/driftPreFlight.js +3 -3
- package/dist/src/orchestration/index.d.ts +1 -1
- package/dist/src/orchestration/index.js +1 -1
- package/dist/src/orchestration/organisation/cascadeHelpers.js +1 -1
- package/dist/src/orchestration/organisationDeploy/infraSteps.d.ts +1 -1
- package/dist/src/orchestration/organisationDeploy/infraSteps.js +1 -1
- package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.js +4 -4
- package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.js +1 -1
- package/dist/src/orchestration/probes/deleteBlockProbes.d.ts +38 -0
- package/dist/src/orchestration/probes/deleteBlockProbes.js +1 -0
- package/dist/src/orchestration/remediation/recreatePreFlight.js +1 -1
- package/dist/src/orchestration/remediation/recreateResource.js +1 -1
- package/dist/src/orchestration/remediation/removalUpdate.d.ts +74 -13
- package/dist/src/orchestration/remediation/removalUpdate.js +1 -1
- package/dist/src/orchestration/restart/restartApplication.js +1 -1
- package/dist/src/orchestration/restart/secretsDrift.js +1 -1
- package/dist/src/orchestration/stackCleanup/stackResources.d.ts +5 -3
- package/dist/src/services/application/ApplicationStackService.d.ts +2 -1
- package/dist/src/services/application/ApplicationStackService.js +1 -1
- package/dist/src/services/infrastructure/CloudFormationService.d.ts +11 -10
- package/dist/src/services/infrastructure/CloudFormationService.js +1 -1
- package/dist/src/services/infrastructure/EcsService.d.ts +11 -9
- package/dist/src/services/infrastructure/EcsService.js +1 -1
- package/dist/src/services/infrastructure/EcsServiceResolver.d.ts +4 -4
- package/dist/src/services/infrastructure/EcsServiceResolver.js +1 -1
- package/dist/src/services/infrastructure/LambdaService.d.ts +19 -2
- package/dist/src/services/infrastructure/LambdaService.js +1 -1
- package/dist/src/types/application/ApplicationServiceTypes.d.ts +1 -0
- package/dist/src/types/application/ApplicationServiceTypes.js +1 -1
- package/dist/src/types/remediation.d.ts +1 -0
- package/dist/src/types/remediation.js +1 -1
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ECSClient as
|
|
1
|
+
import{ECSClient as $,UpdateServiceCommand as T,DescribeServicesCommand as b,DescribeClustersCommand as F,ListServicesCommand as R,ListClustersCommand as M,RegisterTaskDefinitionCommand as N,DescribeTaskDefinitionCommand as _}from"@aws-sdk/client-ecs";import{success as c,failure as l}from"@fjall/generator";import{BaseServiceError as I}from"../../types/errors/ServiceError.js";import{logger as D}from"@fjall/util/logger";import{getErrorMessage as w,maskSensitiveOutput as p,sleep as U}from"@fjall/util";import{getAwsErrorDetails as x}from"../../aws/utils/awsErrorHandler.js";import{composeSdkAbortSignal as g,isAborted as A}from"../../aws/organisations/types.js";class m extends I{errorType;resourceArn;constructor(n,s,e,t,r=!1){super(`ECS_${s.toUpperCase()}`,n,t,r),this.errorType=s,this.resourceArn=e}}class W{aws;constructor(n){this.aws=n}getClient(){return this.aws.getClient($)}async updateService(n,s,e,t){try{const r=this.getClient(),a=new T({cluster:n,service:s,forceNewDeployment:e?.forceNewDeployment!==!1,desiredCount:e?.desiredCount,taskDefinition:e?.taskDefinition});return D.debug("EcsService",`UpdateService request: cluster=${n}, service=${s}, forceNewDeployment=${e?.forceNewDeployment!==!1}, taskDefinition=${e?.taskDefinition??"<unchanged>"}`),await r.send(a,{abortSignal:g(t)}),c(void 0)}catch(r){const{message:a,name:o,httpCode:i}=x(r),d=p(a);D.error("EcsService",`UpdateService failed: ${o} - ${d}`,{clusterArn:n,serviceArn:s,httpCode:i,error:r});let f=`Failed to update ECS service: ${d}`;return i&&(f+=` (HTTP ${i})`),o!=="Error"&&o!=="Unknown"&&(f+=` [${o}]`),l(new m(f,"unknown",s,{clusterArn:n,error:r,httpCode:i,errorName:o},!1))}}async describeServices(n,s,e){try{const t=this.getClient(),r=new b({cluster:n,services:s,include:["TAGS"]}),a=await t.send(r,{abortSignal:g(e)});if(!a.services)return c([]);const o=a.services.map(i=>({serviceArn:i.serviceArn,serviceName:i.serviceName,clusterArn:i.clusterArn,status:i.status,desiredCount:i.desiredCount,runningCount:i.runningCount,pendingCount:i.pendingCount,deployments:i.deployments,events:i.events,taskDefinition:i.taskDefinition}));return c(o)}catch(t){const r=p(w(t));return l(new m(`Failed to describe services: ${r}`,"unknown",void 0,{clusterArn:n,serviceArns:s,error:t},!1))}}async getDeploymentStatus(n,s,e){const t=await this.describeServices(n,[s],e);if(!t.success)return l(t.error);const r=t.data;if(r.length===0)return l(new m(`Service ${s} not found in cluster ${n}`,"service_not_found",s,{clusterArn:n}));const a=r[0],o=a.deployments||[],i=o.find(C=>C.status==="PRIMARY");if(!i)return c({deploymentCompleted:!1,deploymentFailed:!0,runningCount:0,desiredCount:0,pendingCount:0,deploymentCount:o.length,message:"No primary deployment found",percentComplete:0});const d=i.desiredCount||0,f=i.runningCount||0,y=i.pendingCount||0,v=d>0?Math.round(f/d*100):0,h=o.length===1&&f===d&&y===0,k=(i.failedTasks??0)>0||i.rolloutState==="FAILED";let u=`Running: ${f}/${d}`;if(u+=`, Pending: ${y}`,o.length>1&&(u+=` (${o.length} deployments active)`),k){const C=i.rolloutStateReason||(i.failedTasks?`${i.failedTasks} task(s) failed to start`:void 0);C&&(u+=` \u2014 ${C}`)}const S=a.events&&a.events.length>0?a.events[0]?.message:void 0;return c({deploymentCompleted:h,deploymentFailed:k,runningCount:f,desiredCount:d,pendingCount:y,deploymentCount:o.length,message:u,percentComplete:v,latestEvent:S})}async isDeploying(n,s){const e=await this.getDeploymentStatus(n,s);if(!e.success)return D.debug("EcsService","Could not determine deployment status, assuming not deploying",{error:e.error.message}),c(!1);const t=e.data;return c(!t.deploymentCompleted&&!t.deploymentFailed)}async getServiceEvents(n,s,e){try{const t=this.getClient(),r=new b({cluster:n,services:[s],include:["TAGS"]}),a=await t.send(r,{abortSignal:g(e)});if(!a.services||a.services.length===0)return c([]);const i=(a.services[0].events||[]).map(d=>({message:d.message||"",timestamp:d.createdAt||new Date}));return c(i)}catch(t){const r=p(w(t));return l(new m(`Failed to get service events: ${r}`,"unknown",s,{clusterArn:n,error:t}))}}async pollDeployment(n){const{clusterArn:s,serviceArn:e,waitForCompletion:t=!0,maxWaitTime:r=6e5,pollInterval:a=5e3,progressCallback:o,abortSignal:i}=n;if(!t)return c(void 0);const d=Date.now(),f=new Date(d-5e3);let y=null,v="";const h=new Set;for(;Date.now()-d<r;){if(A(i))return l(new m("Deployment polling cancelled by abort signal","unknown",e,{clusterArn:s}));const k=await this.getDeploymentStatus(s,e,i);if(!k.success)return l(k.error);const u=k.data,S=await this.getServiceEvents(s,e,i);if(S.success){const C=this.processDeploymentEvents(S.data,u,f,y,h,o);y=C.lastEventTimestamp,C.eventsReported?v=u.message:u.message!==v&&(o?.(u),v=u.message)}if(u.deploymentCompleted)return c(void 0);if(u.deploymentFailed)return l(new m("ECS deployment failed. Check the ECS console for detailed error information","deployment_failed",e,{clusterArn:s,status:u}));await U(a)}return l(new m(`ECS deployment timed out after ${r/1e3} seconds. The deployment is still in progress. Check the ECS console for status`,"deployment_timeout",e,{clusterArn:s,maxWaitTime:r}))}processDeploymentEvents(n,s,e,t,r,a){const o=n.filter(i=>!(i.timestamp<e||t&&i.timestamp<=t||r.has(i.message)));if(o.length===0)return{lastEventTimestamp:t,eventsReported:!1};for(const i of o)r.add(i.message),a?.({...s,latestEvent:i.message});return{lastEventTimestamp:o[o.length-1].timestamp,eventsReported:!0}}async listClusters(n){try{const s=this.getClient(),e=new M({}),t=await s.send(e,{abortSignal:g(n)});return c(t.clusterArns||[])}catch(s){const e=p(w(s));return l(new m(`Failed to list clusters: ${e}`,"permission_denied",void 0,s))}}async describeClusters(n,s){try{const e=this.getClient(),t=new F({clusters:n}),r=await e.send(t,{abortSignal:g(s)});if(!r.clusters)return c([]);const a=r.clusters.map(o=>({clusterArn:o.clusterArn,clusterName:o.clusterName,status:o.status,registeredContainerInstancesCount:o.registeredContainerInstancesCount,runningTasksCount:o.runningTasksCount,pendingTasksCount:o.pendingTasksCount}));return c(a)}catch(e){const t=p(w(e));return l(new m(`Failed to describe clusters: ${t}`,"unknown",void 0,{clusterArns:n,error:e},!1))}}async listServices(n,s){try{const e=this.getClient(),t=new R({cluster:n}),r=await e.send(t,{abortSignal:g(s)});return c(r.serviceArns||[])}catch(e){const t=p(w(e));return l(new m(`Failed to list services: ${t}`,"unknown",n,{clusterArn:n,error:e},!1))}}async registerTaskDefinition(n,s){try{const e=this.getClient(),t=new N(n),r=await e.send(t,{abortSignal:g(s)});return r.taskDefinition?.taskDefinitionArn?c(r.taskDefinition.taskDefinitionArn):l(new m("Task definition registration failed - no ARN returned","task_definition_failed",void 0,n))}catch(e){const t=p(w(e));return l(new m(`Failed to register task definition: ${t}`,"task_definition_failed",void 0,{taskDefinition:n,error:e},!1))}}async getLatestTaskDefinition(n,s){try{const e=this.getClient(),t=new _({taskDefinition:n}),r=await e.send(t,{abortSignal:g(s)});return c(r.taskDefinition)}catch(e){const t=p(w(e));return l(new m(`Failed to get task definition: ${t}`,"unknown",void 0,{family:n,error:e},!1))}}async deployService(n,s,e){const t=await this.updateService(n,s,{forceNewDeployment:!0,taskDefinition:e?.taskDefinition},e?.abortSignal);if(!t.success)return l(t.error);if(e?.waitForCompletion!==!1){const r=await this.pollDeployment({clusterArn:n,serviceArn:s,waitForCompletion:!0,progressCallback:e?.progressCallback,abortSignal:e?.abortSignal});if(!r.success)return l(r.error)}return c(void 0)}}export{m as EcsError,W as EcsService};
|
|
@@ -7,10 +7,10 @@ import type { EcsError } from "./EcsService.js";
|
|
|
7
7
|
* cast across the package boundary.
|
|
8
8
|
*/
|
|
9
9
|
export interface CfnExportsClient {
|
|
10
|
-
getExportsByNames(names: string[]): Promise<Result<Map<string, string>, {
|
|
10
|
+
getExportsByNames(names: string[], abortSignal?: AbortSignal): Promise<Result<Map<string, string>, {
|
|
11
11
|
message: string;
|
|
12
12
|
}>>;
|
|
13
|
-
listExports(): Promise<Result<Array<{
|
|
13
|
+
listExports(callbacks?: undefined, abortSignal?: AbortSignal): Promise<Result<Array<{
|
|
14
14
|
Name: string;
|
|
15
15
|
Value: string;
|
|
16
16
|
}>, {
|
|
@@ -57,7 +57,7 @@ export declare class EcsServiceResolver {
|
|
|
57
57
|
name: string;
|
|
58
58
|
}>;
|
|
59
59
|
}>;
|
|
60
|
-
}): Promise<Result<{
|
|
60
|
+
}, abortSignal?: AbortSignal): Promise<Result<{
|
|
61
61
|
clusterArn?: string;
|
|
62
62
|
serviceArns: string[];
|
|
63
63
|
}, EcsError>>;
|
|
@@ -71,7 +71,7 @@ export declare class EcsServiceResolver {
|
|
|
71
71
|
* Service: `${clusterName}${serviceName}DeployableService`
|
|
72
72
|
* where clusterName typically contains the app name (e.g. "StandardsapiCompute").
|
|
73
73
|
*/
|
|
74
|
-
getDeployableClusterAndServices(appName: string): Promise<Result<{
|
|
74
|
+
getDeployableClusterAndServices(appName: string, abortSignal?: AbortSignal): Promise<Result<{
|
|
75
75
|
clusterArn?: string;
|
|
76
76
|
serviceArns: string[];
|
|
77
77
|
}, EcsError>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{success as l}from"@fjall/generator";import{logger as
|
|
1
|
+
import{success as l}from"@fjall/generator";import{logger as u}from"@fjall/util/logger";import{getErrorMessage as p,maskSensitiveOutput as g}from"@fjall/util";import{extractEcsServiceParts as b,buildArn as y}from"../../aws/utils/arnParser.js";function m(d,o){const a=d.toLowerCase(),r=o.toLowerCase();if(r.length===0)return!1;const i=e=>!/[a-zA-Z0-9]/.test(e),n=e=>/[A-Z]/.test(e);let s=a.indexOf(r);for(;s!==-1;){const e=d[s]??"",t=s>0?d[s-1]??"":"",c=s===0||n(e)||i(t),f=s+r.length,v=d[f],h=v===void 0||n(v)||i(v);if(c&&h)return!0;s=a.indexOf(r,s+1)}return!1}class C{cfService;constructor(o){this.cfService=o}async getDeployableClusterAndServicesByManifest(o,a){try{const r=[];for(const t of o.clusters){r.push(`${t.name}DeployableCluster`);for(const c of t.services)r.push(`${t.name}${c.name}DeployableService`)}if(r.length===0)return l({serviceArns:[]});const i=await this.cfService.getExportsByNames(r,a);if(!i.success)return u.debug("EcsServiceResolver","Failed to get CloudFormation exports by name",{error:i.error.message}),l({serviceArns:[]});const n=i.data;let s;for(const t of o.clusters){const c=n.get(`${t.name}DeployableCluster`);if(c){s=c;break}}const e=[];for(const t of o.clusters)for(const c of t.services){const f=n.get(`${t.name}${c.name}DeployableService`);f&&e.push(f)}return u.debug("EcsServiceResolver",`Manifest-based discovery: found ${e.length} service(s), cluster=${s||"not found"}`),l({clusterArn:s,serviceArns:e})}catch(r){return u.warn("EcsServiceResolver","Manifest-based discovery failed",{error:g(p(r))}),l({serviceArns:[]})}}async getDeployableClusterAndServices(o,a){try{const r=await this.cfService.listExports(void 0,a);if(!r.success)return u.debug("EcsServiceResolver","Failed to list CloudFormation exports",{error:r.error.message}),l({serviceArns:[]});const n=r.data.filter(e=>{const t=e.Name??"";return m(t,o)&&t.toLowerCase().endsWith("deployableservice")}).map(e=>e.Value).filter(e=>e!==void 0);let s;if(n.length>0){const e=b(n[0]);e&&(s=y("ecs",e.region,e.accountId,`cluster/${e.clusterName}`))}return s||(s=r.data.find(t=>{const c=t.Name??"";return m(c,o)&&c.toLowerCase().endsWith("deployablecluster")})?.Value),u.debug("EcsServiceResolver",`Found ${n.length} deployable service(s) for app "${o}" in cluster ${s||"unknown"}`),l({clusterArn:s,serviceArns:n})}catch(r){return u.warn("EcsServiceResolver","Failed to get deployable services",{error:g(p(r))}),l({serviceArns:[]})}}}export{C as EcsServiceResolver,m as matchesAppNameToken};
|
|
@@ -13,6 +13,12 @@ export interface PublishedLambdaVersion {
|
|
|
13
13
|
export interface UpdatedLambdaFunctionCode {
|
|
14
14
|
functionArn: string;
|
|
15
15
|
version: string;
|
|
16
|
+
/**
|
|
17
|
+
* Set when the update was accepted but its completion could NOT be
|
|
18
|
+
* verified (the deploy role lacks `lambda:GetFunctionConfiguration`).
|
|
19
|
+
* Absent means the update was polled to `LastUpdateStatus: Successful`.
|
|
20
|
+
*/
|
|
21
|
+
unverifiedReason?: string;
|
|
16
22
|
}
|
|
17
23
|
/**
|
|
18
24
|
* Lambda service using the AwsProvider interface. Constructor-injected
|
|
@@ -31,7 +37,7 @@ export declare class LambdaService {
|
|
|
31
37
|
* shape, not the parameter's deploy-time resolved value, so the hash
|
|
32
38
|
* doesn't change between deploys even though the underlying image does).
|
|
33
39
|
*/
|
|
34
|
-
publishVersion(functionName: string): Promise<Result<PublishedLambdaVersion, LambdaError>>;
|
|
40
|
+
publishVersion(functionName: string, abortSignal?: AbortSignal): Promise<Result<PublishedLambdaVersion, LambdaError>>;
|
|
35
41
|
/**
|
|
36
42
|
* Update a container-image Lambda function's code directly — the Lambda
|
|
37
43
|
* equivalent of ECS's `UpdateService`/`RegisterTaskDefinition` for a
|
|
@@ -41,5 +47,16 @@ export declare class LambdaService {
|
|
|
41
47
|
* performs the code update and `publishVersion` has to run as a separate
|
|
42
48
|
* step afterward.
|
|
43
49
|
*/
|
|
44
|
-
updateFunctionCode(functionName: string, imageUri: string): Promise<Result<UpdatedLambdaFunctionCode, LambdaError>>;
|
|
50
|
+
updateFunctionCode(functionName: string, imageUri: string, abortSignal?: AbortSignal): Promise<Result<UpdatedLambdaFunctionCode, LambdaError>>;
|
|
51
|
+
/**
|
|
52
|
+
* UpdateFunctionCode is accepted asynchronously: the API returns 200 with
|
|
53
|
+
* `LastUpdateStatus: InProgress`, and a container-image update can still
|
|
54
|
+
* fail afterwards (image optimisation — ImageAccessDenied, InvalidImage,
|
|
55
|
+
* ImageDeleted), leaving the function on its previous code. Poll the
|
|
56
|
+
* configuration until the update lands, mirroring the ECS rollout's
|
|
57
|
+
* `pollDeployment` semantics (same 600s budget). A role missing
|
|
58
|
+
* `lambda:GetFunctionConfiguration` degrades to accepted-but-unverified
|
|
59
|
+
* rather than failing a rollout that almost certainly succeeded.
|
|
60
|
+
*/
|
|
61
|
+
private waitForUpdateCompletion;
|
|
45
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LambdaClient as
|
|
1
|
+
import{GetFunctionConfigurationCommand as v,LambdaClient as _,PublishVersionCommand as C,UpdateFunctionCodeCommand as $}from"@aws-sdk/client-lambda";import{success as p,failure as a}from"@fjall/generator";import{BaseServiceError as g}from"../../types/errors/ServiceError.js";import{logger as f}from"@fjall/util/logger";import{maskSensitiveOutput as m}from"@fjall/util";import{getAwsErrorDetails as b}from"../../aws/utils/awsErrorHandler.js";import{composeSdkAbortSignal as w,isAborted as A,isAccessDenied as L}from"../../aws/organisations/types.js";const h=6e5,F=5e3;function P(l,e){return e===void 0?new Promise(r=>setTimeout(r,l)):e.aborted?Promise.resolve():new Promise(r=>{const o=setTimeout(()=>{e.removeEventListener("abort",t),r()},l),t=()=>{clearTimeout(o),r()};e.addEventListener("abort",t,{once:!0})})}class d extends g{functionName;operation;constructor(e,r,o,t){super(`LAMBDA_${o.toUpperCase()}_FAILED`,e,t,!1),this.functionName=r,this.operation=o}}class R{aws;constructor(e){this.aws=e}getClient(){return this.aws.getClient(_)}async publishVersion(e,r){try{const t=await this.getClient().send(new C({FunctionName:e}),{abortSignal:w(r)});return!t.FunctionArn||!t.Version?a(new d("PublishVersion returned no function ARN or version",e,"publish_version",t)):(f.debug("LambdaService",`Published version ${t.Version} for ${e}`),p({functionArn:t.FunctionArn,version:t.Version}))}catch(o){const{message:t,name:s,httpCode:n}=b(o),i=m(t);f.error("LambdaService",`PublishVersion failed for ${e}: ${s} - ${i}`,{functionName:e,httpCode:n,error:o});let u=`Failed to publish Lambda version for '${e}': ${i}`;return n&&(u+=` (HTTP ${n})`),a(new d(u,e,"publish_version",{error:o,httpCode:n,errorName:s}))}}async updateFunctionCode(e,r,o){try{const t=this.getClient(),s=await t.send(new $({FunctionName:e,ImageUri:r,Publish:!0}),{abortSignal:w(o)});if(!s.FunctionArn||!s.Version)return a(new d("UpdateFunctionCode returned no function ARN or version",e,"update_function_code",s));const n=await this.waitForUpdateCompletion(t,e,o);return n.success?(f.debug("LambdaService",`Updated ${e} to ${r}, published version ${s.Version}`),p({functionArn:s.FunctionArn,version:s.Version,...n.data.unverifiedReason!==void 0?{unverifiedReason:n.data.unverifiedReason}:{}})):a(n.error)}catch(t){const{message:s,name:n,httpCode:i}=b(t),u=m(s);f.error("LambdaService",`UpdateFunctionCode failed for ${e}: ${n} - ${u}`,{functionName:e,imageUri:r,httpCode:i,error:t});let c=`Failed to update Lambda function code for '${e}': ${u}`;return i&&(c+=` (HTTP ${i})`),a(new d(c,e,"update_function_code",{error:t,httpCode:i,errorName:n}))}}async waitForUpdateCompletion(e,r,o){const t=Date.now();for(;Date.now()-t<h;){if(A(o))return a(new d(`Cancelled while waiting for the code update of '${r}' to complete \u2014 the update was accepted and may still land`,r,"update_function_code"));let s,n;try{const i=await e.send(new v({FunctionName:r}),{abortSignal:w(o)});s=i.LastUpdateStatus,n=i.LastUpdateStatusReason}catch(i){const{message:u,name:c}=b(i);return L(c)?p({unverifiedReason:"lambda:GetFunctionConfiguration is denied for this role, so completion of the update could not be verified"}):a(new d(`Failed to verify the code update of '${r}' completed: ${m(u)}`,r,"update_function_code",{errorName:c}))}if(s==="Successful")return p({});if(s==="Failed")return a(new d(`Code update of '${r}' was accepted but failed to apply: ${m(n??"no reason reported")}. The function is still running its previous code.`,r,"update_function_code",{statusReason:n}));await P(F,o)}return a(new d(`Code update of '${r}' did not complete within ${h/1e3}s \u2014 it may still be in progress. Check the Lambda console before retrying.`,r,"update_function_code"))}}export{d as LambdaError,R as LambdaService};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BaseServiceError as
|
|
1
|
+
import{BaseServiceError as c}from"../errors/ServiceError.js";import{getErrorMessage as o,maskSensitiveOutput as i}from"@fjall/util";function T(t,a,e,p,r){const s=i(o(r));return new m(`${t}: ${s}`,{errorType:a,appName:e,operation:p,details:r,...r instanceof Error&&{cause:r}})}class m extends c{errorType;appName;operation;stackType;constructor(a,e){super(`APPLICATION_${e.errorType.toUpperCase()}`,a,e.details,e.recoverable??!1,e.cause),this.errorType=e.errorType,this.appName=e.appName,this.operation=e.operation,this.stackType=e.stackType}}export{m as ApplicationError,T as wrapApplicationError};
|
|
@@ -119,6 +119,7 @@ export declare const RemediationJournalRecordSchema: z.ZodObject<{
|
|
|
119
119
|
Snapshot: "Snapshot";
|
|
120
120
|
Delete: "Delete";
|
|
121
121
|
}>>>;
|
|
122
|
+
coRemovedLogicalIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
122
123
|
orphanedResources: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
123
124
|
unverifiedRemovals: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
124
125
|
completedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as e}from"zod";const t=["captured","flip-verified","flip-applied","removal-applied","done"],
|
|
1
|
+
import{z as e}from"zod";const t=["captured","flip-verified","flip-applied","removal-applied","done"],o=e.enum(t);function m(i){return t.indexOf(i)}const r=e.object({logicalId:e.string().min(1),resourceType:e.string().min(1),physicalId:e.string().min(1)}).strict();function a(i,n){return`${i}/${n}`}function p(i,n){return i.physicalId===a(n,i.logicalId)}const s=e.object({diffGuardPassed:e.boolean(),changeSetMetadataOnly:e.boolean(),noChanges:e.boolean(),provenAt:e.string().min(1)}).strict(),l=e.enum(["forget","recreate"]),d=e.object({version:e.literal(1),opId:e.string().min(1),verb:l,accountId:e.string().min(1),region:e.string().min(1),stackName:e.string().min(1),appName:e.string().min(1).optional(),targets:e.array(r).min(1),phase:o,createdAt:e.string().min(1),updatedAt:e.string().min(1),liveTemplateDigest:e.string().min(1).optional(),forensicsPath:e.string().min(1).optional(),proof:s.optional(),consentedPhysicalNames:e.array(e.string()).optional(),retainedByRedeclaration:e.array(e.string().min(1)).optional(),fliplessTargets:e.array(e.string().min(1)).optional(),fliplessByNecessity:e.array(e.string().min(1)).optional(),recreatedResources:e.array(e.string().min(1)).optional(),snapshotPolicies:e.record(e.string().min(1),e.enum(["Snapshot","Delete"])).optional(),coRemovedLogicalIds:e.array(e.string().min(1)).optional(),orphanedResources:e.array(e.string().min(1)).optional(),unverifiedRemovals:e.array(e.string().min(1)).optional(),completedAt:e.string().min(1).optional()}).strict();export{t as REMEDIATION_PHASES,s as RemediationFlipProofSchema,d as RemediationJournalRecordSchema,o as RemediationPhaseSchema,r as RemediationTargetSchema,l as RemediationVerbWithSurgerySchema,p as isRemediationPlaceholderPhysicalId,m as remediationPhaseRank,a as remediationPlaceholderPhysicalId};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/deploy-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.31.1",
|
|
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",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"@aws-sdk/client-cloudformation": "^3.1038.0",
|
|
71
71
|
"@aws-sdk/client-cloudtrail": "^3.1065.0",
|
|
72
72
|
"@aws-sdk/client-cost-explorer": "^3.1038.0",
|
|
73
|
+
"@aws-sdk/client-dynamodb": "^3.1038.0",
|
|
73
74
|
"@aws-sdk/client-ec2": "^3.1038.0",
|
|
74
75
|
"@aws-sdk/client-ecr": "^3.1039.0",
|
|
75
76
|
"@aws-sdk/client-iam": "^3.1038.0",
|
|
@@ -85,8 +86,8 @@
|
|
|
85
86
|
"@aws-sdk/client-ssm": "^3.1038.0",
|
|
86
87
|
"@aws-sdk/client-sso-admin": "^3.1038.0",
|
|
87
88
|
"@aws-sdk/client-sts": "^3.1038.0",
|
|
88
|
-
"@fjall/generator": "^2.
|
|
89
|
-
"@fjall/util": "^2.
|
|
89
|
+
"@fjall/generator": "^2.31.1",
|
|
90
|
+
"@fjall/util": "^2.31.1",
|
|
90
91
|
"@smithy/node-http-handler": "^4.6.1",
|
|
91
92
|
"aws-cdk": "^2.1128.1",
|
|
92
93
|
"tsx": "^4.21.0",
|
|
@@ -97,5 +98,5 @@
|
|
|
97
98
|
"typescript": "^6.0.3",
|
|
98
99
|
"vitest": "^4.1.5"
|
|
99
100
|
},
|
|
100
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "a48cfaf6e050ce1736837802dfcaf517ba39f199"
|
|
101
102
|
}
|