Posted: August 6, 2022
I used to run a pretty complicated publishing workflow on this website. I don’t anymore. I’m writing this up because it might be useful for somebody else who uses the Jekyll static site generator for publishing to their own private hosting site.
I like Jekyll. It combines the power of a content management system (such as Wordpress) with the simplicity, security, and performance of a static hosted website. I write my posts in the simple Markdown format, and Jekyll processes them to HTML for publication.
My Old Workflow
So when I make changes and pushed them into Git source control, the Jenkins pipeline would launch, rebuild the site content, and publish it to the live site. It was très fancy.
But, it was quite complex and brittle. For instance, the Jenkinsfile had to copy the files in and out of a Docker volume, so the container could access it.
It was way too much overhead and complexity to publish my simple site. So I switched to a simple, manual tooling.
I replaced the complex CI/CD pipeline with a simple Rakefile.
A Rakefile is a set of rules for the Rake build utility. Rake is closely associated with the Ruby programming language and Jekyll is implemented in Ruby, thus they pair well.
Here is my entire Rakefile:
desc "Serve site locally" task :serve do sh "bundle exec jekyll serve --drafts" end desc "Rebuild site static content" task :build do sh "bundle exec jekyll build" end desc "Publish site static content to web server" task :publish => :build do sh "rsync -av --delete --checksum _site/. email@example.com:Website/htdocs/." end
The two tasks I directly use are: serve and publish.
The serve task launches a local web server at http://localhost:4000/, which contains the draft version of the full website. As the content is edited, the website served is automatically updated. (Restart is required only when the configuration changes.) That way I can edit the content locally and view the results immediately in a web browser.
Here is a sample run of the serve task:
$ rake serve bundle exec jekyll serve --drafts Configuration file: /home/courtney/Workspace/website-crosenthal-com/_config.yml Source: /home/courtney/Workspace/website-crosenthal-com Destination: /home/courtney/Workspace/website-crosenthal-com/_site Incremental build: disabled. Enable with --incremental Generating... Jekyll Feed: Generating feed for posts AutoPages: Disabled/Not configured in site.config. Pagination: Complete, processed 1 pagination page(s) done in 1.018 seconds. Auto-regeneration: enabled for '/home/courtney/Workspace/website-crosenthal-com' LiveReload address: http://0.0.0.0:35729 Server address: http://0.0.0.0:4000/ Server running... press ctrl-c to stop. LiveReload: Browser connected
The publish task generates the full website content and then pushes it live to the web server. The publish task has a dependency on the build task, which does the bit about generating the website content. Then the publish task continues, using the Linux rsync command to efficiently push the changes to the live site.
Here is a sample run of the publish task:
/usr/bin/ruby /usr/local/bin/rake publish bundle exec jekyll build Configuration file: /home/courtney/Workspace/website-crosenthal-com/_config.yml Source: /home/courtney/Workspace/website-crosenthal-com Destination: /home/courtney/Workspace/website-crosenthal-com/_site Incremental build: disabled. Enable with --incremental Generating... Jekyll Feed: Generating feed for posts AutoPages: Disabled/Not configured in site.config. Pagination: Complete, processed 1 pagination page(s) done in 1.502 seconds. Auto-regeneration: disabled. Use --watch to enable. rsync -av --delete --checksum _site/. firstname.lastname@example.org:Website/htdocs/. sending incremental file list . . . sent 5,212 bytes received 849 bytes 1,346.89 bytes/sec total size is 9,145,652 speedup is 1,508.93 Process finished with exit code 0
Even though IntelliJ is intended for Java development, it works fine for this purpose. It has a plugin that understands the Markdown format, which is how I author blog posts. Plus, IntelliJ knows how to run rake tasks, which allows me to integrate the Rakefile. It’s available in a free community edition, which supports all the features I need for my website.
I setup two run configurations, one to serve the website locally (called “rake serve”) and another to publish updates once changes are done (called “rake publish”), which run the corresponding Rake tasks. The screenshot below (click to view full size) shows the setup of the “rake serve” run configuration.
The “rake serve” run configuration launches a local web server at http://localhost:4000/. It serves the draft version of the full website. I can browse the website as I edit. The website is automatically updated as I make changes.
To start it, I do: Run -> Run … -> Rake Serve
The screenshot below (click to view full size) shows the startup.
The configuration of the rake publish run configuration is the same as for rake serve (see previous screenshot) – just change both instances of “serve” to “publish”.
Once I’m done with my website changes and I’m ready to publish, I do:
- Git -> Commit… -> Commit and Push…
- Run -> Run… -> Rake Publish
That’s it – all very manual and simple. I tried the fully automated way, but I like this better. The combination of a simple Rakefile and my IDE make it easy to edit and publish my website.