Continuous Deployment with anynines, github and Travis CI

A few words about continuous deployment

Continuous deployment is part of the continuous delivery paradigm. The basic idea of continuous delivery is to automate the software delivery process as far as possible. This includes automated testingcontinuous integration as well as continuous deployment.

Your continuous deployment benefits

With a working continuous deployment chain in place you gain the following benefits:

Git deployments
This prevents individual developers having uncommitted code.

Everything must be committed to be tested and everything must be tested to be deployed.

Easy to learn and use
As you will learn in this article continuous deployment is easy to setup. But more importantly, think of your growing team of developers. New team members have to learn how to use your CI and deployment process.

With a continuous deployment in place all they need to learn is to commit to a git repository.

Everybody can deploy
Many teams allow only certain members to deploy code. Why is that? Most likely either because of lacking trust within the team and/or because of complicated deployment procedures. You can get rid of both causes, easily by enforcing a CI along with an automated deployment.

Time savings
With the absence of a complicated deployment procedure you can re-focus on building your application.

Increased quality
By being integral parts of your development process automated testing, CI and continuous deployments guarantee intermediate notification of quality problems. Therefore, your team can clean up much faster!

Github, Travis CI and anynines

The combination of these three services allow to completely focus on product development. Operations of git, CI and PaaS environments is not your headache!

Being well integrated you can setup your continuous deployment toolchain within a few minutes and here is how…

How does it work?

Once you have set up continuous deployments all you have to care about is pushing your code into your github repository.

Your tests will be executed and succeeding commits will be deployed to your anynines account, automatically.

In order to make this happen only a few steps are necessary.

Getting started with continuous deployment on anynines

Assuming you have a local Ruby environment in place, the first thing you need is a simple app in a github repository.

In case you don’t have an app at hand, you can easily fork the anynines ruby-sinatra-example-app github repository.

For each major step described here you can find a corresponding git tag in the example repository, so you can switch to the corresponding code depending on where you are in this tutorial. For the app only – without any anynines and travis configuration, for example, refer to the 10-app-only tag.

Signup at anynines

You will need an anynines account to follow this tutorial. So sign up here. The trial is for free.

Installing the anynines gem

Now with an app at your hand, you can move forward and install the anynines gem.
gem install a9s
This will install the correct version of the cf gem required to interact with anynines.

Create a manifest.yml

Travis will later perform unattended deployments for you. Therefore, your app needs to contain some information about the deployment. Cloud Foundry, the technology used by anynines, stores this meta data in a yaml file called manifest.yml.

Creating a manifest.yml is easy. Just go to your local app directory and invoke
cf push
This will trigger a first deployment to anynines. The cf gem will notice that there is no manifest.yml and will ask you a standard set of configuration questions such as the desired number and memory size of your app instances, whether and which services to bind to them and most importantly, whether you want to store this information.
Please answer this question with yes as it will create the desired manifest.yml file.

Once your push was successful, you should be able to access your application using a browser of your choice which means your are ready to setup travis.

In case you have questions or trouble with the initial deployment, you can find further information on the anynines support page. If you want to talk to the anynines staff directly, feel free to visit our irc channel #anynines on irc.freenode.net.

Note: you can also checkout the app as it should look now by using the 20-manifest tag of our example repository.

Configuring Travis CI

Admittedly, our test app does not have real tests as this tutorial is not about testing but about continuous deployment. Therefore, you might want to have a look at the Travis CI documentation on how to set up your real world app to use travis.

For private repos checkout travis-ci.com.

For now we will create a travis configuration file that will fake a succeeding test suite. Please go to your local app directory and create a .travis.yml file. At the moment, paste the following content. We’ll add some more information, later using the travis gem.
language: ruby
script: 'true'

Note: you can also checkout the app as it should look now by using the 30-travis tag of our example repository.

Now your app contains the travis configuration but how should travis know when to pull your code from github and trigger test execution? This is where github hooks come into play.

Basically there are two ways to enable github hooks for travis.

The hard way:
Go to travis-ci.org > Accounts > Get your token; Go to github > Your repo > Settings > Hooks > Travis and paste your token there.

The easy way:
Go to travis-ci.org > Accounts > Repositories and the activate github travis hook by using the on/off switch the repository of your choice.

Travis CI Github Hook activation

Now you should be good to go with travis so we can test the continuous integration part of our setup. Just push a code change to your repository and check travis-ci.org to see if your test suite is being executed. You should also receive an email that your build succeeded.

Travis CI mail for a successful build

With a working CI in place we can now configure the actual deployment.

Setting up travis deployment to anynines

Now it is time to finish our setup by telling travis how to deploy to anynines. Again, there are potentially two ways to achieve this. You could either edit .travis.yml or go the easy way and use the travis gem.
gem install travis
Now use the travis command to setup the anynines deployment
travis setup cloudfoundry
In case you don’t know the anynines target URL use
cf target
to gather all information required for travis setup. This includes target url, username, the organization and space you are currently using. You can also look at the welcome mail you have received after signing up at anynines.com.

As of the time of this writing the anynines target URL is:
https://api.de.a9s.eu
After the travis command has finished, your .travis.yml could look like this:
language: ruby
script: 'true'
deploy:
provider: cloudfoundry
target: https://api.de.a9s.eu
username: john.doe@example.com
password:
secure: your encryped password determined by the travis gem=
organization: john_doe_example_com
space: hell
on:
repo: anynines/ruby-sinatra-example-app

Note: you can also checkout the app as it should look now by using the 40-travis-deploy tag of our example repository.

Don’t forget to commit and push your changes to .travis.yml as it will be required in your github repository to take effect.

From now on whenever you commit changes to your github repository, tests will be run and your app is being deployed.

Try it out!

Travis will then show log output similar to this:
Installing deploy dependencies
Fetching: addressable-2.3.5.gem (100%)
Successfully installed addressable-2.3.5
Fetching: multi_json-1.7.9.gem (100%)
Successfully installed multi_json-1.7.9
Fetching: caldecott-client-0.0.2.gem (100%)
Successfully installed caldecott-client-0.0.2
Fetching: i18n-0.6.5.gem (100%)
Successfully installed i18n-0.6.5
Fetching: tzinfo-0.3.37.gem (100%)
Successfully installed tzinfo-0.3.37
Fetching: minitest-4.7.5.gem (100%)
Successfully installed minitest-4.7.5
Fetching: atomic-1.1.13.gem (100%)
Building native extensions. This could take a while...
Successfully installed atomic-1.1.13
Fetching: thread_safe-0.1.2.gem (100%)
Successfully installed thread_safe-0.1.2
Fetching: activesupport-4.0.0.gem (100%)
Successfully installed activesupport-4.0.0
Fetching: builder-3.1.4.gem (100%)
Successfully installed builder-3.1.4
Fetching: activemodel-4.0.0.gem (100%)
Successfully installed activemodel-4.0.0
Fetching: cf-uaa-lib-2.0.0.gem (100%)
Successfully installed cf-uaa-lib-2.0.0
Fetching: multipart-post-1.2.0.gem (100%)
Successfully installed multipart-post-1.2.0
Fetching: rubyzip-0.9.9.gem (100%)
Successfully installed rubyzip-0.9.9
Fetching: cfoundry-4.3.6.gem (100%)
Successfully installed cfoundry-4.3.6
Fetching: interact-0.5.2.gem (100%)
Successfully installed interact-0.5.2
Fetching: json_pure-1.8.0.gem (100%)
Successfully installed json_pure-1.8.0
Fetching: mothership-0.5.1.gem (100%)
Successfully installed mothership-0.5.1
Fetching: mime-types-1.25.gem (100%)
Successfully installed mime-types-1.25
Fetching: rest-client-1.6.7.gem (100%)
Successfully installed rest-client-1.6.7
Fetching: uuidtools-2.1.4.gem (100%)
Successfully installed uuidtools-2.1.4
Fetching: cf-5.2.2.gem (100%)
Successfully installed cf-5.2.2
22 gems installed
dpl.2
Preparing deploy
Setting target to https://api.de.a9s.eu...... OK
target: https://api.de.a9s.eu
Authenticating.. . ... OK
Switching to organization john_doe_example_com... OK
Switching to space hell... OK
dpl.3
Deploying application
Using manifest file manifest.yml
Uploading ruby-sinatra-example-app... OK
Stopping ruby-sinatra-example-app... OK
Preparing to start ruby-sinatra-example-app... OK
Checking status of app 'ruby-sinatra-example-app'...
0 of 1 instances running (1 starting)
0 of 1 instances running (1 starting)
1 of 1 instances running (1 running)
Push successful! App 'ruby-sinatra-example-app' available at http://ruby-sinatra-example-app.de.a9sapp.eu
Logging out... OK

This means your are done and good to go! Have fun with continuous deployment.

Trouble Shooting

In the (unlikely :-) event you encounter any trouble you can always use cf commands such as
cf logs
To gather information about the last deployment.

It’s also helpful to check whether a push from your local filesystem works fine, to ensure you are not searching errors in the wrong place.

Especially errors during the initialization process of your app can be cumbersome. For Ruby on Rails apps check your asset settings.

Feel free to refer to the anynines support to get help. Feel free to visit our irc channel #anynines on irc.freenode.net. We are happy to receive your feedback.