Continuous Deployment and a JHipster Restart

hipsterMy current technical goal is to have cyclic development, testing, and deployment of a JHipster/Spring Boot application. I’ve managed to get the development, testing, and deployment of the application archive to the production server, however I now need to call a script as gitlab-runner user and have that script restart the application properly. I think the way is to create a script that will run as root without requiring a password such as the use of sudo. My gitlab-runner user uses SSH (without a password) to connect to the production server, however any root-related tasks require sudo and even though the user is into the box, he must provide a password for the sudo session.

Overview

I’m going to describe the production environment and then I’ll elaborate on the solution I want to describe here. The application being developed is a Spring Boot executable WAR. This file is created with the following Maven command:

A WAR file is created in the target/ directory. Using a Gitlab Pipeline I wanted to compile, test, and package the WAR archive on the GitLab server and then deploy the archive to the production server. Before the archive is copied (scp) to the production server, I needed to stop the running WAR. So, I’ll stop the application, copy the new deployment, and then start the application and exit. The stop and start commands were put into shell scripts. These scripts will call the following commands before and after the SCP copy of the new deployment.

The stop and start commands are found in two separate shell scripts. After the stop command, sleep 10 is added to pause the script to allow for a clean shutdown prior to copying the new deployment over the running WAR. I want to explain now how the gitlab-runner user does all this automatically when I commit a change to the GIT repo within GitLab.

The GitLab Pipeline

A GitLab pipeline is an executable process that can be triggered with a new commit to a branch in your Git repository. In my case, I want a pipeline to be executed when I commit to my project. The beautiful aspect of the pipeline is its configurability. Modern agile software projects, in an effort to make people awesome, deliver value continuously, make safety a prerequisite, and experiment/learn rapidly, do so by supporting fast failure and welcoming feedback. The GitLab pipeline process is defined by you. The pipeline is the vehicle and you are the architect. And, if the pipeline is in place to be triggered by our development workflow, the pipeline executables (process stages) define this “continuous” term that seems to be the new buzzword. It’s really not because continuous integration (or automatic builds with feedback) was first formally written we think by Grady Booch, Chief Scientist at IBM. My goal here is not to show you how to setup a pipeline or gitlab-runner, but to show you that today CI/CD is much more than build and notify.

The pipeline for my project is defined in a file called .gitlab-ci.yml. Here’s a copy of that file.

There are 3 stages, build, package, and deploy. Maven will build and package my project and then I use shell commands within a script: (YAML) tag to call a shell script to stop the running production WAR, then SCP the new WAR over to the production server, and then run a second script to start the application again.

This looks easy but it wasn’t. I still love how Linux makes things difficult in the name of good security practice. My GitLab pipeline runs as a Linux system user called gitlab-runner. I created this user with sudo rights on my production server. I ended up using sudo on the production machine but also modifying /etc/sudoers to allow any sudo user to run my start and stop scripts without password across SSH. I also SCP the new WAR into a directory owned by the gitlab-runner user. The start script first copies the WAR from that directory into one owned by root. Also, because root is running the start script, the copy means that root owns the file in the final directory.

Here are the scripts that are called in the GitLab pipeline in the order that they are called.

After the SCP of the new WAR, I call the start script to start the application again.

Conclusion

I created the application wisehealth for my parents to record their health data, weight, blood pressure, and blood sugar. It also allows each user to record their prescriptions or medicines. I’ll add reports soon so they can print listings of data for their doctor visits. What’s great about this is that I quickly stood up an enterprise-ready Spring Boot application and secured it. I used Digital Ocean for the hosting. I installed a LetsEncrypt valid HTTPS certificate. I taught my mom how to use the app last night on the speakerphone and my step-father created his account on his iPad. By the time I was done, they realized that this application can be accessed on an iPhone or Android too. The beauty of this entire exercise is that I can make a change to a production-ready JHipster application in my IntelliJ IDE, check in and my users can see the “continuous” improvement in their application. CI/CD baby!

If anyone wants to check out the application, please register an account at https://health.ciwise.com and take a look. I did the application in about 4 hours. It’s not pretty but JHipster is comparable to Rails Composer. Maybe Rails Composer copied JHipster. I’m not sure, but I sure like it!

P.S. Anyone should be able to access the public source code at https://devops.ciwise.com/ciwise/wise-health/ . I’m currently working on an open source site https://ciwise.org . Let me know if you can’t see or clone the code because I’ve only recently opened this project only.

Leave a Reply

Wow, 554 people read this.