Weekly Brain Dump #2
At a Glance
- LocalCI: An overhaul of the output styles
- Zero Downtime Deployments for this Blog: How I don’t drop any requests during a deployment
- Ventoy: Booting many ISOs off of one USB drive
- Git Changelog: An alias for git that makes generating changelogs easy
- Other Blog Posts: Interesting blog posts I read this week
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:
- Just committing the files to git
- Hosting the files on a separate subdomain/application
- 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.
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.