Claude Code and AWS CodePipeline: stages, artifacts, approvals, and safe deploys
Design AWS CodePipeline with Claude Code: stages, actions, artifacts, CodeBuild, approvals, S3, Lambda, and failure checks.
“Why bother with AWS CodePipeline when GitHub Actions works fine?”—a question I hear all the time.
The answer lies in deep integration with AWS resources. Pushing to ECR, deploying to ECS, updating CloudFormation stacks—when you want all of this to work natively within AWS, CodePipeline + CodeBuild is the most seamless combination.
I manage pipelines that combine multiple AWS services at work, and ever since Claude Code started generating buildspec.yml, CDK code, and IAM policies all at once just from describing my pipeline requirements, the time to build new pipelines has dropped to one-quarter of what it used to be.
Basic Structure of CodePipeline / CodeBuild
CodePipeline (Orchestrator)
│
├─ Source Stage: Fetch code from GitHub / CodeCommit
├─ Build Stage: Build, test, create Docker images with CodeBuild
├─ Test Stage: Integration tests, security scans (optional)
└─ Deploy Stage: Deploy to ECS / Elastic Beanstalk / S3
CodeBuild executes commands written in buildspec.yml. Think of it as the equivalent of steps: in GitHub Actions.
Step 1: Auto-Generate buildspec.yml
claude -p "
Generate a buildspec.yml for CodeBuild with the following requirements.
[Build Contents]
- Node.js 20 environment
- Install with npm ci
- TypeScript build (npm run build)
- Run unit tests (npm test)
- Build Docker image and push to ECR
- Image tag: CODEBUILD_RESOLVED_SOURCE_VERSION (Git SHA)
- Also attach latest tag simultaneously
[Security Scan]
- Run Trivy scan after ECR image push
- Fail build if HIGH/CRITICAL vulnerabilities found
[Artifacts]
- Output imagedefinitions.json (for ECS deploy)
"
Generated buildspec.yml:
version: 0.2
env:
variables:
AWS_DEFAULT_REGION: us-east-1
ECR_REPO_NAME: myapp
parameter-store:
ECR_REGISTRY: /myapp/ecr-registry
phases:
install:
runtime-versions:
nodejs: 20
commands:
- echo "Installing dependencies..."
- npm ci
pre_build:
commands:
- echo "Running tests..."
- npm test
- echo "Logging in to 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 "Building TypeScript..."
- npm run build
- echo "Building Docker image..."
- docker build -t $IMAGE_URI -t $ECR_REGISTRY/$ECR_REPO_NAME:latest .
post_build:
commands:
- echo "Pushing image to ECR..."
- docker push $IMAGE_URI
- docker push $ECR_REGISTRY/$ECR_REPO_NAME:latest
- echo "Scanning image for vulnerabilities..."
- |
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 "Creating 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
Step 2: Build the Entire Pipeline with CDK
claude -p "
Implement the following CodePipeline in CDK TypeScript in lib/pipeline-stack.ts.
[Pipeline Configuration]
- Source: GitHub (main branch of owner/repo)
- Build: CodeBuild (using buildspec.yml above)
- Deploy: Blue/Green deployment to ECS service
[Notifications]
- Notify Slack via SNS on pipeline failure
- Also notify Slack on successful deployment
[Artifact Store]
- S3 bucket (encryption and versioning enabled)
"
// 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);
// Artifact store S3 bucket
const artifactBucket = new s3.Bucket(this, "ArtifactBucket", {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
// Artifact definitions
const sourceOutput = new codepipeline.Artifact("SourceOutput");
const buildOutput = new codepipeline.Artifact("BuildOutput");
// CodeBuild project
const buildProject = new codebuild.PipelineProject(this, "BuildProject", {
buildSpec: codebuild.BuildSpec.fromSourceFilename("buildspec.yml"),
environment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_7_0,
privileged: true, // Required for Docker builds
},
environmentVariables: {
AWS_ACCOUNT_ID: { value: this.account },
},
});
// Grant ECR access permissions
buildProject.addToRolePolicy(new iam.PolicyStatement({
actions: [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
],
resources: ["*"],
}));
// Pipeline
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,
}),
],
},
],
});
// Failure notifications
const alertTopic = new sns.Topic(this, "AlertTopic");
pipeline.notifyOnAnyStageStateChange("PipelineNotification", alertTopic, {
events: [
codepipeline.PipelineNotificationEvents.PIPELINE_EXECUTION_FAILED,
codepipeline.PipelineNotificationEvents.PIPELINE_EXECUTION_SUCCEEDED,
],
});
}
}
Step 3: Configure Test Result Reports
claude -p "
I want to send test results to CodeBuild Reports in CodeBuild
so I can check quality reports per PR.
- Test framework: Vitest
- Coverage report: Istanbul (lcov format)
- Add reports section to buildspec.yml
- Also define report group with CDK
"
# buildspec.yml reports section
reports:
UnitTestResults:
files:
- "test-results/junit.xml"
file-format: JUNITXML
CodeCoverage:
files:
- "coverage/lcov.info"
file-format: CLOVERXML
Step 4: Multi-Environment Pipeline Design
claude -p "
Design a CDK staged deployment pipeline for 3 environments: dev → staging → prod.
- dev: auto-deploy on push to main branch
- staging: deploy after dev succeeds, with manual approval
- prod: deploy after staging succeeds, with manual approval
- Notify Slack when each environment deployment completes
"
// Add manual approval gates for staging → prod
{
stageName: "Approve_Staging",
actions: [
new codepipeline_actions.ManualApprovalAction({
actionName: "Approve_Deploy_to_Staging",
notificationTopic: alertTopic,
additionalInformation: "Do you approve deployment to Staging?",
}),
],
},
{
stageName: "Deploy_Staging",
actions: [
new codepipeline_actions.EcsDeployAction({
actionName: "Deploy_to_Staging",
service: stagingService,
input: buildOutput,
}),
],
},
4 Common Pitfalls
1. Forgetting privileged: true in CodeBuild
Building Docker images requires privileged: true. Without it, you’ll get Cannot connect to the Docker daemon errors.
2. Insufficient GitHub OAuth Token Permissions
The GitHub source requires the repo scope. Using only public_repo won’t work for private repositories.
3. S3 Artifact Bucket Region
The pipeline and the artifact S3 bucket must be in the same region. Cross-region pipelines require additional configuration.
4. imagedefinitions.json Format for ECS Deploy Action
ECS deployment requires the exact format:
[{"name": "container-name", "imageUri": "image-uri"}]
The container name must exactly match the container name in the task definition.
Start with the minimal Source-Build-Test-Deploy shape
For a beginner, CodePipeline is easiest to understand as a conveyor belt for releases. A pipeline is the whole release flow. A stage is a named section such as Source, Build, Test, Approval, or Deploy. An action is the actual task inside a stage. An artifact is the bundle passed from one action to the next, for example source code from GitHub or a built dist directory from CodeBuild.
The AWS CodePipeline concepts page uses the same mental model: pipelines contain stages, stages contain actions, and actions consume or produce artifacts. When you ask Claude Code to build a pipeline, naming these four pieces clearly prevents vague and risky output.
A practical first pipeline is Source -> Build -> Test -> Approve -> Deploy. AWS notes in the pipeline creation guide that a pipeline needs at least a source stage and one other build or deployment stage. In real teams, adding a manual approval before production is usually worth the extra click because it gives humans one final checkpoint.
| stage | action | artifact | purpose |
|---|---|---|---|
| Source | GitHub / CodeStar connection | SourceOutput | Pull the main branch change |
| Build | CodeBuild | BuildOutput | npm ci, tests, build, zip |
| Test | CodeBuild | TestOutput | Run smoke tests separately |
| Approve | Manual approval | none | Human check before production |
| Deploy | S3 / CloudFormation / Lambda | BuildOutput | Publish to S3/CloudFront or Lambda |
{
"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": "Check smoke test, CloudWatch alarms, and release note before approving." }, "runOrder": 1 }] }
]
}
}
aws codepipeline create-pipeline --cli-input-json file://pipeline.json
aws codepipeline get-pipeline --name webapp-main
aws codepipeline start-pipeline-execution --name webapp-main
S3/CloudFront and Lambda deploy examples
For a static site, let CodeBuild create the dist directory and let the S3 deploy action extract the artifact into the hosting bucket. CloudFront invalidation is a separate concern, so put it in a following CodeBuild or Lambda invoke action if you want the pipeline graph to stay readable. For Lambda, CodeBuild can package the function and CloudFormation can deploy the packaged template.
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:
- "**/*"
For Lambda, keep the package and the deploy template visible as artifacts.
version: 0.2
env:
variables:
AWS_REGION: ap-northeast-1
ARTIFACT_BUCKET: my-lambda-artifacts-apne1
phases:
install:
runtime-versions:
nodejs: 20
commands:
- npm ci
build:
commands:
- npm test
- npm run build
- zip -r function.zip dist package.json node_modules
post_build:
commands:
- aws s3 cp function.zip s3://$ARTIFACT_BUCKET/lambda/function.zip
- aws cloudformation package --template-file template.yml --s3-bucket $ARTIFACT_BUCKET --output-template-file packaged.yml
artifacts:
files:
- packaged.yml
- function.zip
Three use cases cover most early teams: a static Astro or Next.js site deployed to S3 and CloudFront, a Lambda API packaged through CloudFormation, and a team release flow where staging is automatic but production requires approval. Keeping these separate makes artifacts and IAM easier to review.
How to inspect failures
When CodePipeline fails, do not stare at the whole pipeline first. Identify the failed stage and action. Source failures usually mean connection ARN, branch name, or artifact format. Build failures usually mean CodeBuild logs, buildspec syntax, environment variables, or IAM. Deploy failures usually mean artifact names, bucket permissions, CloudFormation role permissions, Lambda package paths, or region mismatch.
aws codepipeline get-pipeline-state --name webapp-main
aws codepipeline list-action-executions --pipeline-name webapp-main --max-results 5
aws codebuild batch-get-builds --ids webapp-build:BUILD_ID_FROM_ACTION_EXECUTION
aws logs tail /aws/codebuild/webapp-build --since 30m --follow
The most common artifact mistake is producing BuildOutput and then configuring the deploy action to read SourceOutput. The next one is giving the CodeBuild service role too little access to S3, CloudFront, CloudFormation, or Lambda. Another expensive mistake is placing tokens in plaintext environment variables instead of Parameter Store or Secrets Manager. AWS lists Source, Build, Test, Deploy, Approval, and Invoke as action categories in the actions guide, so review permissions by action instead of by pipeline as a whole.
A safe Claude Code prompt
Claude Code can generate a broad IAM policy or skip the approval gate if the request is too vague. The prompt should include the desired stages, the forbidden behavior, and the verification commands.
Add AWS CodePipeline + CodeBuild CI/CD to this repository.
Goal:
- Source: GitHub main
- Build: CodeBuild runs npm ci, npm test, npm run build
- Test: run smoke tests in a separate CodeBuild action
- Approve: add Manual approval before production
- Deploy: publish dist to S3 and invalidate CloudFront
Constraints:
- Do not attach AdministratorAccess or broad wildcard IAM permissions
- Do not deploy to production automatically without approval
- Do not store secrets in plaintext environment variables
- Do not delete existing pipelines or buckets
Deliverables:
- buildspec.yml
- pipeline.json or CDK stack
- failure inspection commands
- README operating guide
Verification:
- Explain the current setup before changing it
- Show the diff before applying changes
- Document aws codepipeline get-pipeline-state and CodeBuild log checks
This prompt follows the AWS pipeline creation guide and pipeline definition guide. Asking Claude Code to explain which official concepts it used makes the review much easier.
Masa-style verification note and next step
The strongest small habit is naming artifacts consistently: SourceOutput, BuildOutput, and TestOutput. That alone makes failures easier to inspect. Starting with a visible JSON or console pipeline also helps beginners map the CodePipeline screen back to the source. After the first working pipeline, CDK is much easier to understand.
This topic connects directly to IAM, S3, Lambda, and CloudFront. Read the AWS IAM guide, the AWS S3 guide, and the AWS Lambda guide if you want the whole release flow to make sense.
If you are testing alone, start with the free PDF and keep the basic Claude Code commands nearby. If you are introducing CI/CD to a team, design buildspec, IAM, approval gates, rollback behavior, and incident checks together. For that deeper setup, the Claude Code training and consultation page is the natural next step.
Summary
| Task | Claude Code’s Contribution |
|---|---|
| buildspec.yml generation | Generated with build, test, Docker, and security scan included |
| CDK Pipeline | Auto-generates all stages from Source→Build→Deploy |
| Multi-environment design | Designs staged deployment with manual approval gates |
| Test reports | Automates CodeBuild Reports configuration |
CodePipeline configuration may look complex, but just tell Claude Code “I want this kind of pipeline” and it will produce both buildspec.yml and CDK code in one shot. Start by trying it with buildspec.yml first.
Related Articles
- Claude Code × AWS ECS/Fargate Complete Guide
- Claude Code × AWS CloudFormation/CDK Complete Guide
- Claude Code × AWS IAM Complete Guide
References
Free PDF: Claude Code Cheatsheet
Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.
We handle your data with care and never send spam.
Level up your Claude Code workflow
Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.
About the Author
Masa
Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.
Related Posts
Claude Code Obsidian to CLAUDE.md Workflow: Stop Re-explaining Context
Turn Obsidian working notes into concise CLAUDE.md operating notes that make Claude Code sessions easier to resume.
Claude Code Revenue CTA Routing: Send Articles to PDF, Gumroad, and Consultation
A Claude Code workflow for routing article readers to the free PDF, Gumroad products, or consultation by intent.
Claude Code Team Handoff Rules: Review Evidence, Permissions, Rollback, and Revenue Paths
A practical Claude Code handoff format for team review, proof, permission rules, rollback, free PDF, Gumroad, and consultation paths.
Related Products
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.