AWS CodeBuild pipeline

What is CodeBuild?

In short CodeBuild is a fully managed continuous integration service provided by AWS, where you pay for the length of time your builds runs using compute resources. Think Jenkins but extremely AWS flavored with high integration with certain AWS services for example ‘AWS IAM’. If you want to know more about the codebuild features head over to AWS documentation.

Where to start?

Using CodeBuild is fairly straightforward once you understand the basics, for this example you will however need the following beforehand;

  • GitHub account.
  • An AWS account.

We will not discuss how to create an AWS or GitHub account, lets leave that topic for another day. With that out of the way lets begin.

Step 1:

You will first need to create a deployment script which AWS calls the buildspec (with extension .yml) file which has at minimum the following format;

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto11
    commands:
      - echo install step
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - mvn install
  post_build:
    commands:
      - echo Build completed on `date`

Lets take the following example;

version: 0.2

phases:
  install:
    runtime-versions:
      python: 3.8
    commands:
      - echo "install step"
  pre_build:
    commands:
      - ls
  build:
    commands:
      - zip -r test.zip .
      - aws --version
      - pwd
      - aws s3 cp . "s3://codedeploy-test-bucket/" --recursive
  post_build:
    commands:
      - echo Pushed to s3

In the above example we can see that CodeBuild works with “phases” mainly 3; ‘pre_build’, ‘build’, ‘post_build’, similar to stages in Jenkinsfile key difference being you cannot have multiple stages of your choice or name the stages in ‘buildspec’ file.
Then there is the ‘install’ phase, since CodeBuild is a “Serverless” service the build environment is destroyed each time the build is completed, so you need to configure your build environment at the start of each build if your build requires any dependency that’s not available in a standard Amazon Linux image (one of the AWS flavor I mentioned in the beginning.), for example python 3.8 runtime or custom commands to configure the environment. To learn more about what you can do with the buildspec file you can head over here.

First create a file named buildspec with .yml extension then copy the above contents save into the buildspec.yml file, while making sure the spaces match with the example line for line. Upload this buildspec.yml file to your git repository that you wish to use.

Step 2:

Now head over to AWS console web page, open the CodeBuild page by searching codebuild in the search bar.

Click on ‘Build projects’.

Then click on ‘Create Build Project’.

In the create project page set the options to as seen below;

Select GitHub as source provider, we will be using your personal GitHub account to allow CodeBuild to clone repositories. Then click “Connect to GitHub”

A small window will open, asking your permission to allow CodeBuild to connect to you GitHub account. Click on “Authorize aws-codesuite”.

Once you do a final confirm you will see that under ‘Authorized OAuth Apps’ tab an AWS CodeBuild application is visible. The Applications menu can be found in your GitHub account settings.

Once you are successfully connected the Source menu visually changes to allow further configuration. add the git repository you want to use, for this example I am using the ‘codebuild_example’ repository made by yours truly, you may use the repository (https://github.com/CloudInfraChicken/codebuild_example.git) also to get an initial idea of how things work.
Even though this is a public repository we still need to connect our GitHub account to CodeBuild since GitHub and AWS CodeBuild revamped how they handle 3rd party repository authentication and also the options to add the repository URL do not appear until we connect to GitHub.

Now its time to configure the environment CodeBuild will use run the buildspec.yml file. I prefer to use ‘Amazon Linux 2’ since it being optimized for the cloud by AWS, in my experience it plays nicely when your build pipeline need to interact/invoke AWS services like ‘Lambda’.
In the ‘Additional configuration’ set the compute size to the minimum specs depending on your AWS region, since even the minimum specs are overkill for this example. ;-p

Time to configure the buildspec, you have the option to use the default option and let CodeBuild use the buildspec.yml present in the cloned repository.

Or you can preconfigure the buildspec by typing them in the configuration step.

Finally make sure the CloudWatch logs checkbox is selected so we can look at the build logs and click on ‘create build project’.

When you see the example-project in the list, you know the project is created.

Step 3:

Finally its time to run your build. Click on the example-project and then click on ‘Start build’. When you see an entry in the ‘Build history’, the build has started, it might take some time for it to move out of the provision stage.

After a while you will see that the status has changed to ‘Succeeded’ if you fallowed the instructions correctly.

Conclusion

Now that we have basic understanding of how CodeBuild works now lets take a look at the logs and see what CodeBuild did.

[Container] 2022/01/13 09:51:33 Waiting for agent ping
[Container] 2022/01/13 09:51:35 Waiting for DOWNLOAD_SOURCE
[Container] 2022/01/13 09:51:35 Phase is DOWNLOAD_SOURCE
[Container] 2022/01/13 09:51:35 CODEBUILD_SRC_DIR=/codebuild/output/src887441905/src/github.com/CloudInfraChicken/codebuild_example
[Container] 2022/01/13 09:51:35 YAML location is /codebuild/output/src887441905/src/github.com/CloudInfraChicken/codebuild_example/buildspec.yml
[Container] 2022/01/13 09:51:35 Processing environment variables
[Container] 2022/01/13 09:51:35 Selecting 'python' runtime version '3.8' based on manual selections...
[Container] 2022/01/13 09:51:35 Running command echo "Installing Python version 3.8 ..."
Installing Python version 3.8 ...

[Container] 2022/01/13 09:51:35 Running command pyenv global  $PYTHON_38_VERSION

[Container] 2022/01/13 09:51:37 Moving to directory /codebuild/output/src887441905/src/github.com/CloudInfraChicken/codebuild_example
[Container] 2022/01/13 09:51:37 Configuring ssm agent with target id: codebuild:38f7c974-423f-4fc8-899b-41f3abba5960
[Container] 2022/01/13 09:51:37 Successfully updated ssm agent configuration
[Container] 2022/01/13 09:51:37 Registering with agent
[Container] 2022/01/13 09:51:37 Phases found in YAML: 4
[Container] 2022/01/13 09:51:37  INSTALL: 1 commands
[Container] 2022/01/13 09:51:37  PRE_BUILD: 1 commands
[Container] 2022/01/13 09:51:37  BUILD: 3 commands
[Container] 2022/01/13 09:51:37  POST_BUILD: 2 commands
[Container] 2022/01/13 09:51:37 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
[Container] 2022/01/13 09:51:37 Phase context status code:  Message: 
[Container] 2022/01/13 09:51:37 Entering phase INSTALL
[Container] 2022/01/13 09:51:37 Running command echo "install step"
install step

[Container] 2022/01/13 09:51:37 Phase complete: INSTALL State: SUCCEEDED
[Container] 2022/01/13 09:51:37 Phase context status code:  Message: 
[Container] 2022/01/13 09:51:37 Entering phase PRE_BUILD
[Container] 2022/01/13 09:51:37 Running command ls
README.md
buildspec.yml
test.txt

[Container] 2022/01/13 09:51:37 Phase complete: PRE_BUILD State: SUCCEEDED
[Container] 2022/01/13 09:51:37 Phase context status code:  Message: 
[Container] 2022/01/13 09:51:37 Entering phase BUILD
[Container] 2022/01/13 09:51:37 Running command zip -r test.zip .
  adding: test.txt (deflated 35%)
  adding: buildspec.yml (deflated 52%)
  adding: README.md (stored 0%)
  adding: .git/ (stored 0%)
  adding: .git/objects/ (stored 0%)
  adding: .git/objects/info/ (stored 0%)
  adding: .git/objects/pack/ (stored 0%)
  adding: .git/objects/pack/pack-20b2b078aae5cbe88977985ab9a272eefa9087af.idx (deflated 82%)
  adding: .git/objects/pack/pack-20b2b078aae5cbe88977985ab9a272eefa9087af.pack (stored 0%)
  adding: .git/index (deflated 31%)
  adding: .git/shallow (stored 0%)
  adding: .git/HEAD (stored 0%)
  adding: .git/config (deflated 13%)
  adding: .git/refs/ (stored 0%)
  adding: .git/refs/remotes/ (stored 0%)
  adding: .git/refs/remotes/origin/ (stored 0%)
  adding: .git/refs/remotes/origin/main (stored 0%)
  adding: .git/refs/heads/ (stored 0%)
  adding: .git/refs/heads/main (stored 0%)
  adding: .git/refs/tags/ (stored 0%)

[Container] 2022/01/13 09:51:37 Running command aws --version
aws-cli/1.20.58 Python/3.8.10 Linux/4.14.123-86.109.amzn1.x86_64 exec-env/AWS_ECS_EC2 botocore/1.21.58

[Container] 2022/01/13 09:51:38 Running command pwd
/codebuild/output/src887441905/src/github.com/CloudInfraChicken/codebuild_example

[Container] 2022/01/13 09:51:38 Phase complete: BUILD State: SUCCEEDED
[Container] 2022/01/13 09:51:38 Phase context status code:  Message: 
[Container] 2022/01/13 09:51:39 Entering phase POST_BUILD
[Container] 2022/01/13 09:51:39 Running command echo Post build step
Post build step

[Container] 2022/01/13 09:51:39 Running command ls
README.md
buildspec.yml
test.txt
test.zip

[Container] 2022/01/13 09:51:39 Phase complete: POST_BUILD State: SUCCEEDED
[Container] 2022/01/13 09:51:39 Phase context status code:  Message: 

As we can see CodeBuild first downloaded the repository, installed the python 3.8 runtime then moved on to the build phases; pre_build, build and post_build in that order.


Posted

in

, ,

by

Tags:

Comments

Leave a Reply