For our CI (Continuous Integration), we are using Jenkins.

📝 NOTE: The details of this document will soon change to reflect the change in our concrete testing. Moving focus away from unit tests and more onto integration testing and E2E testing. In particular, there will be fewer test targets and the testing infrastructure required by Jenkins will be more complex. The overall gist of this document still remains true.

Automated Building and Testing

Our Jenkins Pipeline is triggered when new code is pushed to the master branch of our git repository. Just to be certain that we don’t miss pushes, we also have Jenkins check each 5 min for changes to the master branch. If there have been pushed new code to the repository it triggers our “Build and Test” job. For this job we make use of scripted Jenkinsfiles. In the base folder of the UCloud project you will find a Jenkinsfile that bootstraps the job. Each service also have a Jenkinsfile in their base folder. When the bootstrapping Jenkinsfile is run, it finds all services belonging to the project and loads (and executes) the Jenkinsfile for each service and saves the result for each build.

The Jenkinsfile in each service consists of a build stage and a test stage. If the build stage should fail it returns FAILURE. If the test stage fails, it returns UNSTABLE. If everything is fine and the build and test both are success it returns SUCCESS. All test results are automatically saved and gathered in the Jenkins job. Since all tests and builds are independent of each are we able to run them in parallel, reducing the time from commit to notification drastically.

Once all services has been build and tested we check to see if any had failed. If not, then the job is done and Jenkins marks it as being a SUCCESS. It also publishes the code coverage report generated by Jacoco If however 1 or more services has been marked as FAILURE or UNSTABLE, then the job is marked as FAILED and a message is sent to our Slack channel #devalerts specifying which services are to blame.

Jenkins Flow Chart

“Automated” Build of Docker Images

We also have the possibility to create Docker images for all our services. This is never triggered automatically when the master branch is updated, but have to be initialized manually. This is a scripted job that pulls from our git repository and locates all service directories. For each service/directory it loads the JenkinsBuildDockerFile that are found in each services base folder. We have chosen that the build of Docker images should not be triggered automatically since we rarely need all services to have their Docker image created. Usually we do this manually for a specific service when it have been patched.

Future enhancements

  • Code coverage requirements At the current moment we do run code coverage when we do the unit tests. It is possible to mark a job as unstable if the code coverage is below a certain level. This could help enforce that new code is also tested properly.

  • Detekt requirements As part of the build stage we also run detekt. It is possible to make a build fail if detekt returns a certain number of violation. This could help enforce specific code style and insure code documentation.

  • Dependency of other Jobs Make the construction of Docker images dependent on last “Build and Test” job. Only allow if last “Build and Test” job was success.