Claude Code × AWS CodePipeline入门:stage、artifact、审批与安全部署
用Claude Code设计AWS CodePipeline:stage/action/artifact、CodeBuild、审批、S3、Lambda和失败排查。
“GitHub Actions不就够了,为什么要用AWS CodePipeline?“——这是我经常被问到的问题。
答案在于与AWS资源的深度集成。推送到ECR、部署到ECS、更新CloudFormation栈——当这些都需要在AWS内部原生完成时,CodePipeline + CodeBuild的组合是最无缝的选择。
我在工作中管理着结合多个AWS服务的流水线,自从只需向Claude Code描述流水线需求,它就能一次性生成buildspec.yml、CDK代码和IAM策略之后,构建新流水线的时间缩短为原来的四分之一。
CodePipeline / CodeBuild 基本结构
CodePipeline(编排器)
│
├─ Source阶段: 从GitHub / CodeCommit获取代码
├─ Build阶段: 使用CodeBuild进行构建、测试、创建Docker镜像
├─ Test阶段: 集成测试、安全扫描(可选)
└─ Deploy阶段: 部署到ECS / Elastic Beanstalk / S3
CodeBuild执行buildspec.yml中描述的命令。可以把它理解为GitHub Actions中steps:的对应物。
第1步:自动生成buildspec.yml
claude -p "
按以下条件生成CodeBuild的buildspec.yml。
【构建内容】
- Node.js 20环境
- 使用npm ci安装
- TypeScript构建(npm run build)
- 运行单元测试(npm test)
- 构建Docker镜像并推送到ECR
- 镜像标签:CODEBUILD_RESOLVED_SOURCE_VERSION(Git SHA)
- 同时添加latest标签
【安全扫描】
- ECR镜像推送后用Trivy进行扫描
- 发现HIGH/CRITICAL漏洞则构建失败
【制品】
- 输出imagedefinitions.json(用于ECS部署)
"
生成的buildspec.yml:
version: 0.2
env:
variables:
AWS_DEFAULT_REGION: ap-northeast-1
ECR_REPO_NAME: myapp
parameter-store:
ECR_REGISTRY: /myapp/ecr-registry
phases:
install:
runtime-versions:
nodejs: 20
commands:
- echo "安装依赖..."
- npm ci
pre_build:
commands:
- echo "运行测试..."
- npm test
- echo "登录Amazon ECR..."
- aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY
- IMAGE_TAG=$CODEBUILD_RESOLVED_SOURCE_VERSION
- IMAGE_URI=$ECR_REGISTRY/$ECR_REPO_NAME:$IMAGE_TAG
build:
commands:
- echo "构建TypeScript..."
- npm run build
- echo "构建Docker镜像..."
- docker build -t $IMAGE_URI -t $ECR_REGISTRY/$ECR_REPO_NAME:latest .
post_build:
commands:
- echo "推送镜像到ECR..."
- docker push $IMAGE_URI
- docker push $ECR_REGISTRY/$ECR_REPO_NAME:latest
- echo "扫描镜像漏洞..."
- |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest image \
--exit-code 1 \
--severity HIGH,CRITICAL \
$IMAGE_URI
- echo "创建imagedefinitions.json..."
- printf '[{"name":"app","imageUri":"%s"}]' $IMAGE_URI > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
reports:
test-reports:
files:
- "coverage/junit.xml"
file-format: JUNITXML
第2步:用CDK构建完整流水线
claude -p "
在lib/pipeline-stack.ts中用CDK TypeScript实现以下CodePipeline。
【流水线配置】
- Source:GitHub(owner/repo的main分支)
- Build:CodeBuild(使用上面的buildspec.yml)
- Deploy:ECS服务的蓝绿部署
【通知】
- 流水线失败时通过SNS → Slack通知
- 部署成功时也通知Slack
【制品存储】
- S3存储桶(启用加密和版本控制)
"
// lib/pipeline-stack.ts
import * as cdk from "aws-cdk-lib";
import * as codepipeline from "aws-cdk-lib/aws-codepipeline";
import * as codepipeline_actions from "aws-cdk-lib/aws-codepipeline-actions";
import * as codebuild from "aws-cdk-lib/aws-codebuild";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as iam from "aws-cdk-lib/aws-iam";
import * as sns from "aws-cdk-lib/aws-sns";
import * as ecs from "aws-cdk-lib/aws-ecs";
export class PipelineStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 制品存储S3存储桶
const artifactBucket = new s3.Bucket(this, "ArtifactBucket", {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
// 制品定义
const sourceOutput = new codepipeline.Artifact("SourceOutput");
const buildOutput = new codepipeline.Artifact("BuildOutput");
// CodeBuild项目
const buildProject = new codebuild.PipelineProject(this, "BuildProject", {
buildSpec: codebuild.BuildSpec.fromSourceFilename("buildspec.yml"),
environment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
privileged: true, // Docker构建所必需
},
environmentVariables: {
AWS_ACCOUNT_ID: { value: this.account },
},
});
// 授予ECR访问权限
buildProject.addToRolePolicy(new iam.PolicyStatement({
actions: [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
],
resources: ["*"],
}));
// 流水线
const pipeline = new codepipeline.Pipeline(this, "Pipeline", {
pipelineName: "myapp-pipeline",
artifactBucket,
stages: [
{
stageName: "Source",
actions: [
new codepipeline_actions.GitHubSourceAction({
actionName: "GitHub_Source",
owner: "your-org",
repo: "your-repo",
branch: "main",
oauthToken: cdk.SecretValue.secretsManager("github-token"),
output: sourceOutput,
}),
],
},
{
stageName: "Build",
actions: [
new codepipeline_actions.CodeBuildAction({
actionName: "Build_and_Test",
project: buildProject,
input: sourceOutput,
outputs: [buildOutput],
}),
],
},
{
stageName: "Deploy",
actions: [
new codepipeline_actions.EcsDeployAction({
actionName: "Deploy_to_ECS",
service: ecs.FargateService.fromFargateServiceAttributes(
this, "EcsService", {
cluster: ecs.Cluster.fromClusterArn(
this, "Cluster",
`arn:aws:ecs:${this.region}:${this.account}:cluster/myapp-cluster`
),
serviceName: "myapp-service",
}
),
input: buildOutput,
}),
],
},
],
});
// 失败通知
const alertTopic = new sns.Topic(this, "AlertTopic");
pipeline.notifyOnAnyStageStateChange("PipelineNotification", alertTopic, {
events: [
codepipeline.PipelineNotificationEvents.PIPELINE_EXECUTION_FAILED,
codepipeline.PipelineNotificationEvents.PIPELINE_EXECUTION_SUCCEEDED,
],
});
}
}
第3步:配置测试结果报告
claude -p "
想在CodeBuild中将测试结果发送到CodeBuild Reports,
以便为每个PR查看质量报告。
- 测试框架:Vitest
- 覆盖率报告:Istanbul(lcov格式)
- 在buildspec.yml中添加reports部分
- 也用CDK定义报告组
"
# buildspec.yml的reports部分
reports:
UnitTestResults:
files:
- "test-results/junit.xml"
file-format: JUNITXML
CodeCoverage:
files:
- "coverage/lcov.info"
file-format: CLOVERXML
第4步:多环境流水线设计
claude -p "
用CDK设计3个环境的分阶段部署流水线:dev → staging → prod。
- dev:向main分支push时自动部署
- staging:dev部署成功后,经手动审批后部署
- prod:staging部署成功后,经手动审批后部署
- 各环境部署完成时通知Slack
"
// 为staging → prod添加手动审批门控
{
stageName: "Approve_Staging",
actions: [
new codepipeline_actions.ManualApprovalAction({
actionName: "Approve_Deploy_to_Staging",
notificationTopic: alertTopic,
additionalInformation: "批准部署到Staging吗?",
}),
],
},
{
stageName: "Deploy_Staging",
actions: [
new codepipeline_actions.EcsDeployAction({
actionName: "Deploy_to_Staging",
service: stagingService,
input: buildOutput,
}),
],
},
4个常见陷阱
1. 忘记CodeBuild中的privileged: true
构建Docker镜像需要privileged: true。没有这个设置会出现Cannot connect to the Docker daemon错误。
2. GitHub OAuth令牌权限不足
GitHub源需要repo权限范围。仅有public_repo不能用于私有仓库。
3. S3制品存储桶的区域
流水线和制品S3存储桶必须在同一区域。跨区域流水线需要额外配置。
4. ECS部署操作的imagedefinitions.json格式
ECS部署需要精确的格式:
[{"name": "容器名", "imageUri": "镜像URI"}]
容器名必须与任务定义中的容器名完全一致。
先确定Source-Build-Test-Deploy的最小结构
对初学者来说,可以把CodePipeline理解成发布流程的传送带。pipeline是整个流程,stage是Source、Build、Test、Deploy这样的分段,action是分段里实际执行的一步,artifact则是传给下一步的文件包。比如GitHub取出的源码是SourceOutput,CodeBuild生成的dist或zip是BuildOutput。
AWS的CodePipeline concepts也是这个模型:pipeline包含stage,stage包含action,action消费或产出artifact。让Claude Code生成流水线时,先把这四个词讲清楚,输出就会少很多危险默认值。
最小实践可以从Source -> Build -> Test -> Approve -> Deploy开始。AWS创建指南也说明,pipeline至少需要Source stage,以及另一个Build或Deploy stage。生产发布前加入Manual approval,能给团队留下最后的人类确认点。
{
"pipeline": {
"name": "webapp-main",
"roleArn": "arn:aws:iam::123456789012:role/service-role/AWSCodePipelineServiceRole-ap-northeast-1-webapp-main",
"artifactStore": { "type": "S3", "location": "my-codepipeline-artifacts-apne1" },
"stages": [
{ "name": "Source", "actions": [{ "name": "Source", "actionTypeId": { "category": "Source", "owner": "AWS", "provider": "CodeStarSourceConnection", "version": "1" }, "configuration": { "ConnectionArn": "arn:aws:codestar-connections:ap-northeast-1:123456789012:connection/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "FullRepositoryId": "your-org/your-repo", "BranchName": "main", "OutputArtifactFormat": "CODE_ZIP" }, "outputArtifacts": [{ "name": "SourceOutput" }], "runOrder": 1 }] },
{ "name": "Build", "actions": [{ "name": "BuildAndUnitTest", "actionTypeId": { "category": "Build", "owner": "AWS", "provider": "CodeBuild", "version": "1" }, "configuration": { "ProjectName": "webapp-build" }, "inputArtifacts": [{ "name": "SourceOutput" }], "outputArtifacts": [{ "name": "BuildOutput" }], "runOrder": 1 }] },
{ "name": "ApproveProd", "actions": [{ "name": "ApproveProduction", "actionTypeId": { "category": "Approval", "owner": "AWS", "provider": "Manual", "version": "1" }, "configuration": { "CustomData": "批准前检查smoke test、CloudWatch告警和发布说明。" }, "runOrder": 1 }] }
]
}
}
aws codepipeline create-pipeline --cli-input-json file://pipeline.json
aws codepipeline get-pipeline-state --name webapp-main
aws codepipeline start-pipeline-execution --name webapp-main
S3/CloudFront和Lambda部署例
静态站点可以让CodeBuild生成dist,再由S3 deploy action展开到bucket。CloudFront invalidation最好放到后续CodeBuild或Lambda invoke action,这样图上职责更清楚。Lambda则可以由CodeBuild打包,再交给CloudFormation部署。
version: 0.2
env:
variables:
AWS_REGION: ap-northeast-1
S3_BUCKET: my-webapp-prod
CLOUDFRONT_DISTRIBUTION_ID: E1234567890ABC
phases:
install:
runtime-versions:
nodejs: 20
commands:
- npm ci
pre_build:
commands:
- npm test
- npm run lint
build:
commands:
- npm run build
post_build:
commands:
- aws s3 sync ./dist s3://$S3_BUCKET/ --delete --cache-control "public,max-age=300"
- aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
artifacts:
base-directory: dist
files:
- "**/*"
三种实例最常见:Astro/Next.js静态站点发布到S3和CloudFront;API Lambda通过CloudFormation更新;staging自动部署但production必须人工审批。把三类拆开,artifact名和IAM权限都更容易检查。
失败时先看stage和action
Source失败通常是ConnectionArn、分支名或artifact格式。Build失败通常看CodeBuild日志、buildspec、环境变量和IAM。Deploy失败通常是artifact名称、S3 bucket、CloudFormation role、Lambda包路径或区域不一致。
aws codepipeline get-pipeline-state --name webapp-main
aws codepipeline list-action-executions --pipeline-name webapp-main --max-results 5
aws logs tail /aws/codebuild/webapp-build --since 30m --follow
常见失败例有三个。第一,BuildOutput产出了,却在Deploy里读取SourceOutput。第二,CodeBuild service role缺少S3、CloudFront、CloudFormation或Lambda权限。第三,把token放进明文环境变量,而不是Parameter Store或Secrets Manager。AWS actions guide把action分成Source、Build、Test、Deploy、Approval、Invoke,权限也应该按action检查。
安全交给Claude Code的提示词
请为这个仓库添加 AWS CodePipeline + CodeBuild CI/CD。
目标: Source使用GitHub main,Build运行npm ci/test/build,Test单独执行smoke test,Production前加入Manual approval,Deploy到S3并执行CloudFront invalidation。
限制: 不要使用AdministratorAccess,不要给通配符IAM权限,不要无审批部署生产,不要把secret放进明文环境变量,不要删除已有pipeline或bucket。
成果物: buildspec.yml、pipeline.json或CDK stack、失败排查命令、README运维步骤。
验证: 修改前说明当前结构,展示diff,写出aws codepipeline get-pipeline-state和CodeBuild日志查看方法。
这个提示词对齐了Create a pipeline, stages, and actions和Define CI/CD pipelines。让Claude Code说明自己依据的官方概念,review会轻松很多。
Masa式验证记录和下一步
Masa的经验感是,最先固定artifact名最有效。SourceOutput、BuildOutput、TestOutput清楚后,失败点会马上浮出来。初学者也不要一开始就全CDK化,先用console或JSON看懂CodePipeline画面,再抽象成CDK更稳。
这个主题会自然连接到Claude Code AWS IAM指南、AWS S3入门和AWS Lambda完整指南。个人学习先看免费PDF即可;团队要落地CI/CD时,buildspec、IAM、审批、回滚和故障检查需要一起设计,可以从Claude Code培训与咨询继续。
总结
| 任务 | Claude Code的贡献 |
|---|---|
| buildspec.yml生成 | 包含构建、测试、Docker和安全扫描一体生成 |
| CDK流水线 | 自动生成Source→Build→Deploy的全部阶段 |
| 多环境设计 | 设计带手动审批门控的分阶段部署 |
| 测试报告 | 自动化CodeBuild Reports配置 |
CodePipeline的配置看起来很复杂,但只需告诉Claude Code”我想要这样的流水线”,它就会一次性生成buildspec.yml和CDK代码。建议先从buildspec.yml开始尝试。
相关文章
- Claude Code × AWS ECS/Fargate 完全指南
- Claude Code × AWS CloudFormation/CDK 完全指南
- Claude Code × AWS IAM 完全指南
参考资料
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
从Obsidian到CLAUDE.md的Claude Code流程:不再反复解释上下文
把 Obsidian 工作笔记整理成 CLAUDE.md 运行说明,让 Claude Code 每次都带着正确上下文开始。
Claude Code 收入 CTA 路由:从文章分流到 PDF、Gumroad 与咨询
用 Claude Code 按读者意图把文章流量分到免费 PDF、Gumroad 教材或咨询入口。
Claude Code 团队交接规则: 把审查证据、权限、回滚和收入路径一起交付
面向团队的 Claude Code 交接格式: 证据、权限、回滚、免费 PDF、Gumroad 与咨询路径都要可审查。