Published at 09.09.2013
Table of Contents
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 testing, continuous integration as well as continuous deployment.
With a working continuous deployment chain in place you gain the following benefits:
**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.
**With the absence of a complicated deployment procedure you can re-focus on building your application.
**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!
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…
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.
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.
You will need an anynines account to follow this tutorial. So sign up here. The trial is for free.
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.
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
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.
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.
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.
With a working CI in place we can now configure the actual deployment.
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
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:
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: firstname.lastname@example.org 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) <strong>Push successful</strong>! App 'ruby-sinatra-example-app' available at https://ruby-sinatra-example-app.de.a9sapp.eu Logging out... OK
This means your are done and good to go! Have fun with continuous deployment.
In the (unlikely :-) event you encounter any trouble you can always use cf commands such as
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.