Search code examples
rubyrakejekyll

How do I build a Jekyll site from Rake task without using the command line?


I want to create a Rake task that builds a Jekyll site, then runs tests on the generated site, similar to the following:

require 'html/proofer'

task :test => [:build] do
  HTML::Proofer.new('./_site',{
                                 :only_4xx => true,
                                 :check_favicon => true,
                                 :check_html => true
                             }).run
end

task :build do
  system 'bundle exec jekyll build'
end

I'm relatively new to Ruby and I'm keen to gain more experience. Using system 'bundle exec jekyll build' in the build task seems a bit of a shortcut to me, so as an exercise I wanted to refactor this rake task to build the site using Jekyll::Commands::Build and therefore not calling a command line executable, as the above example does. I was hoping something like this would suffice:

# Including only the changed build task
require 'jekyll'

task :build do
  config = { 'source' => './', 'destination' => './_site' }
  site = Jekyll::Site.new(config)
  Jekyll::Commands::Build.build site, config
end

However, I can't build the site using this task:

joenyland@Joes-MBP ~/Documents/masterroot24.github.io $ bundle exec rake build
rake aborted!
NoMethodError: undefined method `to_sym' for nil:NilClass
/Users/joenyland/.rvm/gems/ruby-2.2.1@masterroot24.github.io/gems/jekyll-2.4.0/lib/jekyll/site.rb:27:in `initialize'
/Users/joenyland/Documents/masterroot24.github.io/Rakefile:14:in `new'
/Users/joenyland/Documents/masterroot24.github.io/Rakefile:14:in `block in <top (required)>'
Tasks: TOP => build
(See full trace by running task with --trace)

How do I build an existing site from a Rake task without using the command line and instead use the Jekyll library directly?

As requested by @DavidJacquel in the comments below, I've thrown together a demo of the issue in a repo here.


Solution

  • The configuration should be a Jekyll.configuration instance:

    # Including only the changed build task
    require 'jekyll'
    
    task :build do
      config = Jekyll.configuration({ 
        'source' => './', 
        'destination' => './_site' 
      })
      site = Jekyll::Site.new(config)
      Jekyll::Commands::Build.build site, config
    end