Continuous Integration and Continuous Deployment with Middleman, Codeship, and GitHub Pages

This is a guest blog post by Ryan McGeary. Ryan runs Busyconf, where he aims to make conference planning easy. When we first saw his article we thought it would be a great tutorial about Continuous Integration and Continuous Deployment for static pages to publish on our blog. We got in contact with him and Ryan kindly provided his original article here.


Set up Continuous Deployment for Middleman

I use GitHub Pages for hosting some of my websites, and I use the Middleman static site generator as my content management system for some of these sites.

I like to run continuous integration for my projects whenever possible, and this goes for static site repositories as much as regular code repositories.

Recently, I started playing with Codeship for Continuous Integration and Continuous Deployment. It’s a well-priced continuous service, and I wanted to be able to automatically deploy my middleman site upon successful builds to the master branch. It took a bit of trial and error, but I finally got something that works well.

Codeship – A hosted Continuous Deployment platform for web applications

Continuous Integration with Codeship – Test Settings

After initializing a new GitHub repository in Codeship, you’ll need to define how tests are run. Under the Test project settings in Codeship, select Ruby as the language and define your Setup Commands and Test Commands.

Setup Commands:

bundle install

Test Commands:

bundle exec middleman build

Perfect. Now your site will run a test build upon every code push.

Continuous Deployment with Codeship – Deployment Settings

This is where I had some trouble, but I finally found a set of commands that correctly deloyed to our gh-pages branch in the repository. First, it’s worth mentioning that I use the middleman-gh-pages gem for deploying to the gh-pages branch. This gem gives you a rake publish task that handles most of the dirty work.

Under the Deployment project settings in Codeship, configure a deployment from the master branch using a Custom Script.

Custom Script:

git config --global user.email "robot@example.com"
git config --global user.name "Codeship Robot"
rm -rf build
git remote set-branches --add origin gh-pages
git fetch
bundle exec rake publish
sleep 30
wget --retry-connrefused --no-check-certificate -T 60 http://yoursite.com/

This configures a git user, removes the build directory that was left there from the test steps, adds a gh-pages remote branch (because Codeship only clones the relevant branch during setup), and runs the rake publish task to deploy the site to the gh-pages branch.

If all went well, your site will automatically deploy to GitHub Pages upon a push and successful build in the master branch.

Extra Credit: Force Codeship to skip builds on the gh-pages branch.

Unfortunately, Codeship currently tries to run builds on all branches, including the gh-pages branch. This is undesirable for this setup, so to avoid this, we also need to add ”–skip-ci” or “[skip ci]” to the commit message that is pushed to the gh-pages branch.

Fortunately, after this pull-request by yours truly, middleman-gh-pages can support that.

If using version >= 0.0.3 (or the master branch), you can add this to the bottom of your project’s Rakefile:

# Ensure builds are skipped when pushing to the gh-pages branch
ENV["COMMIT_MESSAGE_SUFFIX"] = "[skip ci]"

We want to thank Ryan for making his original blog post available. If you have any questions feel free to write them in the comments or ping Ryan on twitter.

Subscribe via Email

Be sure to join 13,643 subscribers of our newsletter to receive updates on software development best practices, Continuous Delivery and tips and tricks to start shipping your product faster.

Join the Discussion

Leave us some comments on what you think about this topic or if you like to add something.

  • Giovani

    After it waits for username

    git push origin gh-pages
    Username for ‘https://github.com':

    • http://ryan.mcgeary.org Ryan McGeary

      Giovani, Please see the original blog post here: http://ryan.mcgeary.org/2013/12/19/continuous-integration-deployment-middleman-codeship-github-pages/

      There’s an additional section that talks about GitHub Publishing Caveats:

      Make sure the email address that you use for this git user is a verified email address in your GitHub account. Otherwise, GitHub will accept the commit, but it will not publish the changes to your site. To fully make everything work, you will need to do one of two things: 1) Move the Codeship deploy key to an SSH key in your own GitHub account OR 2) Create a new machine user on GitHub and move the Codeship deploy key to an SSH key on that user account, give that machine user push/pull access to the repository, and make sure that machine user’s email address is fully verified by GitHub. I highly recommend going with option #2.

      • Giovani

        Thanks a lot for your article. This is the reason why I started playing with Codeship as well!
        I didn’t figure out how to work with a machine user and codeship. So I’ve just used option #1. That’s where things get interesting and during ‘bundle exec middleman build’ it asks for Username….

        • https://www.codeship.io/ Florian Motlik @codeship

          Do you have any HTTPS urls as dependencies or anything like that in your middleman scripts? That’s typically when github tries to pull through HTTPS and then you need the username/password.

          You could just change that to a git pull url which would solve the authentication issue.

          • Giovani

            I use the script called ‘middleman-gh-pages’ to deploy my pages. The same as described in the original tutorial. And it kept asking for username/password.

            So I’ve just had to add this line, as I said yesterday:
            git remote set-url origin git@github.com:***

            Actually, that’s interesting, am I the only one who experienced this problem?)

          • http://ryan.mcgeary.org Ryan McGeary

            To me, it sounds like either the Codeship SSH deploy key isn’t configured correctly at GitHub, or the origin URL isn’t an SSH url (but you said that was configured plus Codeship should have used that version of the remote URL anyway, no?)

  • Giovani

    so I have to add:
    git remote set-url origin git@github.com:…

  • http://www.pdsullivan.com Patrick Sullivan

    Gonna give this a try, such a great idea!

    • https://www.codeship.io/ Manuel Weiss @codeship

      Very happy you like it Patrick. Great we could help :) Let me know should you run into any problems. Happy to help!