AWS: CodeBuild Deep Dive

Sarath Tamminana
KPMG UK Engineering
8 min readJun 21, 2024

HI Everyone,

As part of AWS Developer tools deep dive series, in this article I would like to give a detailed usage information about CodeBuild.

AWS CodeBuild is a fully managed build service in the cloud. CodeBuild compiles your source code, runs unit tests, and produces artifacts that are ready to deploy.

It is better to understand CodeCommit Article here before implementing the below topics.

Topics to be covered

  1. Initial Identity Access Management Setup
  2. Sample Code Overview
  3. CodeBuild Project Setup
  4. Integrating SNS with proper Access Policy
  5. Triggers and Notifications
  6. Build Process and Artifacts Validation
  7. Report History and Report Groups

Initial Identity Access Management Setup

We need a user and a role to perform the CodeBuild Tasks without any issues.

a. Create a “testuser” and attach the CodeCommit Full Access as shown below. We are going to use this for pushing our codebase to CodeCommit Repository.

Please generate the HTTPS Credentials as well by going into Security Credentials section. We are going to use those for Authentication with CodeCommit Repository.

b. Create a “codebuildlearningrole” and attach EC2/S3/CodeCommit/SNS/CodeDeploy Full Access. You can use granular permissions as well in case you feel the permissions are too broad. Please make sure this rule should be assumed by CodeBuild Service to perform operations like pushing Artifacts to s3, sending notification event to sns and communicating with CodeDeploy.

Sample Code Overview

In order to work with CodeBuild we are going to specify the operations in the form of YAML File called as buildspec.yml.

We are going to build a jar file as well as few tar.gz files as artifacts using CodeBuild.

MessageUtil.java

public class MessageUtil {
private String message;

public MessageUtil(String message) {
this.message = message;
}

public String printMessage() {
System.out.println(message);
return message;
}

public String salutationMessage() {
message = "Hi!" + message;
System.out.println(message);
return message;
}
}

TestMessageUtil.java

import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestMessageUtil {

String message = "Robert";
MessageUtil messageUtil = new MessageUtil(message);

@Test
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
assertEquals(message,messageUtil.printMessage());
}

@Test
public void testSalutationMessage() {
System.out.println("Inside testSalutationMessage()");
message = "Hi!" + "Robert";
assertEquals(message,messageUtil.salutationMessage());
}
}

buildspec.yml : Total 4 phases, you should not change the names. All those are predefined names. 3 Artifacts one is created during mvn install and other 2 are sample tar.gz files creating for demonstrating purpose.

version: 0.2

phases:
install:
runtime-versions:
java: corretto11
pre_build:
commands:
- echo
build:
commands:
- echo Build started on `date`
- mvn install
- mkdir files
- touch f1 f2
- cp -rf f1 f2 files/
- tar -cvzf files.tar.gz files
- mkdir files2
- cp -rf scripts/* files2/
- tar -cvzf files2.tar.gz files2
post_build:
commands:
- echo Build completed on `date`
artifacts:
files:
- target/messageUtil-1.0.jar
- files.tar.gz
- files2.tar.gz

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>messageUtil</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>Message Utility Java Sample App</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
</plugins>
</build>
</project>

NOTE:

f4, f5 are empty files, I am just using for creation of gz files.

Please make sure to follow below directory structure only otherwise build may trigger errors.

Directory Structure looks like below

I am using EC2 Instance for CLI Purpose. You can use your local environment as well if you are comfortable with that.

Once the folder is created with above directory structure and specified files are updated, we are all good with Codebase.

Please run for proper permissions.

chmod -R 755 testrepo
#testrepo is your codecommit repo cloned directory.

Please push the code to CodeCommit Repository origin, once it is pushed it will be visible as shown below. You need to keep the buildspec.yml in root directory.

CodeBuild Project Setup

Switch to the CodeBuild Landing Page and click on create project

Please make sure to have an S3 Bucket in place to store your artifacts.

As part of the build project creation consider using CodeCommit for Source Code, S3 bucket as destination for storing the Artifacts.

Please select the branch where your code is currently located. As of now myn is in master so using the same while configuring the project.

Please use the Environment default options only for convenience purpose.

Since we placed all our instruction in buildspec.yml file, we are going to select that. In case you want to run any commands, you can enter manually.

Consider using the IAM Role we created during initial setup.

Consider S3 as destination to store our artifacts. You need to select the bucket which you created in your account.

Once the project is created, it will be listed in Build Projects section as below.

Integrating SNS with proper Access Policy

We would like to get notified for specific Build Events like failed/succeeded/InProgress. We will be integrating an SNS Topic to the Build Project to get the notifications.

Create a TOPIC and update the access policy as shown below. If you don’t use the correct access policy, Notification target will go to unreachable state. so please make sure the below access policy in sns topic. Please don’t enable encryption for convenience purpose. In case you enabled it, you need to use different access policy.


{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "CodeNotification_publish",
"Effect": "Allow",
"Principal": {
"Service": "codestar-notifications.amazonaws.com"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:eu-west-1:1XXXXXXXXX:TOPIC_NAME"
}
]
}

NOTE 1: Change 12345678910 to your AWS account ID, and TOPIC_NAME to the name of your SNS topic.
NOTE 2: If your region is different than us-east-2, then change that too in the above snippet.
NOTE 3: Both the SNS topic and the Codebuild Notification rule should be in the same region, otherwise this won’t work.

Triggers and Notifications

Go to the Project Settings and select the Notifications section

Create a Notification rule, by giving details like Name, Level of Detail, Events and Targets.

Please select the topic which you updated with proper access policy as destination target.

Click Submit. Once the Notification Rule is created, we can validate the Target status. It should be ACTIVE state for getting the Notifications.

If it is UNREACHABLE, please check the access policy and update correctly as shown in the previous step.

We can enable TRIGGERS as well for Project.

Please provide details like how frequently the build need to trigger or at what time the trigger need to start.

Build Process and Artifacts Validation

Select the Build Project and Click on Start Build

You can see the Build Logs

Phase Details

Build Details

Once the BUILD is successful it will be shown as below

We need to validate whether the Artifacts are created and stored in S3 Bucket or not.

If we check our inbox, we will get the notifications for the events we selected during Rule configuration.

Resource Utilization/ Metrics

Report History and Report Groups

Report History: You can create reports in CodeBuild that contain details about tests that are run during builds. You can create tests such as unit tests, configuration tests, and functional tests.

As part of our code, we have few test cases written as shown below. This will help us in generating Reports.

import org.junit.Test;
import org.junit.Ignore;
import static org.junit.Assert.assertEquals;

public class TestMessageUtil {

String message = "Robert";
MessageUtil messageUtil = new MessageUtil(message);

@Test
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
assertEquals(message,messageUtil.printMessage());
}

@Test
public void testSalutationMessage() {
System.out.println("Inside testSalutationMessage()");
message = "Hi!" + "Robert";
assertEquals(message,messageUtil.salutationMessage());
}
}

Report Groups

It contains test reports and specifies shared settings. You use the buildspec file to specify the test cases to run and the commands to run them when it builds. For each report group configured in a build project, a run of the build project creates a test report. Multiple runs of a build project configured with a report group create multiple test reports in that report group, each with results of the same test cases specified for that report group.

Hope you got some good insights of CodeBuild with this article.

Happy Learning!!!

--

--

Sarath Tamminana
KPMG UK Engineering

Certified AWS & GCP Cloud Architect currently working at KPMG as a Assistant Manager. About 10 years of experience in Cloud, DevOps & Middleware Technologies