如何在CDK中当源文件变更时强制触发BucketDeployment部署?
解决S3 BucketDeployment源文件变更不触发部署的问题
方法1:利用源对象ETag触发更新
CDK的BucketDeployment默认不会主动跟踪S3源对象的内容变化,我们可以通过获取源文件的ETag(文件哈希标识),将其作为部署资源的元数据,让CDK在合成模板时检测到变化,从而触发重新部署。
代码示例:
import boto3 from aws_cdk import aws_s3_deployment as s3_deploy # 假设src_bucket和dest_bucket已提前定义 s3_client = boto3.client('s3') # 获取dist.zip的ETag,去除返回结果自带的引号 src_obj_info = s3_client.head_object(Bucket=src_bucket.bucket_name, Key="dist.zip") source_etag = src_obj_info['ETag'].strip('"') # 创建BucketDeployment deployment = s3_deploy.BucketDeployment( self, "UploadFrontendFromMainBucket", sources=[ s3_deploy.Source.bucket( src_bucket, zip_object_key="dist.zip", ) ], destination_bucket=dest_bucket, destination_key_prefix="/", extract=True, retain_on_delete=self._deployto != "tst", prune=False, ) # 添加ETag作为元数据,让CDK感知源文件变化 deployment.node.add_metadata("source-dist-zip-etag", source_etag) deployment.node.add_dependency(api, dest_bucket)
当源dist.zip更新时,ETag会随之改变,CDK合成模板时会检测到元数据的差异,自动触发重新部署。
方法2:启用源桶版本控制并使用版本ID
如果源存储桶开启了版本控制,可以获取dist.zip的最新版本ID,将其传入Source.bucket的object_version参数。每次文件更新都会生成新的版本ID,CDK会自动识别并触发部署。
代码示例:
import boto3 from aws_cdk import aws_s3_deployment as s3_deploy # 假设源桶已开启版本控制 s3_client = boto3.client('s3') src_obj_info = s3_client.head_object(Bucket=src_bucket.bucket_name, Key="dist.zip") latest_version_id = src_obj_info['VersionId'] deployment = s3_deploy.BucketDeployment( self, "UploadFrontendFromMainBucket", sources=[ s3_deploy.Source.bucket( src_bucket, zip_object_key="dist.zip", object_version=latest_version_id # 指定最新版本ID ) ], destination_bucket=dest_bucket, destination_key_prefix="/", extract=True, retain_on_delete=self._deployto != "tst", prune=False, ) deployment.node.add_dependency(api, dest_bucket)
方法3:用自定义资源动态检测变化
如果不想在CDK合成阶段提前获取ETag(比如担心权限或需要动态检测),可以通过自定义资源(CustomResource)在部署阶段检查源文件ETag,让BucketDeployment依赖该资源。当ETag变化时,自定义资源更新,触发部署重新运行。
核心逻辑:
- 编写一个Lambda函数,负责调用S3 API获取
dist.zip的ETag - 创建CDK自定义资源,关联该Lambda函数
- 让
BucketDeployment依赖这个自定义资源
代码示例(简化版):
from aws_cdk import custom_resources as cr # 创建自定义资源的Lambda提供者(需提前定义Lambda函数实现ETag获取逻辑) etag_provider = cr.Provider( self, "SourceETagProvider", on_event_handler=get_etag_lambda # get_etag_lambda是已定义的Lambda函数 ) # 创建自定义资源获取ETag source_etag_resource = cr.CustomResource( self, "SourceDistZipETag", service_token=etag_provider.service_token, properties={ "BucketName": src_bucket.bucket_name, "Key": "dist.zip" } ) # 让部署任务依赖自定义资源 deployment.node.add_dependency(source_etag_resource)
内容的提问来源于stack exchange,提问作者Guillaume
相关产品推荐
相关产品推荐

