Intro

Firstly, I’d say the Teammates assignment in this semester is one of the worst coding experiences I have ever experienced. It is a bad practice for learning Google App Engine or Java EE related stuff.  Why? Have a look at these:

wow, such looooooooooooooonnnng class name, much java, very enterprise…
110 map() calls in teammates.ui.controller.ActionFactory?! 

(There are about 100 calls in the original project, we’ve added another 10. We don’t have time to refactor these stuff so we just followed they have done before.)
and that’s what I feel…

Anyway, let’s forget about the code.  This is a quick note for what I did recently. I have managed to add continuous integration and continuous delivery configurations into Teammates with Travis CI. When a commit is submitted, Travis CI will pull and compile our code, test it and deploy it to Google App Engine.

Travis CI & CI tests

The original Teammates comes with a working Travis CI configuration. We have modified a little bit to make it works.

Here is the original configuration: https://github.com/TEAMMATES/teammates/blob/master/.travis.yml

Don’t forget there are some separated unit tests and integration tests in the CI scripts and it is DIFFERENT from the local tests!!

In order to make it works for us, we need to make some changes:

  • Some original unit tests and integration tests cannot work correctly. I have fixed 600+ tests and made it works again. But there are still 29 left we couldn’t fix, which are mainly caused by frontend changes. Teammates’ tests use some hard-coded HTML files and compare the HTML generated/rendered from Teammates server. We have to write a script and crawl all the new web pages down, or manually do the job on our own, which is even more impossible. Later our tutors noticed us that we are not required to fix that as it is way too time-consuming. So we just simply disabled them as required.
  • Remove the Codecov in the Travis configuration (i.e. the bash <(curl -s https://codecov.io/bash)). It is not free for private repos, and we don’t need that according to our assignment spec. Most importantly, I’m not a crazy rich Asian and same as my friends in the group. So, we just removed it.
  • Some linting issues need to be fixed
Yay now it works…

Deployment & Continuous Delivery

On the local side, we just need to follow the instructions provided by our tutors and run appengineDeployAll Gradle task. It should work fine as we expected. But for the Travis CI side, it is a bit more complex than I thought. For some reasons, Travis CI’s GAE deployment function doesn’t work for Teammates. But we can do it by our custom script instead.

Here I assume the Travis CLI tool is installed and logged in. Follow this link for more info.

Firstly, we need to create a service account configuration from Google Cloud Console:

Download the JSON file and put in under the root of Teammate source directory

Then, pack the scripts and encrypt the archive. This requires a macOS or Linux environment as Travis CI’s CLI client cannot encrypt the file properly on Windows. According to Travis, if you are a victim of Windows, please consider upgrading to Windows 10 and use WSL. I guess msys2 or Cygwin environment should also work, but I haven’t tried it yet.

Open the terminal and do this:

~$ cd ~/wherever-your-teammate-source-is/
~$ tar Jcvf secrets.tar.xz src/main/resources/build.properties src/main/webapp/WEB-INF/appengine-web.xml gae.json
~$ travis encrypt-file secrets.tar.xz
Yes I am a bit too lazy to switch back to Ubuntu, so I’m also a victim of Windows.

After the archive is encrypted, remember to add the original files into .gitignore, especially for the service account configuration. Otherwise some days later you may get bankrupted.

Then create a Bash script for deployment, like this:

#!/bin/bash

# Decrypt config & key files
openssl aes-256-cbc -K $encrypted_*******_key -iv $encrypted_******_iv -in secrets.tar.xz.enc -out secrets.tar.xz -d
tar xvf ./secrets.tar.xz

# Clean up browser path
rm -rf firefox/

# Authorise GCloud SDK
gcloud auth activate-service-account [email protected] --key-file=gae.json --project=your-project-name

# Run Gradle deployment task
./gradlew appengineDeployAll

Now everything is done except for the Travis configuration. Just add a deploy section at the end of the configuration file:

deploy:
  provider: script
  script: bash deploy.sh
  on:
    branch: master

Here we only deploy our app for master branch, not for other buggy branches.