Comments

Publish Posts Later With Jekyll/Octopress

I really like Octopress, which is built on Jekyll. You can read a lot of articles about the advantages and disadvantages of pre-baked blogs, so I won’t bore you with those details. Instead, I’ll bore you on the subject of the one feature I miss with pre-baked blogs: scheduling posts for later publication.

When I switched to a pre-baked blogging tool like Octopress, I gave up the ability to upload a post, but publish it later. Well, I didn’t really give it up entirely, but pre-baking my blog means thinking of my blog as a static web site, rather than a dynamic one, which implies having to re-deploy every time I wanted to change its content. This makes scheduling posts in the future a bit more tricky.

Using Heroku and its read-only file system make it even trickier, since I can’t regenerate the blog in production.

I just wanted to share my solution with you, in case it interests you. First, I added to Octopress the ability to generate the blog without future-dated posts. This looked difficult, especially with Octopress’s existing “preview mode” feature, but I discovered that Jekyll supports omitting future-dated posts directly with jekyll --no-future, so I augmented Octopress to use this feature. If you’d like to explore the details, click here.1

Next, I needed a way to republish my Octopress site regularly in order to include new posts as their publication instant arrives. I asked my tweeps for ideas, and we agreed that we couldn’t get around having a machine Out There Somewhere that’s always on that would poll a git repository for changes, then regenerate and publish to Heroku. I settled on the following architecture.

You can smell the Architecture!

I followed these basic steps:

  1. Added an SSH public key from “Monitor/Staging” to “Production”, so that the former could push to the latter.
  2. Installed a script into “Monitor/Staging” to, well, monitor, stage, then push.
  3. Cloned my local git repository to “Integration” so that it will always be available to “Monitor/Staging”.

Complicated, sure, but–and you’ll tell me if you disagree–just barely sufficiently complicated, and no worse. I can handle that.

My workflow hasn’t changed much. I compose posts, preview, and push to “Integration” when I finish. “Monitor/Staging” runs the following script every 10 minutes.

(deploy-blog.thecodewhisperer.com.sh) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#! /bin/bash
pushd $HOME/Workspaces/blog.thecodewhisperer.com
# I have to do this by hand, apparently.
. .rvmrc

# I can't assume that I'm on the right branch
git checkout -q master
git pull -q origin master
git checkout -q publish
git merge -q master

# Check the diff /before/ regenerating, to avoid spurious
# timestamp differences
DIFF="$(git diff --stat publish heroku/master)"
NOW=`date`
if [ -n "$DIFF" ]; then
  echo "Publishing $NOW..."
  bundle exec rake generate
  git add -A && git commit -m "Published $NOW" && git push heroku publish:master
else
  echo "No need to publish at $NOW.";
fi
popd

I write posts to the branch master, and “Monitor/Staging” merges them to the branch publish, then deploys them to “Production”’s branch master.

Of course, I will monitor this closely over the next few days, looking for anomalies. In particular, I worry a little about what happens when “Monitor/Staging” can’t merge master to publish automatically. I suppose in that case I’ll have something to worry about, and in the worst case, no changes will publish to production, which could cause annoyance, but sounds like safe default behavior.

If you see any problems with this setup, please don’t keep them to yourself!

  1. I’ve submitted a pull request for this, but I think Octopress’s maintainer has other, more important stuff to do these days.

Comments