Source code is in the pipeline. The Build stage hands it to CodeBuild, which installs dependencies and builds the site. The built files become an output artifact for the Deploy stage.
CodeBuild Service Role
CodeBuild needs its own IAM role, separate from the pipeline’s role in post 8. This role grants CodeBuild permission to write logs and access artifacts.
CodeBuildServiceRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: 'sts:AssumeRole'
Policies:
- PolicyName: CodeBuildAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${AWS::StackName}-Build*'
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:GetBucketVersioning
Resource:
- !Sub '${PipelineArtifactBucket.Arn}/*'
- !GetAtt PipelineArtifactBucket.Arn
AssumeRolePolicyDocument is the trust policy. It allows the codebuild.amazonaws.com service principal to assume this role.
The Policies array contains one inline policy with two statements.
The first statement grants CloudWatch Logs permissions scoped to the build project’s log group (/aws/codebuild/${AWS::StackName}-Build). Without these, builds fail silently with no output to debug.
The second statement grants S3 permissions scoped to the artifact bucket only. CodeBuild reads the source artifact and writes the build artifact back.
CodeBuild Project
The AWS::CodeBuild::Project resource defines the build environment and commands. Everything runs inside a managed container, so there’s nothing to install or maintain.
BuildProject:
Type: 'AWS::CodeBuild::Project'
Properties:
Name: !Sub '${AWS::StackName}-Build'
ServiceRole: !GetAtt CodeBuildServiceRole.Arn
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
Cache:
Type: LOCAL
Modes:
- LOCAL_CUSTOM_CACHE
Source:
Type: CODEPIPELINE
BuildSpec: |
version: 0.2
phases:
install:
runtime-versions:
nodejs: 20
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
base-directory: dist
files:
- '**/*'
cache:
paths:
- 'node_modules/**/*'
A few things to note:
Artifacts: Type: CODEPIPELINE and Source: Type: CODEPIPELINE tell CodeBuild that it receives input from and sends output to a pipeline. It doesn’t pull source or push artifacts on its own.
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0 is a managed image with common runtimes pre-installed. The runtime-versions block in the buildspec selects Node.js 20 from it.
ComputeType: BUILD_GENERAL1_SMALL gives the build 3 GB of memory and 2 vCPUs. That’s plenty for a static site build.
Cache with LOCAL_CUSTOM_CACHE enables local caching on the build host. The buildspec cache.paths section tells CodeBuild which directories to persist. Here it caches node_modules so npm does not re-download every package on every run. The cache is best-effort. If CodeBuild provisions a fresh runner, the cache starts empty and packages are downloaded from scratch.
The buildspec has two phases:
- install selects Node.js 20 and runs
npm ci. Unlikenpm install,npm ciuses the lockfile exactly, is faster in CI, and fails ifpackage-lock.jsonis out of sync withpackage.json. - build runs
npm run build. Replace this with whatever your framework uses.
artifacts tells CodeBuild to package everything in the dist directory. This is the standard output directory for Astro, Vite, and most static site generators. If your framework outputs to build or out, change base-directory to match.
cache.paths lists the directories CodeBuild should persist between builds. node_modules/**/* covers the full dependency tree. This only works with LOCAL_CUSTOM_CACHE set in the resource’s Cache block.
Build Stage
The Build stage in the pipeline’s Stages array connects the Source output to the CodeBuild project.
- Name: Build
Actions:
- Name: SiteBuild
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: '1'
InputArtifacts:
- Name: SourceArtifact
OutputArtifacts:
- Name: BuildArtifact
Configuration:
ProjectName: !Ref BuildProject
InputArtifacts references SourceArtifact from the Source stage. This is the zipped repo contents.
OutputArtifacts names the build output BuildArtifact. The Deploy stage uses this name to pick up the built files.
ProjectName: !Ref BuildProject tells the pipeline which CodeBuild project to run. !Ref returns the project name, not the ARN.