In a previous blog post I went through the basics of what it takes to create a configuration for Cloud Build. This article will expand on it by creating a working CI / CD pipeline for a Java project using Cloud Build. Note that I’m claiming the pipeline will be functional but far from optimal, a follow-up post at some point will review potential pipeline optimizations.
The goal of continuous integration is to ensure that developers regularly merge quality code into a common place. Quality is checked using automation, which is where a tool like Cloud Build comes in during the CI process.
Consider a flow where developers work on feature branches and, when ready, send a pull request to the main branch.
Now, to ensure quality, checks must be made on the Developer Features branch before it is allowed to be merged into the “main” branch. This means two things:
1. Performing quality checks on the developer functionality branch
2. Mergers with the main branch should not be allowed until the checks have been performed.
Let’s start with point 1 – Perform quality checks on a feature branch
Performing quality checks on a feature branch
This is where the integration of Cloud Build with the repository comes in. i use this repository – https://github.com/bijukunjummen/hello-cloud-build, to demonstrate this integration with Cloud Build. If you have access to a Google Cloud environment, a new Cloud build build integration with a repository looks like this:
Once this integration is in place, a Cloud Build “trigger” must be created to act on a new extraction request to the repository:
This is where the Cloud Build configuration comes in, it specifies what should happen when a Pull Request is sent to the repository. This is a java based project with gradle as a build tool, I want to run some tests and other checks, which is normally done via a gradle task called ‘check’, a build setup that does this Is simple :
steps: - name: openjdk:11 id: test entrypoint: "./gradlew" args: [ "check" ]
On the next objective – Mergers with the main branch should not be allowed until the checks are cleared
Merge with the main branch only with a clean version
This is done on the repository side on github, via settings that look like this –
The settings protect the “main” branch by not allowing merges until the checks in the PR branch are cleaned up. It also prevents code from being checked directly into the main branch.
With these two considerations, checking the feature branch before mergers are allowed and allowing merges to the “main” branch after the checks should ensure that the quality code should go into the “main” branch.
On the side of the continuous deployment of the house.
So now, probably, some clean code has made its way to the main branch and we want to deploy it in an environment.
In Cloud Build, this translates to a “trigger”, which acts on commits to specific branches and looks like this to me:
steps: - name: openjdk:11 id: test entrypoint: "/bin/bash" args: - '-c' - |- ./gradlew check - name: openjdk:11 id: build-image entrypoint: "/bin/bash" args: - '-c' - |- ./gradlew jib --image=gcr.io/$PROJECT_ID/hello-cloud-build:$SHORT_SHA - name: 'gcr.io/cloud-builders/gcloud' id: deploy args: [ 'run', 'deploy', "--image=gcr.io/$PROJECT_ID/hello-cloud-build:$SHORT_SHA", '--platform=managed', '--project=$PROJECT_ID', '--region=us-central1', '--allow-unauthenticated', '--memory=256Mi', '--set-env-vars=SPRING_PROFILES_ACTIVE=gcp', 'hello-cloud-build' ]
Here i use Jib to create the image.
With that toolkit in place, a developer flow looks like this. A PR triggers checks and displays like this on the github side:
and once the checks are complete, allows you to merge the branch into:
After the merge, the code is deployed cleanly.