The Build Stage is where your Serverless application gets built and packaged by SAM. We are going to use AWS CodeBuild as the Build provider for our pipeline. It is worth mentioning that CodePipeline also supports other providers like Jenkins, TeamCity or CloudBees.
AWS CodeBuild is a great option because you only pay for the time where your build is running, which makes it very cost effective compared to running a dedicated build server 24 hours a day when you really only build during office hours. It is also container-based which means that you can bring your own Docker container image where your build runs, or use a managed image provided by CodeBuild.
Let’s go ahead and add a Build stage to you PipelineStack.java:
// Declare build output as artifacts
Artifact buildOutput = new Artifact("buildOutput");
// Declare a new CodeBuild project
PipelineProject buildProject = new PipelineProject(this, "Build", PipelineProjectProps.builder()
.environment(BuildEnvironment.builder()
.buildImage(AMAZON_LINUX_2).build())
.environmentVariables(Collections.singletonMap("PACKAGE_BUCKET", BuildEnvironmentVariable.builder()
.value(artifactsBucket.getBucketName())
.build()))
.build());
// Add the build stage to our pipeline
CodeBuildAction buildAction = new CodeBuildAction(CodeBuildActionProps.builder()
.actionName("Build")
.project(buildProject)
.input(sourceOutput)
.outputs(Collections.singletonList(buildOutput))
.build());
pipeline.addStage(StageOptions.builder()
.stageName("Build")
.actions(Collections.singletonList(buildAction))
.build());
The highlighted code is the new addition:
import software.amazon.awscdk.core.Construct; import software.amazon.awscdk.core.Stack; import software.amazon.awscdk.core.StackProps; import software.amazon.awscdk.services.codebuild.; import software.amazon.awscdk.services.codecommit.; import software.amazon.awscdk.services.codepipeline.; import software.amazon.awscdk.services.codepipeline.actions.; import software.amazon.awscdk.services.s3.Bucket;
import java.util.*;
import static software.amazon.awscdk.services.codebuild.LinuxBuildImage.AMAZON_LINUX_2;
public class PipelineStack extends Stack { public PipelineStack(final Construct scope, final String id) { this(scope, id, null); }
<span style="color:#66d9ef">public</span> <span style="color:#a6e22e">PipelineStack</span>(<span style="color:#66d9ef">final</span> <span style="color:#a6e22e">Construct</span> <span style="color:#a6e22e">scope</span>, <span style="color:#66d9ef">final</span> String <span style="color:#a6e22e">id</span>, <span style="color:#66d9ef">final</span> <span style="color:#a6e22e">StackProps</span> <span style="color:#a6e22e">props</span>) {
<span style="color:#66d9ef">super</span>(<span style="color:#a6e22e">scope</span>, <span style="color:#a6e22e">id</span>, <span style="color:#a6e22e">props</span>);
<span style="color:#a6e22e">Bucket</span> <span style="color:#a6e22e">artifactsBucket</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Bucket</span>(<span style="color:#66d9ef">this</span>, <span style="color:#e6db74">"ArtifactsBucket"</span>);
<span style="color:#a6e22e">IRepository</span> <span style="color:#a6e22e">codeRepo</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">Repository</span>.<span style="color:#a6e22e">fromRepositoryName</span>(<span style="color:#66d9ef">this</span>, <span style="color:#e6db74">"AppRepository"</span>, <span style="color:#e6db74">"sam-app"</span>);
<span style="color:#a6e22e">Pipeline</span> <span style="color:#a6e22e">pipeline</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Pipeline</span>(<span style="color:#66d9ef">this</span>, <span style="color:#e6db74">"Pipeline"</span>, <span style="color:#a6e22e">PipelineProps</span>.<span style="color:#a6e22e">builder</span>()
.<span style="color:#a6e22e">artifactBucket</span>(<span style="color:#a6e22e">artifactsBucket</span>).<span style="color:#a6e22e">build</span>());
<span style="color:#a6e22e">Artifact</span> <span style="color:#a6e22e">sourceOutput</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Artifact</span>(<span style="color:#e6db74">"sourceOutput"</span>);
<span style="color:#a6e22e">CodeCommitSourceAction</span> <span style="color:#a6e22e">codeCommitSource</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">CodeCommitSourceAction</span>(<span style="color:#a6e22e">CodeCommitSourceActionProps</span>.<span style="color:#a6e22e">builder</span>()
.<span style="color:#a6e22e">actionName</span>(<span style="color:#e6db74">"CodeCommit_Source"</span>)
.<span style="color:#a6e22e">repository</span>(<span style="color:#a6e22e">codeRepo</span>)
.<span style="color:#a6e22e">output</span>(<span style="color:#a6e22e">sourceOutput</span>)
.<span style="color:#a6e22e">build</span>());
<span style="color:#a6e22e">pipeline</span>.<span style="color:#a6e22e">addStage</span>(<span style="color:#a6e22e">StageOptions</span>.<span style="color:#a6e22e">builder</span>()
.<span style="color:#a6e22e">stageName</span>(<span style="color:#e6db74">"Source"</span>)
.<span style="color:#a6e22e">actions</span>(<span style="color:#a6e22e">Collections</span>.<span style="color:#a6e22e">singletonList</span>(<span style="color:#a6e22e">codeCommitSource</span>))
.<span style="color:#a6e22e">build</span>());
Artifact buildOutput = new Artifact("buildOutput"); PipelineProject buildProject = new PipelineProject(this, "Build", PipelineProjectProps.builder() .environment(BuildEnvironment.builder() .buildImage(AMAZON_LINUX_2).build()) .environmentVariables(Collections.singletonMap("PACKAGE_BUCKET", BuildEnvironmentVariable.builder() .value(artifactsBucket.getBucketName()) .build())) .build()); CodeBuildAction buildAction = new CodeBuildAction(CodeBuildActionProps.builder() .actionName("Build") .project(buildProject) .input(sourceOutput) .outputs(Collections.singletonList(buildOutput)) .build()); pipeline.addStage(StageOptions.builder() .stageName("Build") .actions(Collections.singletonList(buildAction)) .build()); } }
From your terminal, run the following commands to deploy the pipeline:
mvn package
cdk deploy
Navigate to the AWS CodePipeline Console and click on your newly created pipeline!
The Build step should have failed. Don’t worry! this is expected because we haven’t specified what commands to run during the build yet, so AWS CodeBuild doesn’t know how to build our Serverless application.
Let’s fix that.