Use Cases (更新: 2026/6/1)

Claude Code × AWS CodePipeline入门:stage、artifact、审批与安全部署

用Claude Code设计AWS CodePipeline:stage/action/artifact、CodeBuild、审批、S3、Lambda和失败排查。

Claude Code × AWS CodePipeline入门:stage、artifact、审批与安全部署

“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 actionsDefine 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 #codepipeline #codebuild #cicd #devops
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。