Worm with Glasses

Coding • DevOps • Personal

Aug 13, 2017

Managing Site Content with Sub

No self respecting developer will tolerate writing out the same commands over and over.

Automate All the Things!

With Jekyll building the static files, I needed a way to:

  • create draft posts
  • serve drafts via localhost to review
  • publish a draft as a full post
  • build the site
  • deploy to DigitalOcean

After manually running shell commands and manually editing files, I had to automate the workflow.

I use sub to organize the various scripts that handle each part of the process.

Create Draft Posts

First step was to create a template.md file with all the optional Front Matter a post might need.

---
title:

# # Rest are optional
# categories:
# tags:
# permalink:
# excerpt: # Markdown description before the story
# description: # SEO `<meta>` description (requires an `excerpt`)
# header:
#  image: # Path to the full image for the size (1280x...)
#  image_description: # Custom `alt` tag
#  caption: # Photo credit (can be written in markdown)
#  teaser: # Path to teaser image (roughly 500x300)
#
#  # Hero video image
#  video:
#    id: 
#    provider:
#
#  # An image with text overlay and call to action button
#  overlay_image: # Path to the full image size
#  overlay_filter: 0.5 # opacity between 0.0 and 1.0 (or full `rgba(255, 0, 0, 0.5)`)
#  cta_label: # Call to action button label
#  cta_url: # URL the call to action button goes to
#  overlay_color: # Can be used rather than `overlay_image` as #ccc
#
# NOTE: https://mmistakes.github.io/minimal-mistakes/docs/helpers/
#       https://mmistakes.github.io/minimal-mistakes/docs/utility-classes/
---

You’ll notice that only title is required. Everything is commented out. Also, there’s no date attribute since this is a draft.

When I begin writing a draft I run:

site draft whatever-the-post-slug-will-be

which runs:

#!/bin/sh
set -u
set -e

cp _drafts/template.md _drafts/${1}.md
exec $EDITOR _drafts/${1}.md

A simple script to copy the template into the _drafts/ folder with the slug name and then fire up my editor (NeoVim.)

Previewing Drafts on Localhost

Jekyll can preview drafts on the localhost. I run:

site serve

which executes:

#!/bin/sh

set -x
set -e

jekyll serve -D --watch

in a separate tmux pane. Jekyll is configured to watch for changes and rebuild the draft for preview.

Publishing

Once I’m happy with a draft it’s time to publish it (meaning promoting it from _drafts/ into _posts/.)

site publish whatever-the-post-slug-will-be

Which runs:

#! /usr/bin/env ruby
#
# Copy the file from the drafts folder, add the current date, and update the
# filename.  Remove any commented out lines from the front matter.
#

now = Time.now
draft = File.basename(ARGV[0], '.md')
draft_filename = File.join('_drafts', "#{draft_filename}.md")
post_filename = File.join('_posts', "#{now.strftime('%Y-%m-%d')}-#{draft}.md")
post = File.open(post_filename, 'w')

state = :start

open(draft_filename).readlines.each do |line|
  if (state == :start || state == :in_front_matter) && line =~ /^---/
    post.puts line

    if state == :start
      post.puts "date: #{now.strftime('%Y-%m-%d %H:%M:%S %:z')}"

      state = :in_front_matter
    else
      state = :body
    end
  elsif state == :in_front_matter && (line =~ /^#/ || line =~ /^\s$/)
    # Skip all the comment lines in the front matter
    next
  else
    post.puts line
  end
end

post.close

File.unlink(draft_filename) if File.exist?(post_filename)

This Ruby script:

  1. Adds the current date attribute to the Front Matter
  2. Removes all the commented out lines in the Front Matter
  3. Moves the file from the _drafts folder to the _posts folder and prefixes the current date to the file.

Deploy Updates to Production

With everything ready, it’s time to deploy the changes to the [site]({{ .Site.BaseURL }}). One last script:

site deploy

running:

#!/bin/sh

$_SITE_ROOT/bin/site build
rsync -crvz --delete-after --delete-excluded  _site/ wormbytes:/var/www/wormbytes.ca/

First we build the site:

#!/bin/sh

set -u
set -e

jekyll build

and then copy the _site/ directory up to the DigitalOcean production server, deleting any files that have been removed and updating any new files.