In current pace of web technology, the quick response time and low downtime are the core goals of any project. To achieve a continuous deployment scheme the most important factor is how efficiently contributors and maintainers are able to test and deploy the code with every PR. We faced this question when we started building loklak search.
As Loklak Search is a data driven client side web app, GitHub pages is the simplest way to set it up. At FOSSASIA apps are developed by many developers working together on different features. This makes it more important to have a unified flow of control and simple integration with GitHub pages as continuous deployment pipeline.
So the broad concept of continuous deployment boils down to three basic requirements
- Automatic unit testing.
- The automatic build of the applications on the successful merge of PR and deployment on the gh-pages branch.
- Easy provision of demo links for the developers to test and share the features they are working on before the PR is actually merged.
Automatic Unit Testing
At Loklak Search we use karma unit tests. For loklak search, we get the major help from angular/cli which helps in running of unit tests. The main part of the unit testing is TravisCI which is used as the CI solution. All these things are pretty easy to set up and use.
Travis CI has a particular advantage which is the ability to run custom shell scripts at different stages of the build process, and we use this capability for our Continuous Deployment.
Automatic Builds of PR’s and Deploy on Merge
This is the main requirement of the our CD scheme, and we do so by setting up a shell script. This file is deploy.sh in the project repository root.
There are few critical sections of the deploy script. The script starts with the initialisation instructions which set up the appropriate variables and also decrypts the ssh key which travis uses for pushing the repo on gh-pages branch (we will set up this key later).
- Here we also check that we run our deploy script only when the build is for Master Branch and we do this by early exiting from the script if it is not so.
- We also store important information regarding the deploy keys which are generated manually and are encrypted using travis.
- We clone our repo from GitHub and then go to the Target Branch which is gh-pages in our case.
- Now we do a clean up of our directory here, we do this so that fresh build is done every time, here we protect our files which are static and are not generated by the build process. These are CNAME and 404.html
- After checking out to our Master Branch we do an npm install to install all our dependencies here and then do our project build. Then we move our files generated by the ng build to our gh-pages branch, and then we make a commit, to this branch.
- Now the final step is to push our build files to gh-pages branch and as we only want to put the build there if the code has actually changed, we make sure by adding that check.
Now this 70 lines of code handle all our heavy lifting and automates a large part of our CD. This makes sure that no incorrect builds are entering the gh-pages branch and also enabling smoother experience for both developers and maintainers.
The important aspect of this script is ability to make sure Travis is able to push to gh-pages. This requires the proper setup of Keys, and it definitely is the trickiest part the whole setup.
- The first step is to generate the SSH key. This is done easily using terminal and ssh-keygen.
- I would recommend not using any passphrase as it will then be required by Travis and thus will be tricky to setup.
- Now, this generates the RSA public/private key pair.
- We now add this public deploy key to the settings of the repository.
- After setting up the public key on GitHub we give the private key to Travis so that Travis is able to push on GitHub.
- For doing this we use the Travis Client, this helps to encrypt the key properly and send the key and iv to the travis. Which then using these values is able to decrypt the private key.
- Make sure to add deploy_key.enc to git repository and not to add deploy_key to git.
And after all these steps everything is done our client-side web application will deploy on every push on the master branch.
These steps are required only one time in project life cycle. At loklak search, we haven’t touched the deploy.sh since it was written, it’s a simple script but it does all the work of Continuous Deployment we want to achieve.
Generation of Demo Links and Test Deployments
This is also an essential part of the continuous agile development that developers are able to share what they have built and the maintainers to review those features and fixes. This becomes difficult in a web application as the fixes and features are more often than not visual and attaching screenshots with every PR become the hassle. If the developers are able to deploy their changes on their gh-pages and share the demo links with the PR then it’s a big win for development at a faster pace.
Now, this step is highly specific for Angular projects while there are are similar approaches for React and other frameworks as well, if not we can build the page easily and push our changes to gh-pages of our fork.
We use @angular/cli for building project then use angular-cli-ghpages npm package to actually push to gh-pages branch of the fork. These commands are combined and are provided as node command npm run deploy. And this makes our CD scheme complete.
Clearly, the continuous deployment scheme has a lot of advantages over the other methods especially in the client side web apps where there are a lot of PR’s. This essentially eliminates all the deployment hassles in a simple way that any deployment doesn’t require any manual interventions. The developers can simply concentrate on coding the application and maintainers can just simply review the PR’s by seeing the demo links and then merge when they feel like the PR is in good shape and the deployment is done all by the Shell Script without requiring the commands from a developer or a maintainer.
Loklak Search GitHub Repository: https://github.com/fossasia/loklak_search
Loklak Search Application: http://loklak.net/
Loklak Search TravisCI: https://travis-ci.org/fossasia/loklak_search/