Gitlab Pages with Jekyll and NPM

How to configure your .gitlab-ci.yml file to get Jekyll and NPM to play nice

November 24, 2016 - 4 minute read -
npm node jekyll gitlab docker

TL;DR

Here’s the YAML that got my Gitlab instance working, having Node, NPM, Bower and Jekyll play nice in a single container on Gitlab’s Docker runner:

# requiring the environment of Ruby 2.3.x
image: ruby:2.3.1

# add bundle cache to 'vendor' for speeding up builds
cache:
  paths: 
    - vendor/

before_script:
# Getting locales to work. No meme, it really requires 6 commands. Jesus.
  - apt-get update -qy 
  - apt-get install -qy locales
  - echo "en_US UTF-8" > /etc/locale.gen
  - locale-gen en_US en_US.UTF-8
  - export LANG=en_US.UTF-8
  - export LANGUAGE=en_US:en
  - export LC_ALL=en_US.UTF-8

# Jekyll and Chalk require Node, which gets installed alongside NPM automagically
  - apt-get install -y npm

# Symlink it because default apt installs to node (m-muh naming conventions)
  - ln -s /usr/bin/nodejs /usr/bin/node
  - npm install -g npm
  - npm install -g bower

# In this Ruby image, the executing user is root, so we'll have to allow that to bower using the --allow-root flag
  - bower install --allow-root
  - bundle install --path vendor


# The 'pages' job will deploy and build your site to the 'public' path
pages:
  stage: deploy
  script:
    - bundle exec jekyll build -d public/
  artifacts:
    paths:
      - public
  only:
    - master # this job will affect only the 'master' branch

The setting

After seeing a recent post on HN regarding the cheapest way to flexibly host something, I decided to learn a little more about Static Site Generators (SSG) and hosting on a Git provider. I figured it’d be a great exercise to add to my general developer culture.

I decided to go with Gitlab Pages over Github, given it has more flexibility, as opposed to Github, which only allows Jekyll and specific plugins. Additionally, I feel Gitlab generally has a better offering than Github, given their policy regarding nearly unlimited private repositories, being (mostly) open source, etc. After browsing a bunch of templates, I settled on Chalk by Nielsen Ramon, as I enjoyed its elegant simplicity.

Turns out that, while Gitlab allows for more flexibility, it’s also a little more complicated to set up to a simple mortal like myself. Though I have some experience with Docker Compose, this took me a bunch of hours to figure out. I’ll walk you through the .gitlab-ci.yml file I finally came up with. Below I’ve added each of the individual issues that I encountered, solved, and that finally led to this working config.

Issues I ran into

Below are the issues that I ran into before getting the whole thing working.

jekyll 3.3.1 | Error: Could not find a JavaScript runtime.

The delightful first error I ran into. Thankfully here, the problem was relatively simple to solve: read the fucking manual. Turns out I just had to run the command bin/setup before pushing the whole thing. Duh.

/bin/bash: line 47: bower: command not found

Well yeah, it’s a node package, and none of that was installed. Install nodejs and npm first. Adding - npm install -g bower to our pre-script execution should solve that.

/bin/bash: line 47: npm: command not found

Surely you’re seeing a common trend here. npm wasn’t installed, I probably should get on that. Spoiler alert, that’s obviously going to require installing nodejs too. Thankfully, that automatically happens upon installation of npm.

- apt-get install -y npm
- npm install -g npm

/usr/bin/env: node: No such file or directory

Thank you based @digitalmediums for providing the solution to this one. A simple
ln -s /usr/bin/nodejs /usr/bin/node
fixed that.

Note: If you’re interested on exactly why this is happening: installing nodejs with the standard apt-get command on Ubuntu/Debian distributions ends up putting the install in the nodejs directory. The reason for this is that the distro maintainers find node to be a far too generic name that could end up causing naming clashes. In our case, we’re not at risk for that, so we can safely symlink the node folder to nodejs. Read the Github link above if you’re curious for more details or a nice flamewar on whether the distro maintainers are idiots or not.

bower: You can however run a command with sudo using –allow-root option

Yup, the ruby: 2.3.1 image has you default as root, and bower was (very intelligently so) hard-coded to disallow that. Smart move, but in our case not really necessary (don’t do this on a production environment though). Append --allow-root to get rid of this.

jekyll 3.3.1 | Error: “\xE6” on US-ASCII

Oh man, this took me a solid few hours to figure out. The issue in itself is not very obfuscated: the LOCALE in the ruby: 2.3.1 image is set to POSIX, which throws some error when dealing with the encoding from the Chalk Jekyll template. The final, proper solution to set your locale to a nice, UTF-8 compliant one is:

  - apt-get update -qy
  - apt-get install -qy locales
  - echo "en_US UTF-8" > /etc/locale.gen
  - locale-gen en_US en_US.UTF-8
  - export LANG=en_US.UTF-8
  - export LANGUAGE=en_US:en
  - export LC_ALL=en_US.UTF-8