Skip to content

Commit 50a46cb

Browse files
viren-nadkarnigiogranoquetzalliwrites
authored
CodeBuild: Add documentation (#1684)
Co-authored-by: Giovanni Grano <[email protected]> Co-authored-by: Quetzalli <[email protected]>
1 parent 5da8b23 commit 50a46cb

File tree

3 files changed

+384
-2
lines changed

3 files changed

+384
-2
lines changed

content/en/references/configuration.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ This section covers configuration options that are specific to certain AWS servi
125125
| - | - | - |
126126
| `PROVIDER_OVERRIDE_CLOUDWATCH` | `v1` | Use the old CloudWatch provider. |
127127

128+
### CodeBuild
129+
130+
| Variable | Example Values | Description |
131+
| - | - | - |
132+
| `CODEBUILD_REMOVE_CONTAINERS` | `0`\|`1` (default) | Remove Docker containers associated with a CodeBuild build tasks after execution. Disabling this and dumping container logs might help with troubleshooting failing builds. |
133+
128134
### CodePipeline
129135

130136
| Variable | Example Values | Description |

content/en/references/coverage/coverage_codebuild/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
title: "codebuild"
3-
linkTitle: "codebuild"
2+
title: "CodeBuild"
3+
linkTitle: "CodeBuild"
44
description: >
55
Implementation details for API codebuild
66
hide_readingtime: true
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
---
2+
title: CodeBuild
3+
linkTitle: CodeBuild
4+
description: >
5+
Get started with CodeBuild on LocalStack
6+
tags: ["Pro image"]
7+
---
8+
9+
## Introduction
10+
11+
AWS CodeBuild is a fully managed continuous integration service that compiles source code, runs tests, and produces software packages that are ready to deploy.
12+
It is part of the [AWS Developer Tools suite](https://aws.amazon.com/products/developer-tools/) and integrates with other AWS services to provide an end-to-end development pipeline.
13+
14+
LocalStack supports the emulation of most of the CodeBuild operations.
15+
The supported operations are listed on the [API coverage page]({{< ref "coverage_codebuild" >}}).
16+
17+
AWS CodeBuild emulation is powered by the [AWS CodeBuild agent](https://docs.aws.amazon.com/codebuild/latest/userguide/use-codebuild-agent.html).
18+
19+
## Getting Started
20+
21+
This tutorial will show you how to use AWS CodeBuild to test and build a deployable version of a Java executable.
22+
23+
It assumes basic knowledge of the [`awslocal`](https://github.com/localstack/awscli-local) wrapper, Apache Maven, and Java.
24+
25+
### Create the source code
26+
27+
In the first step, we have to create the project that we want to build with AWS CodeBuild.
28+
29+
In an empty directory, we need to re-create the following structure:
30+
31+
```bash
32+
root-directory-name
33+
├── pom.xml
34+
└── src
35+
├── main
36+
│   └── java
37+
│   └── MessageUtil.java
38+
└── test
39+
└── java
40+
└── TestMessageUtil.java
41+
```
42+
43+
Let us walk through these files.
44+
`MessageUtil.java` contains the entire logic of this small application.
45+
It does nothing more than print a salutation message.
46+
Create a `MessageUtil.java` file and save it into the `src/main/java` directory.
47+
48+
```java
49+
public class MessageUtil {
50+
private String message;
51+
52+
public MessageUtil(String message) {
53+
this.message = message;
54+
}
55+
56+
public String printMessage() {
57+
System.out.println(message);
58+
return message;
59+
}
60+
61+
public String salutationMessage() {
62+
message = "Hi!" + message;
63+
System.out.println(message);
64+
return message;
65+
}
66+
}
67+
```
68+
69+
Every build needs to be tested.
70+
Therefore, create the `TestMessageUtil.java` file in the `src/test/java` directory.
71+
72+
```java
73+
import org.junit.Test;
74+
import org.junit.Ignore;
75+
import static org.junit.Assert.assertEquals;
76+
77+
public class TestMessageUtil {
78+
79+
String message = "Robert";
80+
MessageUtil messageUtil = new MessageUtil(message);
81+
82+
@Test
83+
public void testPrintMessage() {
84+
System.out.println("Inside testPrintMessage()");
85+
assertEquals(message,messageUtil.printMessage());
86+
}
87+
88+
@Test
89+
public void testSalutationMessage() {
90+
System.out.println("Inside testSalutationMessage()");
91+
message = "Hi!" + "Robert";
92+
assertEquals(message,messageUtil.salutationMessage());
93+
}
94+
}
95+
```
96+
97+
This small suite simply verifies that the greeting message is built correctly.
98+
99+
Finally, we need a `pom.xml` file to instruct Maven about what to build and which artifact needs to be produced.
100+
Create this file at the root of your directory.
101+
102+
```xml
103+
<project xmlns="http://maven.apache.org/POM/4.0.0"
104+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
105+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
106+
<modelVersion>4.0.0</modelVersion>
107+
<groupId>org.example</groupId>
108+
<artifactId>messageUtil</artifactId>
109+
<version>1.0</version>
110+
<packaging>jar</packaging>
111+
<name>Message Utility Java Sample App</name>
112+
<dependencies>
113+
<dependency>
114+
<groupId>junit</groupId>
115+
<artifactId>junit</artifactId>
116+
<version>4.11</version>
117+
<scope>test</scope>
118+
</dependency>
119+
</dependencies>
120+
<build>
121+
<plugins>
122+
<plugin>
123+
<groupId>org.apache.maven.plugins</groupId>
124+
<artifactId>maven-compiler-plugin</artifactId>
125+
<version>3.8.0</version>
126+
</plugin>
127+
</plugins>
128+
</build>
129+
</project>
130+
```
131+
132+
With the following configuration, Maven will compile the `java` files into a executable jar and run the specified tests.
133+
134+
### Create the buildspec file
135+
136+
Now that we have our project set up, we need to create a `buildspec` file.
137+
A `buildspec` file is a collection of settings and commands, specified in YAML format, that tells AWS CodeBuild how to run a build.
138+
139+
Create this `buildspec.yml` file in the root directory.
140+
141+
```yaml
142+
version: 0.2
143+
144+
phases:
145+
install:
146+
runtime-versions:
147+
java: corretto11
148+
pre_build:
149+
commands:
150+
- echo Nothing to do in the pre_build phase...
151+
build:
152+
commands:
153+
- echo Build started on `date`
154+
- mvn install
155+
post_build:
156+
commands:
157+
- echo Build completed on `date`
158+
artifacts:
159+
files:
160+
- target/messageUtil-1.0.jar
161+
```
162+
163+
In this file we can observe how the build will be executed.
164+
First, we define a runtime version.
165+
Then, we run a `mvn install` command in the build phase which does both the compilation and the testing.
166+
The pre and post build phases do not do much in this example, but can be used for various things, like install some software needed for the build itself.
167+
168+
A full specification of a `buildspec` file can be found in the [AWS CodeBuild docs](https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html).
169+
170+
### Create input and output buckets
171+
172+
Now we have to create two S3 buckets:
173+
- one bucket that stores the source we just created, that will be the source of the AWS CodeBuild build
174+
- one bucket where the output of the build, i.e., the JAR file, will be stored.
175+
176+
Create the buckets with the following commands:
177+
178+
{{< command >}}
179+
$ awslocal s3 mb s3://codebuild-demo-input
180+
<disable-copy>
181+
make_bucket: codebuild-demo-input
182+
</disable-copy>
183+
{{< /command >}}
184+
185+
{{< command >}}
186+
$ awslocal s3 mb s3://codebuild-demo-output
187+
<disable-copy>
188+
make_bucket: codebuild-demo-output
189+
{{< /command >}}
190+
191+
Finally, zip the content of the source code directory and upload it to the created source bucket.
192+
With a UNIX system, you can simply use the `zip` utility:
193+
{{< command >}}
194+
$ zip -r MessageUtil.zip <source-directory>
195+
{{< /command >}}
196+
197+
Then, upload `MessageUtil.zip` to the `codebuild-demo-input` bucket with the following command:
198+
199+
{{< command >}}
200+
$ awslocal s3 cp MessageUtil.zip s3://codebuild-demo-input
201+
{{< /command >}}
202+
203+
### Configuring IAM
204+
205+
To properly work, AWS CodeBuild needs access to other AWS services, e.g., to retrieve the source code from a S3 bucket.
206+
Create a `create-role.json` file with following content:
207+
208+
```json
209+
{
210+
"Version": "2012-10-17",
211+
"Statement": [
212+
{
213+
"Effect": "Allow",
214+
"Principal": {
215+
"Service": "codebuild.amazonaws.com"
216+
},
217+
"Action": "sts:AssumeRole"
218+
}
219+
]
220+
}
221+
```
222+
223+
Then, run the following command to create the necessary IAM role:
224+
{{< command >}}
225+
$ awslocal iam create-role --role-name CodeBuildServiceRole --assume-role-policy-document file://create-role.json
226+
{{< /command >}}
227+
228+
From the command's response, keep note of the role ARN:
229+
it will be needed to create the CodeBuild project later on.
230+
231+
Let us now define a policy for the created role.
232+
Create a `put-role-policy.json` file with the following content:
233+
234+
```json
235+
{
236+
"Version": "2012-10-17",
237+
"Statement": [
238+
{
239+
"Sid": "CloudWatchLogsPolicy",
240+
"Effect": "Allow",
241+
"Action": [
242+
"logs:CreateLogGroup",
243+
"logs:CreateLogStream",
244+
"logs:PutLogEvents"
245+
],
246+
"Resource": "*"
247+
},
248+
{
249+
"Sid": "CodeCommitPolicy",
250+
"Effect": "Allow",
251+
"Action": [
252+
"codecommit:GitPull"
253+
],
254+
"Resource": "*"
255+
},
256+
{
257+
"Sid": "S3GetObjectPolicy",
258+
"Effect": "Allow",
259+
"Action": [
260+
"s3:GetObject",
261+
"s3:GetObjectVersion"
262+
],
263+
"Resource": "*"
264+
},
265+
{
266+
"Sid": "S3PutObjectPolicy",
267+
"Effect": "Allow",
268+
"Action": [
269+
"s3:PutObject"
270+
],
271+
"Resource": "*"
272+
},
273+
{
274+
"Sid": "S3BucketIdentity",
275+
"Effect": "Allow",
276+
"Action": [
277+
"s3:GetBucketAcl",
278+
"s3:GetBucketLocation"
279+
],
280+
"Resource": "*"
281+
}
282+
]
283+
}
284+
```
285+
286+
Finally, assign the policy to the role with the following command:
287+
288+
{{< command >}}
289+
$ awslocal put-role-policy --role-name CodeBuildServiceRole --policy-name CodeBuildServiceRolePolicy --policy-document file://put-role-policy.json
290+
{{< /command >}}
291+
292+
### Create the build project
293+
294+
We now need to create a build project, containing all the information about how to run a build, where to get the source code, and where to place the output.
295+
296+
You can use the CLI to generate the skeleton of the `CreateBuild` request, which you can later modify.
297+
Save the output of the following command to a file named `create-project.json`.
298+
299+
{{< command >}}
300+
$ awslocal codebuild create-project --generate-cli-skeleton
301+
{{< /command >}}
302+
303+
From the generated file, change the source and the artifact location to match the S3 bucket names you just created.
304+
Similarly, fill in the ARN of the CodeBuild service role.
305+
306+
```json {hl_lines=[5,9,16]}
307+
{
308+
"name": "codebuild-demo-project",
309+
"source": {
310+
"type": "S3",
311+
"location": "codebuild-demo-input"
312+
},
313+
"artifacts": {
314+
"type": "S3",
315+
"location": "codebuild-demo-output"
316+
},
317+
"environment": {
318+
"type": "LINUX_CONTAINER",
319+
"image": "aws/codebuild/standard:5.0",
320+
"computeType": "BUILD_GENERAL1_SMALL"
321+
},
322+
"serviceRole": "service-role-arn"
323+
}
324+
```
325+
326+
Now create the project with the following command:
327+
328+
{{< command >}}
329+
$ awslocal codebuild create-project --cli-input-json file://create-project.json
330+
{{< /command >}}
331+
332+
You have now created a CodeBuild project called `codebuild-demo-project` that uses the S3 buckets you just created as source and artifact.
333+
334+
{{< callout >}}
335+
LocalStack does not allow to customize the build environment.
336+
Depending on the host architecture, the build will be executed an Amazon Linux container, version `3.0.x` and `5.0.x`, respectively for the ARM and the x86 architecture.
337+
{{< /callout >}}
338+
339+
### Run the build
340+
341+
In this final step, you can now execute your build with the following command:
342+
343+
{{< command >}}
344+
$ awslocal codebuild start-build --project-name codebuild-demo-project
345+
{{< /command >}}
346+
347+
Make note of the `id` information given in output, since it can be used to query the status of the build.
348+
If you inspect the running containers (e.g., with the `docker ps -a` command), you will notice a container with the `localstack-codebuild` prefix (followed by the build ID), which CodeBuild started to execute the build.
349+
This container will be responsible to start a Docker compose stack that executes the actual build.
350+
351+
As said, you can inspect the status of the build with the following command:
352+
353+
{{< command >}}
354+
$ awslocal codebuild batch-get-builds --ids <build-id>
355+
{{< /command >}}
356+
357+
The command returns a list of builds.
358+
A build has a `buildStatus` attribute that will be set to `SUCCEEDED` if the build correctly terminates.
359+
360+
{{< callout >}}
361+
Each build goes through different phases, each of them having a start and end time, as well as a status.
362+
LocalStack does not provided such granular information.
363+
Currently, it reports only the final status of the build.
364+
{{< /callout >}}
365+
366+
Once the build is completed, you can verify that the JAR artifact has been uploaded to the correct S3 bucket with the following command:
367+
368+
{{< command >}}
369+
$ awslocal s3 ls://codebuild-demo-output
370+
{{< /command >}}
371+
372+
## Limitations
373+
374+
- CodeBuild currently only supports S3, NO_SOURCE, and CODEPIPELINE as [project source](https://docs.aws.amazon.com/codebuild/latest/APIReference/API_ProjectSource.html).
375+
- CodeBuild only uses Amazon Linux as the build environment for a build project.
376+
- Communication with the LocalStack container within the build environment is possible only via the host network, by using the Gateway IP address (typically 172.17.0.1) or `host.docker.internal` if running on MacOS.

0 commit comments

Comments
 (0)