Foreword
In the last article we described the tests added to our project. These tests are useful to check our development locally as we use TDD. But they are also useful to check if there are regressions. In this post we will:
- define what the CICD is
- How to add the CICD settings to our project
What is the CICD
The acronym CICD stands for Continuous Integration Continuous Delivery. The acronym CICDCD stands for Continuous Integration Continuous Delivery Continuous Deployment
When we talk about CICD (or CICDCD) we often also refer to the pipelines. A CICD pipeline defines a process where certain steps are executed one after the other, all with the aim of building, and verifying the application before delivering it and deploying it.
What CICD tools
There are some tools to execute CICD; we can quote:
- Gitlab-ci
- CircleCI
- GitHub Action
- Jenkins
For open sources projects as our, it’s easier to use a CICD tool integrated into a web hosting and software development management service such as GitLab or GitHub. It’s why we prefer to use GitLab, CircleCi or GitHub Actions tools as Jenkins need a separate deployment, management and hardware resources.
We also want to use a free service, it is why we don’t use a Gitlab CI; because we can’t no longer push the report from Gitlab to Github withe the free plan.
In this post we will detail these solutions but we will implement only two of them:
- CircleCI
- GitHub Action
Implementation of our CICD
Our desired pipeline
Through our first pipeline we want to validate :
- build the application
- check if the code is formatted
- verify the non-regression of the code through the execution of test
Also we want the pipeline to be run on every commit to the develop branch and the ci branches (with prefix ci_). We could add other kind of branches: feature(feat_), fixes (fix_), documentation (doc_)
Implementation with CircleCI
First connection
CircleCI is a CICD platform which has a free plan; To be able to use CircleCI we need to:
-
Create an account
-
Set up our code
-
Configure
There are tree possibilities to link your project with your future CI:
Creation of a job
CircleCI defines “jobs” which are executables tasks; each job can be divided into steps In the first version of our CI (cf. code below) we want to:
- build the jar file
- run the unit tests
- run the integration tests
- run the system test
1# Java Gradle CircleCI 2.0 configuration file
2# See: https://circleci.com/docs/2.0/language-java/
3version: 2.1
4
5
6# Define a job to be invoked later in a workflow.
7# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
8jobs:
9assemble:
10# Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub.
11# See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor
12docker:
13# specify the version you desire here
14- image: cimg/openjdk:17.0.5
15
16 # Specify service dependencies here if necessary
17 # CircleCI maintains a library of pre-built images
18 # documented at https://circleci.com/docs/2.0/circleci-images/
19 # - image: circleci/postgres:9.4
20
21 working_directory: ~/happraisal
22
23 environment:
24 # Customize the JVM maximum heap limit
25 JVM_OPTS: -Xmx3200m
26 TERM: dumb
27 # Add steps to the job
28 # See: https://circleci.com/docs/2.0/configuration-reference/#steps
29 steps:
30 - checkout
31 - attach_workspace:
32 at: ~/happraisal
33
34 # Download and cache dependencies
35 - restore_cache:
36 keys:
37 - v1-dependencies-{{ checksum "build.gradle" }}
38 # fallback to using the latest cache if no exact match is found
39 - v1-dependencies-
40
41 - run: ./gradlew assemble
42
43 - save_cache:
44 paths:
45 - ~/.gradle
46 key: v1-dependencies-{{ checksum "build.gradle" }}
47 - persist_to_workspace:
48 root: ~/happraisal
49 paths:
50 - ./build
51 - store_artifacts:
52 path: ~/happraisal/build/libs
53
54unit-tests:
55docker:
56- image: cimg/openjdk:17.0.5
57
58 working_directory: ~/happraisal
59 steps:
60 - checkout
61 - restore_cache:
62 keys:
63 - v1-dependencies-{{ checksum "build.gradle" }}
64 # fallback to using the latest cache if no exact match is found
65 - v1-dependencies-
66 - run: ./gradlew test
67 - save_cache:
68 paths:
69 - ~/.gradle
70 key: v1-dependencies-{{ checksum "build.gradle" }}
71 - store_test_results:
72 path: ~/happraisal/build/test-results
73
74
75
76integration-tests:
77docker:
78- image: cimg/openjdk:17.0.5
79
80 working_directory: ~/happraisal
81 steps:
82 - checkout
83 - restore_cache:
84 keys:
85 - v1-dependencies-{{ checksum "build.gradle" }}
86 # fallback to using the latest cache if no exact match is found
87 - v1-dependencies-
88 - run: ./gradlew integrationTest
89 - save_cache:
90 paths:
91 - ~/.gradle
92 key: v1-dependencies-{{ checksum "build.gradle" }}
93
94
95system-tests:
96docker:
97- image: cimg/openjdk:17.0.5
98
99 working_directory: ~/happraisal
100 steps:
101 - checkout
102 - restore_cache:
103 keys:
104 - v1-dependencies-{{ checksum "build.gradle" }}
105 # fallback to using the latest cache if no exact match is found
106 - v1-dependencies-
107 - run: ./gradlew systemTest
108 - save_cache:
109 paths:
110 - ~/.gradle
111 key: v1-dependencies-{{ checksum "build.gradle" }}
112
113workflows:
114version: 2.1
115microservice:
116jobs:
117- assemble
118- unit-tests:
119requires:
120- assemble
121- integration-tests:
122requires:
123- assemble
124- system-tests:
125requires:
126- assemble
127
Implementation with GitHub Actions
Terminology
A Workflow: In the official documentation a workflow is defined as “a configurable automated process that will execute one or more jobs. It is set up via a yaml file. cf. https://docs.github.com/fr/actions/using-workflows/about-workflows
Action: “Actions are individual tasks that you can combine to create jobs and customize your workflow.” cf. https://docs.github.com/fr/actions/creating-actions/about-custom-actions
First connection
GitHub Actions is the CI tool of GitHUb. This CI is accessible from the Action button in a toolbar
During the first access, GithUb Actions displays a workflow proposal according to your project. In our case we have selected the java with gradle workflow.
Once we have selected our workflow, we are redirected to the editor proposing us a default file. It is possible to modify it and save it on a specific branch; In order to easily test the CICD without having to push on develop. It is possible to define the name of the working branch in the part push.
Creation of jobs
1on:
2 push:
3 branches:
4 - develop
5 - ci_*
To implement the 3 steps defined above, we need to create the jobs:
- assemble: to compile the code and create the jar.
- spotless: to check the format of new code.
- unit-tests: to execute the unit tests.
- integration-tests: to execute the integration tests.
- system-tests: to execute the system tests.
the code below shows an example of how to create a job
1jobs:
2 assemble:
3 runs-on: ubuntu-latest
4 steps:
5 - uses: actions/checkout@v3
6 - uses: actions/setup-java@v3
7 with:
8 java-version: '17'
9 distribution: 'temurin'
10 cache: gradle
11 - run: ./gradlew assemble --no-daemon
12
In the code above:
- we create the assemble job which is based on ubuntu-latest
- we use two actions to check the code and configure the Java compiler.
- we run the gradle assemble job.
Summary
The first objective of this article was to test three CICD engines (GitLab, CircleCi and GitHub Actions), implementing similar pipelines. While trying to implement the CICD on these engines, we quickly encountered some limitations for the first two CICD:
- pushing the report of the Gitlab CI to GitHub is not possible.
- on CircleCi the maximum available space for the artefacts and their retention time were not compatible with our objectives. https://app.circleci.com/settings/plan/github/talk-to-the-duck/overview?return-to=https%3A%2F%2Fapp.circleci.com%2Fprojects%2Fproject-dashboard%2Fgithub%2Ftalk-to-the-duck%2F In this case, only the GitHub action is completely useful.
As a conclusion I think that to set up a free CICD, it is preferable to use a CI integrated with its version manager such as GItHub Actions for GitHub or GitLab CICD for GitLab.
If you have any remarks on the content or the form, you can leave a comment…it is by exchanging that we progress.
Comments