CI/CD using Github Actions
#
Set Up the PipelineOn Github, go to Actions
tab:
This tab is home to Github Actions.
GitHub Actions
GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform for your Github repository that allows you to automate your build, test, and deployment pipeline. You can create workflows (i.e., pipelines) that build and test every pull request to your repository, or deploy merged pull requests to production. GitHub provides Linux, Windows, and macOS virtual machines to run your workflows, or you can host your own self-hosted runners in your own data center or cloud infrastructure
This is where we will create our workflow (i.e., pipeline) file. Github Actions makes some workflow suggestions based on what language(s)/technologies our project source code uses; you will likely see something like this:
Select "Java With Gradle".
info
Each suggested workflow pre-populates your workflow-setup file with some relevant instructions but we are going to write our own workflow file anyway, so it does not really matter which workflow suggestion you choose.
This create a YAML file likely named gradle.yml
under .github/workflows/
path in the repo. This is where Github Action workflow config files are stored by default.
Now, copy & past the following content into the gradle.yml
file:
Don't you worry!
Even though the workflow file may look scary at first, once you understand what is in it, you will most likely find it pretty straightforward actually, so don't get scared by the look of them!
- Workflow Name and Trigger(s): This first part gives this workflow the name of "Java CI with Gradle" and the
on
command specifies that this workflow will run whenever either a newpush
orpull request
is made on themaster
branch ofci-helloworld
repo.
Next, we have the jobs that are part of this workflow. There are two main jobs namely "build_and_test" and "build_and_publish_docker_image":
- 2.1. "build_and_test": here, we first formulate how to build (compilation and packaging instructions) the project:
runs-n
specifies that the following commands will be run an ubuntu machine.2.1.a. "actions/checkout@v3": This is a popular "Action" that is used to checkout the latest version of the project code from the repo.
Actions & Marketplace
GitHub Marketplace is where you can share your apps and actions publicly with all GitHub users. GitHub Marketplace connects you to developers who want to extend and improve their GitHub workflows. You can list free and paid tools for developers to use in GitHub Marketplace. Anytime you want to accomplish a step in your workflow, chances are there is already an "Action" available through the Marketplac that you can just grab and use without the need to re-invent the wheel!
2.1.b. actions/setup-java@v3: This action facilitates compilation of the java project code which was checked out in the previous step. The Java version is set to 11 here.
2.1.c. "Setting Permissions":
chmod
linux command is used to make sure thegradlew
script is executable.2.1.d. build with gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1: Using this action, we build our Java gradle project. This has the same effect as running the command
gradlew build
.2.1.e. test with gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1: Next, we use the same action this time to run the tests. This step is the step that runs all the unit tests in the
ArrayUtilsTest.java
file. If any of the tests fail, the workflow is interrupted at this step and no further steps will be tried.All Tests Must Pass
This step effectively makes sure that in orde to get to the netx steps of this workflow, there must be NO failing test cases, hence preventing deploying/delivering "faulty" code into production stages.
2.1.f. "Run Test Coverage": This step runs the command
./gradlew jacocoTestReport
effectively running Jacoco to produce code coverage report(s).2.1.g. cicirello/jacoco-badge-generator@v2.9.0: With the help of this 'action', we can analyze the generated reports and set minimum required thresholds for different coverage criteria. In our case, we set
100%
branch coverage (BC) minimum requirement. If the test cases achieve anything less than100%
BC on the project source code, the integration/deployment workflow is interrupted.2.2 build_and_publish_docker_image: The overall goal in this job is to publish the code to Docker hub as a container image. We again choose to run the steps on latest version of
ubuntu
. We also specify that this job need successful execution & completion of thebuild_and_test
job.2.2.a. actions/checkout@v3: check out the latest version of the ci-helloworld source code.
2.2.b Login to Docker Hub: In order to create a container image and publish it to docker hub, we need to login using the command
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
:Github Secrets
Github secrets are encrypted environment variables that can be injected into your actions. A secret can not be seen once it have been created and they remain encrypted until they are used in a workflow. But even when they are used in a workflow they cannot be seen in the action logs since they are blurred out. They are thus suitable to be used to store sensitive information such as passwords and keys.
Create Github Secrets
First, if you do not have a docker hub account, go https://hub.docker.com/ and create one for free. Then, on Github, in the main page of your repo, go to
Settings
tab, then click onSecrets and variables
in the left menu:Next Click on
Actions
and using theNew repository secret
create three separate secrets:- DOCKER_PASSWORD with value of whatever your docker hub password is.
- DOCKER_USERNAME with value of whatever your docker hub username is.
- DOCKER_REPO with value of
docker_hub_user/ci-helloworld
wheredocker_hub_user
is your docker hub username.
Docker and Container Image
Docker is an open-source software designed to facilitate and simplify application development. It is a set of platform-as-a-service products that create isolated virtualized environments for building, deploying, and testing applications.
A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: source code, dependencies, libraries, runtime, system tools, system libraries and settings.2.2.c. Build Container image: This step builds the image using the docker command
docker build -t ${{ secrets.DOCKER_REPO }}:latest
where ${{ secrets.DOCKER_REPO }} is replaced by the secret's value you created in the previous step.:latest
gives a tagname to this image called "latest" (i.e., the latest build of the image)2.2.d. Publish Docker image: This is the very last step of the
build_and_publish_docker_image
job as well as the last step of the our entire workflow!YAYYYY!!! Congrats! You made it all the way to the end!