The Deploy Stage is where your SAM application and all its resources are created in an AWS account. The most common way to do this is by using CloudFormation ChangeSets to deploy. This means that this stage will have 2 actions: the CreateChangeSet and the ExecuteChangeSet.
Add the Deploy stage to your PipelineStack.java:
// Deploy stage
CloudFormationCreateReplaceChangeSetAction createChangeSet = new CloudFormationCreateReplaceChangeSetAction(CloudFormationCreateReplaceChangeSetActionProps.builder()
.actionName("CreateChangeSet")
.templatePath(buildOutput.atPath("packaged.yaml"))
.stackName("sam-app")
.adminPermissions(true)
.changeSetName("sam-app-dev-changeset")
.runOrder(1)
.build());
CloudFormationExecuteChangeSetAction executeChangeSet = new CloudFormationExecuteChangeSetAction(CloudFormationExecuteChangeSetActionProps.builder()
.actionName("Deploy")
.stackName("sam-app")
.changeSetName("sam-app-dev-changeset")
.runOrder(2)
.build());
pipeline.addStage(StageOptions.builder()
.stageName("Dev")
.actions(Arrays.asList(createChangeSet, executeChangeSet))
.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:#75715e">// The code that defines your stack goes here
Bucket artifactsBucket = new Bucket(this, "ArtifactsBucket");
<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>());
<span style="color:#75715e">// Declare build output as artifacts
Artifact buildOutput = new Artifact("buildOutput");
<span style="color:#75715e">// 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());
<span style="color:#75715e">// Add the build stage to our pipeline
CodeBuildAction buildAction = new CodeBuildAction(CodeBuildActionProps.builder() .actionName("Build") .project(buildProject) .input(sourceOutput) .outputs(Collections.singletonList(buildOutput)) .build());
<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">"Build"</span>)
.<span style="color:#a6e22e">actions</span>(<span style="color:#a6e22e">Collections</span>.<span style="color:#a6e22e">singletonList</span>(<span style="color:#a6e22e">buildAction</span>))
.<span style="color:#a6e22e">build</span>());
On your terminal, run the following commands from within the pipeline directory:
cd ~/environment/sam-app/pipeline
mvn package
cdk deploy
The CLI might ask you to confirm the changes before deploying, this is because we are giving Admin permissions to the IAM role that deploys our application. This is generally not a bad practice since this role can only be assumed by CloudFormation and not by a human, however, if your organization has a stricter security posture you may want to consider creating a custom IAM deployment role with a fine grain policy.
Navigate to your pipeline and you will see the Deploy stage has been added, however, it is currently grayed out because it hasn’t been triggered. Let’s just trigger a new run of the pipeline manually by clicking the Release Change buttton.