I’m pretty sure that after every conference that I’ve ever organised, I’ve loudly proclaimed that my organising days were behind me.
Yet here we are. Hope to see you at tiny ruby #{conf}
in November.
I’m pretty sure that after every conference that I’ve ever organised, I’ve loudly proclaimed that my organising days were behind me.
Yet here we are. Hope to see you at tiny ruby #{conf}
in November.
If you own a DJI drone and have imported videos from it to your Apple Photos library, you may have noticed that the GPS coordinates are not recognised in Apple’s software.
This is because DJI writes the GPS data to a different metadata field than what Photos.app expects. I don’t know if this is a bug on DJI’s or Apple’s side, but it’s annoying nonetheless.
Luckily, we can use exiftool to extract the GPS coordinates and the macOS avmetareadwrite
CLI tool to fix the issue.
Beer Styles 3.0.0
seems like the perfect date on which to launch version 3 of my Beer Styles app.
Eight years since the last major update, this new version is a complete rewrite of the app. It’s faster, more responsive, and easier to use than ever.
Headline features:
Download it for free from the App Store.
Just a quick experiment trying to use the Taffy layout library and image-builder crates to layout and build images in Rust.
This worked well enough to satiate my curiosity and could, for example, generate social share images à la @vercel/og.
Starring your repo on GitHub doesn’t mean that I ever want to receive your spammy emails.
I’m well aware that finding my email address through GitHub is not only possible but even trivial, but that still doesn’t make it okay for you to be a dick about it.
I considered whether I should redact the name of the project from the email, but bad behaviour deserves to be called out.
I just added code signing and notarization for PaperAge macOS binaries using GitHub Actions, so here’s a very rough guide to how I did it.
As I recently migrated this blog from Middleman to Bridgetown, I thought I could document one of my Bridgetown customizations: on-demand or build-time image resizing.
frontend/
directory and should therefore be also accessible via the Bridgetown built-in asset_path
helper or through esbuild imports.src/images/resized
so that they don’t need to be processed by esbuildWhich Ruby hash or message digest algorithm is the speediest in Ruby? My cursory Googling didn’t surface an up-to-date benchmark from anyone else so here are some rough results of my own.
Note: These algorithms are not all equivalent so don’t just blindly pick the fastest one! CRC32, MurmurHash, xxHash, and CityHash are all non-cryptographic.
Update 2024-03-11: Added OpenSSL::Digest for MD5, SHA1, SHA256, SHA512, and SHA3
100,000 iterations of hashing a 1 MiB blob of random data.
The benchmarks were run on an M1 MacBook Pro.
The benchmark source code is available on GitHub.
Simple syrup is an extremely common ingredient in cocktails and, as the name implies, very simple to make: it’s just sugar and water in a 1:1 ratio. What’s slightly less easy is knowing how much water and sugar to measure out to get a given volume of syrup.
My calculator uses the densities of water (1g/ml) and crystalline sucrose (1.5862g/ml) to do a fairly naïve estimation of the final volume.
This isn’t totally accurate because densities don’t quite work that way in real life. Possibly the most well known example of this is what happens when you mix ethanol and water (250ml + 250ml = 480ml).
However, for cocktails this gets us in the ballpark and the small difference doesn’t really matter.
Combine both ingredients in a saucepan and cook over medium heat until all the sugar has dissolved.
Transfer immediately to a heat-safe bottle or let it cool to room temperature in the saucepan and then transfer to a bottle.
Simple syrup should be refrigerated unless consumed within a day or so. The sugar content is too low to prevent the growth of microbes.
My first Rust-based project, PaperAge, is a solution for making secure paper backups of important secrets. The backups are secured with state-of-the-art cryptography using the age format.
Personally, I use it to make paper backups of the bare minimum credentials I’d need to regain access to all my online accounts and backups. For example, the 1Password recovery kit plus my email account and Apple ID credentials.
One of the requirements for PaperAge was being able to print the backups at any printer without having to trust the printer or whoever operates it. This is why the generated PDF has a blank space for the passphrase. Additionally, this allows you to store the passphrase separately for extra security (either physically or you can trust yourself to remember it).
My personal threat model doesn’t include state actors or extremely tech-savvy burglars, so just relying on physical security and/or obscurity provides a sufficient level of security for my needs. I’m mostly guarding against the unlikely event where I lose access to all my devices at the same time and have to regain access to my accounts and backups from scratch.
Equally, I didn’t want the backup solution to be dependent on any one tool or person. Not even if it was my own project. To this end, you don’t need PaperAge to recover from backups made with it. Instead, you can use either the original age CLI tool or any compatible implementation. Behind the scenes, PaperAge uses rage, the Rust port of age.
The release workflow for PaperAge is highly automated and uses cargo release to tag and publish new releases.
Pushing a release tag to GitHub kicks off a GitHub Actions workflow that will create a new draft release on GitHub, cross compile for macOS, Linux, and Windows, and publish the release once compiled. Finally, it sends a workflow_dispatch
event to the matiaskorhonen/homebrew-paper-age repository to kick off a GitHub Action that updates the Homebrew formula for PaperAge.
The Homebrew formula update action will install Homebrew, update the formula based on a template, test that the formula still works, and finally commit and push the updated formula.
Eventually, I’m planning on trying to get a PaperAge formula up-streamed to Homebrew itself, but the current Cask workflow works so well that I haven’t been very motivated to get it done so far.