ScottLogic / blog

The Scott Logic blog
http://blog.scottlogic.com
Other
9 stars 85 forks source link

Scott Logic Blogs

If you are looking to write a blog post, then you don't need to read any further, as you can author posts using SiteLeaf: see our company intranet for instructions on how to create a new page and view it before publication on the blog.

The below instructions allow more control over the process, though they do require a smidgen of git knowledge and a GitHub account.

Technical Stack

The blog is a static website, designed to be hosted on GitHub pages.

The underlying content is generated through a series of Ruby gems and libraries, starting with a dedicated github-pages gem.

Within that stack, Jekyll is used as the static content generation engine, consuming template files written in either HTML or Markdown (syntax extended by Kramdown). Common content or structure can be further injected or managed using the Liquid templating language.

Authoring

To write a blog post, it is recommended to fork the repo, then perform a sparse checkout that excludes all previous posts and all authors other than yourself. This will result in the quickest build.

The alternative is to perform a full checkout and build all posts (more than 15 years' worth!) which can take five minutes or more to complete. If you are working on technical issues or improvements, then you may need some blog posts to see the result of your changes; in this case, there is little alternative but to perform a full checkout.

Fork the repository

At the top of the ScottLogic blog GitHub repo you will find the "fork" button. You will need to be logged into your GitHub account first, then clicking the button will generate your own fork and navigate to the resulting fork. Then click the <> Code button at the top to see your clone options; HTTPS clone is the simplest. Copy the URL, then:

# Clone your fork without checking anything out:
git clone --depth 1 --filter=blob:none --no-checkout YOUR-REPO-URL-HERE
cd blog

# Optional: tell sparse checkout what to include (excludes _posts by default).
# Use your Scott Logic username in the below command:
git sparse-checkout set _data _includes _layouts assets category scripts scss shell YOUR-SL-USERNAME-HERE
git checkout gh-pages

First-time authors

If this is your first post, you'll need to set yourself up as an author. For this, you will need a directory in the repo root named after your Scott Logic username. Within this you will need a set of files: atom.xml, feed.xml, index.html, and an image file of yourself. Just copy an existing author's files and modify their contents: it should be obvious what needs changing. Then add yourself to _data/authors.yml, again using an existing author as a template. You will need to add

Finally, if you performed a sparse checkout as recommended, you will need to add directory _posts in the root of your local copy.

Adding a new post

Below is a summary for getting started; for more comprehensive instructions on authoring posts, including markdown syntax and linking to images, see the pages on our company intranet.

Within the _posts directory, add a markdown file for your new post, named with date and title similar to existing posts, e.g. 2024-10-31-Your-snappy-post-title.md. Copy the headers from a recent post, and modify the values for yours. You may add as many tags (keywords) as you like, but a maximum of two Categories; see _data/categories.yml for our current categories.

Note that Jekyll will not display your post unless the header date is in the past, so if you do not see your post when running locally, check the date (and time) first. As you can probably guess, this is how you can set a "Go Live" date in the future, if you don't want your post to appear immediately.

Once you have your skeleton file in place, you can run the blog and start writing. Saving changes should trigger a rebuild.

Run the blog locally

By far the easiest route is to use Docker: if you have it installed, you can skip ahead now!

The blog consists of static HTML pages with content generated using:

In theory, once you've installed Ruby and Bundler, given that the project contains a valid Gemfile, then using Bundler should bring in most of the dependencies automatically. However, due to Nokogiri's reliance on Native XML parsers you may require additional steps. Thorough instructions for setting up your development environment are detailed below.

Prerequisites

First, install Ruby and (if on Linux) a few build dependencies for Nokogiri.

On Linux:

sudo apt-get install ruby2.3 ruby2.3-dev build-essential dh-autoreconf libxslt-dev libxml2-dev zlib1g-dev

On Windows, if you use Chocolatey, simply run choco install ruby in a PowerShell instance with elevated priveleges. If you don't use Chocolatey, you can use RubyInstaller or see the Ruby website for alternative ways to install Ruby. You don't need to install any other dependencies on Windows at this stage.

Secondly, update Gem and install the Jekyll, Bundler and Nokogiri gems.

On Linux:

sudo gem update
sudo gem install jekyll bundler nokogiri

On Windows, in a PowerShell instance with elevated privileges:

gem update
gem install jekyll bundler nokogiri

Thirdly, configure Bundler to store project dependencies in vendor/bundle, and, when in the root directory of your clone of the blog, install the project dependencies.

bundle config path vendor/bundle
cd PATH/TO/BLOG
bundle install

Finally, run jekyll -v to check whether Jekyll is working. If so, you're good to run the blog!

Running in the native environment

Once you've got all the prerequisites for your operating system, you can run the blog. Navigate to the root directory of your clone of the blog and execute Jekyll using Bundler.

bundle exec jekyll serve

The blog will then be available on localhost.

If you are working on fixes or new features, and need to re-compile the scripts or SCSS, you can use these npm scripts:

npm ci
npm run scripts
npm run style

Running with Docker

Use a bash-compatible shell; Git bash on Windows should work fine.

Install gem dependencies

First, we output gem dependencies to directory container_gem_cache on the host machine. This is analogous to running "npm install" for an npm package:

./shell/docker-gem-install.sh

Run in watch mode

Now we can serve the blog with live reloading. Replace "jbloggs" with your ScottLogic username:

BLOG_USERNAME=jbloggs ./shell/docker-dev-watch.sh

It'll take a while to build first time, but once it's done you should see message "done in XXX.YYY seconds". Then you can navigate to localhost in your browser.

Note that if you performed a sparse checkout as recommended, and if this is your first post, then you won't see any blog posts when the site loads unless you've already added a file for your new blog post.

CI/CD

We use GitHub Actions for CI/CD. The workflow definitions are in YAML files in .github/workflows.

Compress Images Once a Month

Uses the calibreapp/image-actions Action to automatically compress images. The compression algorithm is near-lossless. It compresses all images in the repo once per month, and creates a Pull Request to merge in the resulting changes.

Check accessibility of changed content

Runs pa11y-ci with the aXe test runner to detect some common accessibility problems. It serves the blog locally and runs the tests on the rendered webpages. It only checks pages and blog posts which have changed, but doesn’t take any interest in changes to layouts or includes, so changes to those should be tested across the whole site separately. This workflow runs on Pull Requests, pushes to gh-pages and on manual dispatches.

Generate Read More related

Generates Read More links on blog pages across the blog, using the OpenAI API to determine which blog posts are on similar themes. This workflow runs only on manual dispatches on the gh-pages branch and creates a Pull Request to merge in the resulting changes.

Remove Unused Images

For each image in the repo, searches all the blog posts, pages, YAML data files and JavaScript scripts for any occurrences of its filename. If the filename occurs nowhere, deletes the image. Then makes a Pull Request to merge in its changes. This workflow runs only on a manual dispatch on the gh-pages branch.