"You wouldn't steal a car" campaign pirated content

I can’t stop laughing at this. It’s so fitting for that ad campaign:

Rib :ms_red_panda: (@Rib) fedi.rib.gay

In a reply someone pointed out that they also stole the music.

(seen via Justin’s blog)

osh is a great drop in bash replacement

Nine Reasons to Use OSH oils.pub

I’ve starting using osh for testing my bash scripts (mostly used in build and deployments). It’s been great for both giving better error messages and spotting problems shellcheck mightn’t catch.

This has been my favourite so far:

osh -o strict:all ./myscript.sh
    if assert_task_definition_is_older "${task_definition}" "deployed"; then
    ^~
myscript.sh:119: errexit was disabled for this construct

    if assert_task_definition_is_older "${task_definition}" "deployed"; then
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
myscript.sh:119: fatal: Can't run a proc while errexit is disabled. Use 'try' or wrap it in a process with $0 myproc

This leads to this interesting note on how errexit and if statements invoking shell functions lead to surprising behaviour (basically errexit is disabled).

The Gist: Trans rights are Data rights thegist.ie

Great analysis of both the recent UK court ruling and a recent CJEU ruling on trans rights. The CJEU ruling is much more relevant to Ireland but got no press coverage.

Using uv for Django projects

uv can be used to bootstrap Python for a Django project on a machine with nothing else except uv installed.

Rough steps:

  1. Install uv. This is the trickiest bit but sets you up well for future projects.
  2. Create a Python project
  3. Add Django as a dependency to the project
  4. Run Django commands using uv (uv run django-admin or uv run python manage.py)

An example using the Django tutorial’s first steps:

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# If you need curl try `brew install curl or `apt-get install curl` or `yum install curl`

# Create a python project
uv init djangotutorial

# Go into the project folder
cd djangotutorial

# Add Django
uv add django

# Initialize a Django site
uv run django-admin startproject mysite .

# Run the site
uv run python manage.py runserver

# Go to http://localhost:8000/

Where the tutorial says python manage.py you can pretty much always use uv run python manage.py.

The other nice feature of this approach over the usual Django tutorial is you start out with a project Python project, ready to package and deploy.

Pin your GitHub Actions

Just going to echo this post:

Pin your GitHub Actions michaelheap.com

Pin your actions!

I’ve done it in my work, and while it’s a little tedious to setup initially it’s not to bad with dependabot updating them automatically.

My First Playdate Game!

I helped organize Dublin GameCraft 2025.

I also created my first Playdate game:

Pop Your Bubble by Michael Twomey micktwomey.itch.io

The theme was pop and I really wanted to use the crank somehow.

I have to say, I really enjoyed the process of developing for the Playdate. It helps that the SDK was heavily inspired by LÖVE, which is a lovely development environment.

You can see all the other submissions here.

PostgreSQL NOT NULL can be added without locking

There’s bit of an interesting rabbit hole with NOT NULL constraints vs locking up your DB.

It starts with “is a NOT NULL check contraint worse than a NOT NULL”?

The docs hint at some difference: https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-NOT-NULL

SO thread: https://dba.stackexchange.com/questions/158499/postgres-how-is-set-not-null-more-efficient-than-check-constraint

Which points to https://dba.stackexchange.com/questions/66840/add-not-null-constraint-to-large-table-without-table-scan

Which finally points to https://dba.stackexchange.com/questions/267947/how-can-i-set-a-column-to-not-null-without-locking-the-table-during-a-table-scan/268128#268128

The big problem is adding a NOT NULL constraint can badly lock up the table and other sessions.

Using a constraint with NOT VALID and then validating later is a work around.

There’s a third step you can do: add a NOT NULL after this an PostgreSQL will do a no-lock update.

First add the constraint:

-- short-time exclusive lock
alter table foos 
  add constraint foos_not_null 
  check (bar1 is not null) not valid;

Next validate it:

-- seqscan, but without exclusive lock, concurrent sessions can read/write
alter table foos validate constraint foos_not_null;

Finally add not null and drop constraint:

-- exclusive lock, but foos_not_null proves: there is no NULL in this column
-- so this alter table would be fast
alter table foos alter column bar1 set not null;
-- not needed anymore
alter table foos drop constraint foos_not_null;

There is also an approach of adding a NOT NULL with a default value, PostgreSQL optimizes this case: https://brandur.org/postgres-default

ALTER TABLE users
    ADD COLUMN credits bigint NOT NULL DEFAULT 0;