Continuous Delivery for Java, using CircleCI and Manageacloud

I am a developer, not a sysadmin, not a devops, still one needs to understand the basics of server configurations in order to ensure that his job will work fine, so the terrible "it works in my machine" situation does not happen often.

If there is something any developer knows how to do is automation: we are use to create small programs to prevent tedious manual processes. This post shows how to unleash the power of CI with Manageacloud. In this example I will be working with a simple java application, the java-demo of manageacloud.

The target of this post is to provide easy CI integration into a java project, which generates a deployment to a new server every time code is pushed into Git, as long as the unit tests pass (because you use unit tests, right?). The unit tests runs in CircleCI, which is a free web-based integration server very convenient for this example. 

This article assumes you have read the quickstart guide and that you have installed the manageacloud mac command line interface.

Setting up CircleCI

There are essentially 2 things we need to do here

  1. Provide a correct circle.yml configuration file
  2. Launch a manageacloud trigger upon artifact build

So lets start with the circle.yml file, lets check how the file looks like

        version: openjdk7
        - "target/java-demo.war"
        - mvn clean install
        - curl \-\-data "APP_VERSION=${CIRCLE_BUILD_NUM}"

As you can see, there is nothing too weird here, the relevant parts are the one indicating that the final artifact will end up in "target/java-demo.war" and then we also have a curl command that invokes a certain url. Let me explain that a little bit: Manageacloud provides "triggers" a trigger is simply a URL that when invoked with a HTTP POST method will trigger the creation of an infraestructure (that is, a set of servers, fully configuring them) and will automatically deploy the war artifact provided in the example (in this case, the one located at "target/java-demo.war").

Please pay attention to the teardown section, there we are invoking a manageacloud trigger, we will explore that in a moment, just keep in mind that we will need to come back to the circle.yml file at the end.

To summarize, now every time a build successfully completes in circleci for your project, it will launch a trigger against manageacloud, at the same time, we will also tell manageacloud that everything is ready to deploy.

Setting up Manageacloud

Now we have CircleCI properly configured, we will configure our manageacloud settings.

There is a configuration that you can reuse here, however I strongly recommend you to follow the steps in order to understand what is going on behing the scenes.

Sign in into manageacloud, click on "server configurations" tab, and then on "New Server Configuration", in the next screen you need to provide a name for your configuration, lets use "my-ci", click on continue, now it is time to determine which technology we will use to create our server, as I said, I am not a sysadmin nor devops, so I will simply use the shell, after that, you will need to select the OS version, pick "Debian Jessie 8", after that you will be presented with some repositories (in case you have used manageacloud before), click on "skip repository", finally a screen were you can put your bash config will appear:

So, in that configuration we are going essentially to:

  1. Install java
  2. Install an application server (in this case tomcat)
  3. Access circleci to get the proper war file
  4. Deploy that war file into the application server

The configuration will looks like this

set -x # enable debug
set -e
# Install basic stack and tools
apt-get update
apt-get install -y -q curl
apt-get install tomcat7 -y -q

# Stop tomcat, to make sure everything starts clean
/etc/init.d/tomcat7 stop
# Get the latest build of circleci

curl -sS -o java-demo.war$APP_VERSION/artifacts/0/home/ubuntu/java-demo/target/java-demo.war
rm -rf /var/lib/tomcat7/webapps/*
cp java-demo.war /var/lib/tomcat7/webapps/ROOT.war

# And restart :)
/etc/init.d/tomcat7 start

Ok, click on "Save & Finalize" now, then click on the "Home" link at the top-left area, and then on the "triggers" tab. And lets create a new trigger, we will call it "ci-trigger", the contents should be this

set -e # abort at any return code != 0


mac instance create -c my-ci -l lon1 -e APP_VERSION=$APP_VERSION

Once you have saved your trigger, you will be returned to the list of all your triggers, click on the "ci-trigger" one and a window like this will be presented to you

Now, that URL that you see is the one that we mentioned on the circle.yml file before, remember?

    version: openjdk7
    - "target/java-demo.war"
    - mvn clean install
    branch: feature/moriano
      - curl \-\-data "APP_VERSION=${CIRCLE_BUILD_NUM}"

Now you will know which one is your trigger hash, so just modify your circle.yml file to reflect the trigger.

Testing everything

Now, every time a circleci build occurrs and it passes all the tests, a trigger will be launched against manageacloud which will create a new linux server containing a tomcat and the very last version of your java code. In addition to that, it is also possible to lick your git account to circleci so that it automatically triggers a build into circleci for every push you do (this can also be done on a per-branch basis).

As an example, I will made a small change into the code, then I will push it and we will see how everything goes.

First, lets see that I have no manageacloud instances running

$ mac instance list
There is no active instances

Now, lets make a git push

$ git push

Counting objects: 64, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (37/37), done.
Writing objects: 100% (51/51), 3.78 KiB | 0 bytes/s, done.
Total 51 (delta 14), reused 0 (delta 0)
   cbf7eab..a7765db  feature/moriano -> feature/moriano

At this point CircleCI will be building the new code and will call Manageacloud to trigger its config

$ mac instance list
| Instance name    | IP  |        Instance ID         |   Type  |       Status      |
|                  |     | d5o6i1fvjqvpd4n7lm7bsrhiab | testing | Creating instance |

And if we wait a bit (1-2 minutes)... we will get our manageacloud instance ready for action!

$ mac instance list
| Instance name  |       IP            |          Instance ID            |   Type  | Status |
|    mct-17e     |      | d5o6i1fvjqvpd4n7lm7bsrhiab      | testing | Ready  |

And that is! this is a simple example of how to unleash the power of continuous delivery with Git + circleci + Manageacloud, note that also here we are creating a new server every time we deploy, meaning that the environment in which the code is deployed is clean, that will get rid forever of the "it works in my machine" problem.

Written by Juan Antonio Gomez Moriano on Monday November 30, 2015
Permalink - Tags: continuous_delivery, continutous_deployment, java, continuous_integration, cd, ci - Category: devops

« Understanding the Manageacloud Systems and Environment - Working safely with the AWS Command Line tool »