- Fully managed build service
- Alternative to other build tools such as Jenkins
- Continuous scaling (no servers to manage or provision – no build queue)
- Pay for usage: the time it takes to complete the builds
- Leverages Docker under the hood for reproducible builds
- Possibility to extend capabilities leveraging our own base Docker images
- Secure: Integration with KMS for encryption of build artifacts, IAM for build
permissions, and VPC for network security, CloudTrail for API calls logging - Source Code from GitHub / CodeCommit / CodePipeline / S3…
- Build instructions can be defined in code (
buildspec.yml
file) - Output logs to Amazon S3 & AWS CloudWatch Logs
- Metrics to monitor CodeBuild statistics
- Use CloudWatch Events to detect failed builds and trigger notifications
- Use CloudWatch Alarms to notify if you need “thresholds” for failures
- CloudWatch Events / AWS Lambda as a Glue
- SNS notifications
First build
In CodeCommit we have index.html
file with “congratulations” word. We will test whether or not the index.html
file has this word. To create a build:
CodeBuild -> Create build project -> ProjectName (MyWebAppCodeBuildMaster) -> Source provider (AWS CodeCommit) -> Repositorry (my-webpage) -> Reference type (Branch) -> Branch (master) -> Environment -> Environment image (Managed image) -> Operating system (Amazon Linux 2) -> Runtime (standard) -> Image (****-standard 1.0) -> Service Role (New service role) -> Role name (codebuild->MyWebAppCodeBuild-service-role) -> Build specifications -> Use a buildspec file -> Create build project
Because in CodeCommit we have buildspec.yml
file we don’t need to fill Buildspec section.
Now we should start a build:
Start build
->
Build will use docker container and buildspecfile.yml
from CodeCommit my-webpage repository.
We can click View entire log
to view the entire log in cloudwatch.
Buildspec.yml file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
version: 0.2 phases: install: runtime-versions: nodejs: 10 commands: - echo "installing something" pre_build: commands: - echo "we are in the pre build phase" build: commands: - echo "we are in the build block" - echo "we will run some tests" - grep -Fq "Congratulations" index.html post_build: commands: - echo "we are in the post build phase" |
This buildspec.yml check if in the index.html file is “Congratulations” word.
We can change this word in the index.html file and Commit changes:
CodeCommit -> Repositories -> my-webpage -> index.html -> Edit -> Author name -> Commit changes
and then:
Developer Tools -> CodeBuild -> Build projects -> MyWebAppCodeBuildMaster -> Start build
And the build will fail:
Docker
To use docker images we can use buildspec.yml
file from refenrences sample:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
version: 0.2 phases: pre_build: commands: - echo Logging in to Amazon ECR... - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com build: commands: - echo Build started on `date` - echo Building the Docker image... - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG . - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG post_build: commands: - echo Build completed on `date` - echo Pushing the Docker image... - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG |
Environment variables & Parameter Store
Let’s modify our first simple buildspec.yml
file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
version: 0.2 phases: install: runtime-versions: nodejs: 10 commands: - printenv - echo "installing something" pre_build: commands: - echo "we are in the pre build phase" build: commands: - echo "we are in the build block" - echo "we will run some tests" - grep -Fq "Congratulations" index.html post_build: commands: - echo "we are in the post build phase" |
Next we must commit changes in
CodeCommit -> author name -> Email address -> Commit changes
And also we must change index.html file and put Congratulations word in:
Next we must commit changes in
CodeCommit -> author name -> Email address -> Commit changes
Then in CodeBuild we must build the project again.
After this changes all the environment variables should be printed:
We can change the environment variables directly in the buuildspec.yml file
1 2 3 4 5 6 7 8 9 10 11 |
env: shell: shell-tag variables: key: "value" key: "value" parameter-store: key: "value" key: "value" exported-variables: -variable -variable |
or directly in the console wile lounching buil project:
Build project with overrides ->
But variables changed in the buildpec.yml file and in console will be visible.
If we want to have unvisible variable we should use Parameter Store.
Create Paremeter
Now in console we use:
To use parameters from Parameter Store a role codebuild-MyWebAppCodeBuild-service-role
should have attached AmazonSSMReadOnlyAccess
.
After build the project we can’t see the DB_PASSWORD variable in the log:
Artifacts and S3
Artifact is the build output. Let’s modify the buildspec file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
version: 0.2 phases: install: runtime-versions: nodejs: 10 commands: - printenv - echo "installing something" pre_build: commands: - echo "we are in the pre build phase" build: commands: - echo "we are in the build block" - echo "we will run some tests" - grep -Fq "Congratulations" index.html post_build: commands: - echo "we are in the post build phase" artifacts: files: - '**/*' name: my-webapp-artifacts |
and commit changes in CodeCommit.
First we need to create a bucket for artifacts:
If we want we can use default encryption for this bucket or encrypt the artifacts after the build proces.
Now edit the artifacts section in CodeBuild project:
Developer Tools -> CodeBuild -> Build projects -> MyWebAppCodeBuildMaster -> Edit Artifacts
As we see the CodeBuild will create a role to access to the S3 bucket.
Now we can run the build project. After building we see in the log that artifacts were succesfully upploaded to the cicd-miro-devops bucket:
S3 bucket:
CloudWatch Events & CloudWatch Logs
If we want to run build project in the sheduled way we can use CloudWatch Events:
Cloudwatch -> Events -> Rules -> Create rule
Project ARN we can take from Build details:
Configure details ->
Create rule ->
Also we can configure CloudWatch Events to react if something happen while build is runing, for example build has been failed or state changed:
Validating AWS CodeCommit Pull Requests
We can validate CodeCommit pull request by sing CloudWatch Events, CodeBuild and Lembda. There is great article abut it at AWS DevOps Blog:
References
- https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html
- https://docs.aws.amazon.com/codebuild/latest/userguide/samples.html
- https://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html
- https://aws.amazon.com/blogs/devops/validating-aws-codecommit-pull-requests-with-aws-codebuild-and-aws-lambda/
- https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html