Part 3: Migrating a WordPress Blog to Middleman and Deploying to Amazon S3

Mike Ball

February 09th, 2015

Part 3: Migrating WordPress blog content and deploying to production

In parts 1 and 2 of this series, we created middleman-demo, a basic Middleman-based blog, imported content from WordPress, and deployed middleman-demo to Amazon S3.

Now that middleman-demo has been deployed to production, let’s design a continuous integration workflow that automates builds and deployments.

In part 3, we’ll cover the following:

  • Testing middleman-demo with RSpec and Capybara
  • Integrating with GitHub and Travis CI
  • Configuring automated builds and deployments from Travis CI

If you didn’t follow parts 1 and 2, or you no longer have your original middleman-demo code, you can clone mine and check out the part3 branch: 

$ git clone  http://github.com/mdb/middleman-demo && cd middleman-demo && git checkout part3

Create some automated tests

In software development, the practice of continuous delivery serves to frequently deploy iterative software bug fixes and enhancements, such that users enjoy an ever-improving product. Automated processes, such as tests, assist in rapidly validating quality with each change.

middleman-demo is a relatively simple codebase, though much of its build and release workflow can still be automated via continuous delivery. Let’s write some automated tests for middleman-demo using RSpec and Capybara. These tests can assert that the site continues to work as expected with each change.

Add the gems to the middleman-demo Gemfile: 

gem 'rspec'
gem 'capybara'

Install the gems:

$ bundle install 

Create a spec directory to house tests:

$ mkdir spec

As is the convention in RSpec, create a spec/spec_helper.rb file to house the RSpec configuration:

$ touch spec/spec_helper.rb

Add the following configuration to spec/spec_helper.rb to run middleman-demo during test execution:

require "middleman"
require "middleman-blog"
require 'rspec'
require 'capybara/rspec'

Capybara.app = Middleman::Application.server.inst do
  set :root, File.expand_path(File.join(File.dirname(__FILE__), '..'))
  set :environment, :development
end

Create a spec/features directory to house the middleman-demo RSpec test files:

$ mkdir spec/features

Create an RSpec spec file for the homepage:

$ touch spec/features/index_spec.rb 

Let’s create a basic test confirming that the Middleman Demo heading is present on the homepage. Add the following to spec/features/index_spec.rb:

require "spec_helper"

describe 'index', type: :feature do
  before do
    visit '/'
  end

  it 'displays the correct heading' do
    expect(page).to have_selector('h1', text: 'Middleman Demo')
  end
end

Run the test and confirm that it passes:

$ rspec

You should see output like the following:

Finished in 0.03857 seconds (files took 6 seconds to load)
1 example, 0 failures

Next, add a test asserting that the first blog post is listed on the homepage; confirm it passes by running the rspec command:

it 'displays the "New Blog" blog post' do
  expect(page).to have_selector('ul li a[href="/blog/2014/08/20/new-blog/"]', text: 'New Blog')
end

As an example, let’s add one more basic test, this time asserting that the New Blog text properly links to the corresponding blog post. Add the following to spec/features/index_spec.rb and confirm that the test passes:

it 'properly links to the "New Blog" blog post' do
  click_link 'New Blog'

  expect(page).to have_selector('h2', text: 'New Blog')
end

middleman-demo can be further tested in this fashion. The extent to which the specs test every element of the site’s functionality is up to you. At what point can it be confidently asserted that the site looks good, works as expected, and can be publicly deployed to users?

Push to GitHub

Next, push your middleman-demo code to GitHub. If you forked my original github.com/mdb/middleman-demo repository, skip this section.

1. Create a GitHub repository
If you don’t already have a GitHub account, create one. Create a repository through GitHub’s web UI called middleman-demo.

2. What should you do if your version of middleman-demo is not a git repository?
If your middleman-demo is already a git repository, skip to step 3.

If you started from scratch and your code isn’t already in a git repository, let’s initialize one now. I’m assuming you have git installed and have some basic familiarity with it.

Make a middleman-demo git repository:

$ git init && git add . && git commit -m 'initial commit' 

Declare your git origin, where <your_git_url_from_step_1> is your GitHub middleman-demo repository URL:

$ git remote add origin <your_git_url_from_step_1>

Push to your GitHub repository:

$ git push origin master

You’re done; skip step 3 and move on to Integrate with Travis CI.

3. If you cloned my mdb/middleman-demo repository…
If you cloned my middleman-demo git repository, you’ll need to add your newly created middleman-demo GitHub repository as an additional remote:

$ git remote add my_origin <your_git_url_from_step_1>

If you are working in a branch, merge all your changes to master.

Then push to your GitHub repository:

$ git push -u my_origin master

Integrate with Travis CI

Travis CI is a distributed continuous integration service that integrates with GitHub. It’s free for open source projects. Let’s configure Travis CI to run the middleman-demo tests when we push to the GitHub repository.

Log in to Travis CI

  1. First, sign in to Travis CI using your GitHub credentials.
  2. Visit your profile.
  3. Find your middleman-demo repository in the “Repositories” list.
  4. Activate Travis CI for middleman-demo; click the toggle button “ON.”

Create a .travis.ymlfile

Travis CI looks for a .travis.yml YAML file in the root of a repository. YAML is a simple, human-readable markup language; it’s a popular option in authoring configuration files. The .travis.yml file informs Travis how to execute the project’s build.

Create a .travis.yml file in the root of middleman-demo:

$ touch .travis.yml

Configure Travis CI to use Ruby 2.1 when building middleman-demo. Add the following YAML to the .travis.yml file:

language: ruby
rvm: 2.1

Next, declare how Travis CI can install the necessary gem dependencies to build middleman-demo; add the following:

install: bundle install

Let’s also add before_script, which runs the middleman-demo tests to ensure all tests pass in advance of a build:

before_script: bundle exec rspec

Finally, add a script that instructs Travis CI how to build middleman-demo:

script: bundle exec middleman build

At this point, the .travis.yml file should look like the following:

language: ruby
rvm: 2.1
install: bundle install
before_script: bundle exec rspec
script: bundle exec middleman build

Commit the .travis.yml file:

$ git add .travis.yml && git commit -m "added basic .travis.yml file"

Now, after pushing to GitHub, Travis CI will attempt to install middleman-demo dependencies using Ruby 2.1, run its tests, and build the site. Travis CI’s command build output can be seen here:

https://travis-ci.org/<your_github_username>/middleman-demo

Add a build status badge

Assuming the build passes, you should see a green build passing badge near the top right corner of the Travis CI UI on your Travis CI middleman-demo page.

Let’s add this badge to the README.md file in middleman-demo, such that a build status badge reflecting the status of the most recent Travis CI build displays on the GitHub repository’s README.

If one does not already exist, create a README.md file:

$ touch README.md

Add the following markdown, which renders the Travis CI build status badge:

[![Build Status](https://travis-ci.org/<your_github_username>/middleman-demo.svg?branch=m...)](https://travis-ci.org/<your_github_username>/middleman-demo)

Configure continuous deployments

Through continuous deployments, code is shipped to users as soon as a quality-validated change is committed. Travis CI can be configured to deploy a middleman-demo build with each successful build.

Let’s configure Travis CI to continuously deploy middleman-demo to the S3 bucket created in part 2 of this tutorial series.

First, install the travis command-line tools:

$ gem install travis

Use the travis command-line tools to set S3 deployments. Enter the following; you’ll be prompted for your S3 details (see the example below if you’re unsure how to answer):

$ travis setup s3

An example response is:

Access key ID: <your_aws_access_key_id>
Secret access key: <your_aws_secret_access_key_id>
Bucket: <your_aws_bucket>
Local project directory to upload (Optional): build
S3 upload directory (Optional):
S3 ACL Settings (private, public_read, public_read_write, authenticated_read, bucket_owner_read, bucket_owner_full_control): |private| public_read
Encrypt secret access key? |yes| yes
Push only from <your_github_username>/middleman-demo? |yes| yes

This automatically edits the .travis.yml file to include the following deploy information:

deploy:
  provider: s3
  access_key_id: <your_aws_access_key_id>
  secret_access_key:
    secure: <your_encrypted_aws_secret_access_key_id>
  bucket: <your_s3_bucket>
  local-dir: build
  acl: !ruby/string:HighLine::String public_read
  on:
    repo: <your_github_username>/middleman-demo

Add one additional option, informing Travis to preserve the build directory for use during the deploy process:

skip_cleanup: true

The final .travis.yml file should look like the following:

language: ruby
rvm: 2.1
install: bundle install
before_script: bundle exec rspec
script: bundle exec middleman build
deploy:
  provider: s3
  access_key_id: <your_aws_access_key>
  secret_access_key:
    secure: <your_encrypted_aws_secret_access_key>
  bucket: <your_aws_bucket>
  local-dir: build
  skip_cleanup: true
  acl: !ruby/string:HighLine::String public_read
  on:
    repo: <your_github_username>/middleman-demo

Confirm that your continuous integration works

Commit your changes:

$ git add .travis.yml && git commit -m "added travis deploy configuration"

Push to GitHub and watch the build output on Travis CI:

https://travis-ci.org/<your_github_username>/middleman-demo

If all works as expected, Travis CI will run the middleman-demo tests, build the site, and deploy to the proper S3 bucket.

Recap

Throughout this series, we’ve examined the benefits of static site generators and covered some basics regarding Middleman blogging. We’ve learned how to use the wp2middleman gem to migrate content from a WordPress blog, and we’ve learned how to deploy Middleman to Amazon’s cloud-based Simple Storage Service (S3). We’ve configured Travis CI to run automated tests, produce a build, and automate deployments.

Beyond what’s been covered within this series, there’s an extensive Middleman ecosystem worth exploring, as well as numerous additional features. Middleman’s custom extensions seek to extend basic Middleman functionality through third-party gems.

Read more about Middleman at Middlemanapp.com.

About this author

Mike Ball is a Philadelphia-based software developer specializing in Ruby on Rails and JavaScript. He works for Comcast Interactive Media where he helps build web-based TV and video consumption applications.