Sean

Weekly Brain Dump #2

- 8 minutes to read

At a Glance

LocalCI

There has been some nice improvements to LocalCI this week. Specifically I’ve been working on getting the different styles of output to work well. There’s now three and they are realtime, json, and plain.

Given this Rakefile.

require "standard/rake"
require "local_ci"

LocalCI::Rake.setup(self)

setup do
  job "Bundle", "bundle check || bundle install"
end

flow "Linting" do
  job "StandardRB", "bundle exec rake standard"
end

flow "Specs" do
  job "RSpec", "bundle exec rspec"
  job "RSpec - plain", "LOCAL_CI_STYLE=plain bundle exec rspec"
  job "RSpec - json", "LOCAL_CI_STYLE=json bundle exec rspec"
  job "RSpec - realtime", "LOCAL_CI_STYLE=realtime bundle exec rspec"
end

The three different styles would look like this.

Realtime

A terminal displaying the below.

The headings are green and the timing are yellow.

$ bundle exec rake ci --jobs 2
===| Setup |====================================================================================
[✓] Bundle (0.15s)
--------------------------------------------------------------------------------------(0.20s)---

===| Linting |==================================================================================
[✓] StandardRB (1.08s)
--------------------------------------------------------------------------------------(1.10s)---

===| Specs |====================================================================================
[✓] RSpec (0.39s)
[✓] RSpec - plain (0.38s)
[✓] RSpec - json (0.40s)
[✓] RSpec - realtime (0.40s)
--------------------------------------------------------------------------------------(0.80s)---

JSON

$ LOCAL_CI_STYLE=json bundle exec rake ci
{"flow":"Setup","job":"Bundle","duration":null,"state":"running"}
{"flow":"Setup","job":"Bundle","duration":0.132428631,"state":"success"}
{"flow":"Linting","job":"StandardRB","duration":null,"state":"running"}
{"flow":"Linting","job":"StandardRB","duration":0.975149449,"state":"success"}
{"flow":"Specs","job":"RSpec - realtime","duration":null,"state":"running"}
{"flow":"Specs","job":"RSpec - json","duration":null,"state":"running"}
{"flow":"Specs","job":"RSpec - json","duration":null,"state":"running"}
{"flow":"Specs","job":"RSpec - json","duration":null,"state":"running"}
{"flow":"Specs","job":"RSpec - plain","duration":0.342158569,"state":"success"}
{"flow":"Specs","job":"RSpec - realtime","duration":0.343942005,"state":"success"}
{"flow":"Specs","job":"RSpec","duration":0.353630655,"state":"success"}
{"flow":"Specs","job":"RSpec - json","duration":0.350691562,"state":"success"}

Plain

$ LOCAL_CI_STYLE=plain bundle exec rake ci
=== Setup - Bundle [running] ===
=== Setup - Bundle [success] (0.13s) ===
=== Linting - StandardRB [running] ===
=== Linting - StandardRB [success] (0.96s) ===
=== Specs - RSpec - realtime [running] ===
=== Specs - RSpec - realtime [success] (0.30s) ===
=== Specs - RSpec - json [running] ===
=== Specs - RSpec - json [success] (0.30s) ===
=== Specs - RSpec - plain [running] ===
=== Specs - RSpec - plain [success] (0.30s) ===
=== Specs - RSpec [running] ===
=== Specs - RSpec [success] (0.29s) ===

Zero Downtime Deployments for this Blog

I use Caprover for hosting everything that I run personally. It’s a great bit of software that’s essentially just a nice interface to Docker service. This means we can have zero downtime deployments – which just means there is never any time where it’s not serving requests – with the HEALTHCHECK command.

Sadly, because I used a mounted folder from the server – or persisted directory as Caprover calls it – I couldn’t simply add the HEALTHCHECK command and have it work. I needed to resolve that situation first. The reason I did this though was so I didn’t have to commit my binary files – images and such – to git as that would bloat out the repository.

Here’s a short list of the options I considered:

  1. Just committing the files to git
  2. Hosting the files on a separate subdomain/application
  3. Magicking the files into the Docker image

I ended up going with the last one as I’ve done that for the documentation on taylormadetech.dev. The way I magic the files into that Docker image is to go and download a zip using wget for the documentation for each version. I know what files to download because I have the git tags. In this project I don’t have that, I have a bunch of arbitrary files that aren’t known at build time.

This works great for taylormadetech.dev because those zip files never change, so the fact that Docker caches the image layer and doesn’t re-run the wget command is a benefit and not a hindrance.

Docker ADD saved the day here for the blog. Essentially this will bring in a file or many files from different locations. It also very handily supports Uniform Resource Locators (URLs) so I can download a zip file from my personal server and extract it in the Docker image. The wonderful thing is it always downloads the URL and if it has changed it busts the layer cache.

Here’s the relevant part of the multi-stage Docker image I use.

FROM debian:latest AS data
WORKDIR /data

RUN apt-get update && \
  apt-get install unzip -y

ADD https://redacted-url/data.zip /data/

RUN unzip data.zip

RUN rm data.zip

If I used tar instead I could drop the installation and usage of unzip but I haven’t implemented that out of sheer laziness.

Ventoy

Ventoy creates a bootable Universal Serial Bus (USB) drive that lets you select from many ISO files stored on the drive to boot. This means that you don’t need to reflash your USB drive every time you want to boot a different ISO, you can just copy the ISOs into the root of the USB drive instead.

It’s a small life improvement but a welcome one.

Git Changelog

I have a useful alias for my git that I’ve shared around at work. I figure I’ll share it here too even though it will not work unless you mark your last production release with a git tag. You will need to replace production-release in the alias with whatever you use to tag your production deployments.

Add this code to your ~/.gitconfig and you’ll be able to run git changelog.

[alias]
	changelog = log --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) %C(yellow)[%an]%C(reset) %C(white)%s%C(reset)' origin/production-release..origin/main

The output should look something like the below.

A terminal displaying the below.

The git hashes are blue and bold, the username is yellow, and the message is
white.

$ git changelog
14fe23c [Sean Earle] Added Circle#overlaps? and Circle#colour now defaults to Colour::BLACK
875092e [Sean Earle] Add Vector2#overlaps?
990a887 [Sean Earle] Add Rectangle#includes?
c2bd8b1 [Sean Earle] Add Colour#contrast and Colour#contrast!
5fccabf [Sean Earle] Improve the speed of web tests
b6bd0b7 [Sean Earle] Add a pull request template
0346837 [Sean Earle] Documentation test now requires all ruby files
c1fe70e [Sean Earle] Fix Window documentation

Other Blog Posts

  • Why My Newsletter Costs $2.50: A great read about why charging a small amount can make a lot of sense for creators. It really gels with my opinions on pricing indie games.

  • I Am An AI Hater: An article that pretty well summarises my feelings towards Artificial Intelligence (AI).

  • State of Hanami 2025: It’s been an amazing year for Hanami and I really need to get off my bum and try it out.