I’ve been building a little home project for the past couple of months, just to experiment with programming languages and frameworks. During this time I managed to put together a simple continuous delivery pipeline, completely automated and free of charge. In the following paragraphs I’ll describe how I, in my next home project should connect those pieces of puzzles together. Maybe it will be useful for others as well.
To be more precise, the interaction of the following systems will be detailed:
- Source code management: GitHub
- Artifacts repository: JFrog Bintray
- Continuous integration server: Codeship
- Deployment: Heroku
Source code management
Some people argue that a simple home project does not need online source code management. I could not disagree more; a few weeks back my laptop got stolen with lots of source code not pushed to any online repository. I had to start over, so I guess git best practices apply to pet projects as well.
Github.com is the obvious choice here. GitHub is awesome, but unfortunately private repositories are not free. So in case the repository contains the next billion dollar idea, BitBucket.org can be used instead. BitBucket hosts private repos for free, and further pieces down the pipeline are compatible with it as well (I think… The options are there for BitBucket, but I’ve not tested it thoroughly).
There’s really no configuration required here, pick either one and we can move to the next step.
Many free artifact repository tools need to be installed on some kind of server, which makes them of little use when it comes to home projects. I found two for free, hosted versions, one is Mymavenrepo.com, the other is JFrog Bintray.
Mymavenrepo is free, but it only gives you 250MB of space, and according to their FAQ, it is planned to become a payed service once they’re not in beta anymore. Until then, it can be useful for really simple projects.
At Bintray, they offer a free, “trial” version. I’ve been using it for a while, but it looks like “trial” does not mean a number of days you can use the service, but rather a limited number of accessible features. Indeed, Bintray is not as advanced as Artifactory, but since we are talking about personal projects here, it is not expected that one has to deal with a very high number of dependencies and versions. If you just want to publish and resolve artifacts, Bintray is perfect.
You just have to (manually) create a repository, select which deployment tool you’ll be using (maven, rpm, etc.) and then pretty much you are all done. Even simpler, you can import GitHub repositories directly. You’ll instantly get a ‘Set me up’ icon, clicking it you’ll get all the instructions you will need in your pom.xml (in case you picked Maven, of course).
JFrog Bintray is only meant to manage released artifacts, so if you need to store SNAPSHOT dependencies as well, some other tools will be needed.
Continuous Integration Server
There are quite some products out there, accessible for free, but the best one I’ve come across is Codeship.com. The reason I like Codeship is that it is pretty easy to use. It can run tests just like my regular desktop computer, you don’t have to worry about hosts and ports. My project runs an embedded web server, which means in my integration tests I need the server to bind to a port. Codeship lets me use localhost and whatever port I need, without any restrictions (note: it takes some time for the web server to start up, though, so some grace period before running tests is advised).
It is easy to connect Codeship to a source code management tool, just select your source code management tool (GitHub, or BitBucket) to connect with, a repository to track, and set some basic config values (jdk version, commands to build and run tests, etc.). From that point on, your new CI server will monitor the repository it is connected to, and builds will be automatically triggered on each and every push.
Codeship can access the central maven repository by default, but of course, it does not know about the artifact repository created in the previous step. Most probably the first build will fail with a message saying that maven (again, in my case) was unable to resolve dependencies. No worries, it’s easy to work around this problem. Previously we’ve seen builds can be configured; for a maven based build, all you need to add to your configuration or pipeline phase is:
echo "<settings>...</settings>" > ~/.m2/settings.xml
Where “…” is, of course, your full settings.xml.
I love Heroku, because it’s free, easy to use, my application gets deployed instantly and is accessible over the web. However, Heroku has some constraints (e.g. you are allowed to use one port only), so it is beneficial to decide to go with it right before you start writing any code.
I am not going to detail Heroku development here, but deployment should be quite easy.
Same as before, Heroku can connect to the central maven repository, but it has no clue about our artifacts hosted on Bintray. As a direct consequence, “cannot resolve dependecy” types of failures can/will occur. The solution to this is to simply place a settings.xml file in the root folder of your project. Heroku’s smart enough to pick that file up and use it for dependency resolution.
Heroku has got an awful lot of add-ons ready to be used. These are usually offered as software as a service (SaaS), awailable to you from anywhere. This means that most of the software you need for application development is already installed, you don’t have to worry about downloading and putting them on your local machine. You can keep your computer clean of message queues, caches, monitoring tools and much more, but still utilize them from whatever machine you want.
A note of connecting Heroku and Codeship
Codeship is extremely easy to connect to Heroku; I like to do the configuration on Codeship side (there is a Codeship add-on for Heroku, it may be even better, but I have never tried that one). Heroku can be configured as well to pull new code from GitHub directly, after every single push. In my opinion this is not a great idea. Github does not run tests, also does not build the software, which means unstable code may end up in “production”. So, I’d say it’s best to push changes to Heroku through Codeship.
In your Codeship project’s settings, navigate to the “Deployment” tab and select Heroku. (It’s worth mentioning that you can also deploy to Google AppEngine, Amazon and several others). Configure your Heroku API key (find it under “Account settings” in Heroku), deployment URL, database settings, verification URL. This last one is a pretty useful setting, the CI server can call this ‘Check URL’ endpoint to determine if the application has come up live or not.
And, that’s it, the full pipeline. The best things about it? All your work is kept in one place and deployed continuously with every push. You can work on your projects from multiple locations, without having to configure your environment over and over again. Should you lose your laptop, GitHub has your code for you. Broken tests, or unstable build? Meh, you are covered by Codeship. You have to install much less software, as Heroku has them for you. You can still run your software locally, as the Heroku add-ons are accessible once you correctly specify your environment variables.
And of course, it takes at most five minutes to get from a git push to up and running software deployed online.