So there’s only about 30 50 thousand pages on this general topic, but I
found that about half of them were out of date, so I figured I should try and
collect all the info into one big post. I’ve referenced where I’ve found some of
the stuff that’s harder to find from Googling using the wonders of Octopress
footnotes.
Unfortunately, as I was finishing up this post, the post announcing Octopress 3.0 comes out. While I had known it was coming, I wasn’t expecting it to be so soon. Obviously this post will be less useful, but it should still be informative. I’ve included what I think will need to be modified to function on 3.0 at the bottom.
Table of contents
My Site Flow
- Local
- Private Github Repo
- Built and Deployed using TravisCI to a DigitalOcean droplet
I’ve got a drafts workflow using a couple tasks I found online1 and then promptly modified:
## -- Misc Configs -- ##
drafts_dir = "_drafts" # directory for draft files
# usage rake new_draft[my-new-draft] or rake new_draft['my new draft'] #desc "Begin a new draft in #{source_dir}/#{drafts_dir}"task :new_draft, :title do |t, args|if args.titletitle = args.titleelsetitle = get_stdin("Enter a title for your post: ")endraise "### You haven't set anything up yet. First run `rake install` to set up an Octopress theme." unless File.directory?(source_dir)mkdir_p "#{source_dir}/#{drafts_dir}"filename = "#{source_dir}/#{drafts_dir}/#{title.to_url}.#{new_post_ext}"if File.exist?(filename)abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'endputs "Creating new draft: #{filename}"open(filename, 'w') do |post|post.puts "---"post.puts "layout: post"post.puts "title: \"#{title.gsub(/&/,'&')}\""post.puts "comments: true"post.puts "#placeholder"post.puts "categories: "post.puts "---"endend
# usage rake publish_draftdesc "Select a draft to publish from #{source_dir}/#{drafts_dir} on the current date."task :publish_draft dodrafts_path = "#{source_dir}/#{drafts_dir}"drafts = Dir.glob("#{drafts_path}/*.#{new_post_ext}")drafts.each_with_index do |draft, index|begincontent = File.read(draft)if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/mdata = YAML.load($1)endrescue => eputs "Error reading file #{draft}: #{e.message}"rescue SyntaxError => eputs "YAML Exception reading #{draft}: #{e.message}"endputs " [#{index}] #{data['title']}"endputs "Publish which draft? "answer = STDIN.gets.chompif /\d+/.match(answer) and not drafts[answer.to_i].nil?mkdir_p "#{source_dir}/#{posts_dir}"source = drafts[answer.to_i]filename = source.gsub(/#{drafts_path}\//, '')dest = "#{source_dir}/#{posts_dir}/#{Time.now.strftime('%Y-%m-%d')}-#{filename}"puts "Publishing post to: #{dest}"File.open(source) { |source_file| contents = source_file.read contents.gsub!(/^#placeholder$/, "date: #{Time.now.strftime('%Y-%m-%d %H:%M %z')}") File.open(dest, "w+") { |f| f.write(contents) }}FileUtils.rm(source)elseputs "Index not found!"endend
For this to work using rake preview
, you’ll need to modify your preview task
slightly, add the flag --drafts
to the jekyll call.
system "compass compile --css-dir #{source_dir}/stylesheets" unless File.exist?("#{source_dir}/stylesheets/screen.css")jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build --watch --drafts")compassPid = Process.spawn("compass watch")
The Build Process
Personally, I don’t want to have to deal with building and uploading my site. Instead I use Travis-CI targeted to a specific Github repo branch, and some modified rsync scripts.
language: rubycache: bundler
rvm: - 1.9.3branches:only: - master
before_install: - echo -e "Host *\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - echo -e "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - eval `ssh-agent -s` - ssh-add ~/.ssh/id_rsa
script: - bundle exec rake integrate #move any stashed posts to source - bundle exec rake generate #generate static to /public - bundle exec rake deploy #rsync /public to server
Rsync Setup
You’ll need to configure your deployment account’s SSH private key in Travis-CI
by replacing all new lines with \n
, and then escaping that to \\n
, so that
it ends up being one line with \\n
in between each original line.2
(NOTE: Make sure the key was generated without ssh-agent running, and set a
blank passphrase.) Next, go to your Travis-CI settings, create a new environment
variable, name it whatever you want, I used $DEPLOY_PRIVATE_KEY
, then paste in
your one-line private key into the variable section. Now that it’s a environment
variable in all Travis workers your builds will use, the before_install
tasks
will disable strict host key checking (requires input, which Travis doesn’t
allow), and then echo the contents of DEPLOY_PRIVATE_KEY
to id_rsa
, then add
that key to the ssh-agent, in my case, allowing the worker to connect using the
user travis-ci
to my droplet.
If the user you’re connecting with in your Rakefile’s settings isn’t the owner
of your specific directories on your hosting server, rsync will probably fail to
sync properly. In that case, you’ll need to add --omit-dir-times
to
rsync-args
in the Rakefile.
After all of this, you should be good to go. If you’re using the master deploy method, push your site up to master, and it should build properly on Travis, and deploy to your rsync destination.
Octopress 3.0
For the most part, as far as I can tell, these modifications will mostly still
work for 3.0. The drafts changes will no longer be needed anymore, as the Jekyll
drafts workflow is now using a separate drafts folder. The .travis.yml
will
need to be tweaked slightly, as well as the _config.yml
having an exclude
added to keep Jekyll running on Travis-CI from trying to build the templates in
/vendor
, but other than that, this post is mostly forwards compatible to
Octopress 3.0.