1
Migrations
David Young edited this page 2026-10-26 16:01:09 -06:00

Migrations

A migration is a script that update runs once on each machine. It's how machines installed before a change catch up with it.

When you need one

If you change install.sh, or a script it calls, and machines that are already installed need the change too, add a migration. Package, service and pipx changes don't need one; see the table in How CoreDesktop Works.

Adding one

cd ~/Projects/coredesktop
$EDITOR migrations/$(date +%s).sh

Usually the migration calls the same script as the installer, so both paths share one copy of the logic:

#!/bin/bash

# Turn on the ufw firewall
bash "$HOME/.local/share/coredesktop/system/firewall.sh"

How they run

  • updates.d/12-migrations.sh runs them during update, and install.sh runs them at the end of every install.
  • They run oldest first (by filename), with bash, as the user.
  • A migration is recorded in ~/.local/state/coredesktop/migrations/<name> only when it exits 0.
  • The first failure stops the run, so a later migration never runs before an earlier one. The failed one is retried on the next update.

Rules

  • Make it safe to repeat. Fresh installs run every migration, right after install.sh has done the same work. A failed migration also runs again.
  • Exit non-zero on failure, and only then. If you exit 0 when it didn't work, the migration is recorded and never runs again. If you exit non-zero when it did work, it blocks every later migration.
  • Don't assume tools work yet. Migrations run right after the pacman upgrade, before 60-pipx.sh and 80-gnome-extensions.sh repair things. After a Python upgrade, for example, pipx apps such as gext are broken. Source utils.sh and use a helper such as ensure_gext to repair what you need.
  • Check the outcome, not the starting state. For example, enable an extension even if it was already installed, in case an earlier run stopped half-way.
  • Never rename or delete a migration that has been pushed. Machines track migrations by filename.

Example

#!/bin/bash

# Install the Tailscale GNOME extension
source "$HOME/.local/share/coredesktop/utils.sh"

ext="tailscale-gnome@diskmth.fr"
ensure_gext || exit 1
if ! ~/.local/bin/gext list | grep -q "$ext"; then
  ~/.local/bin/gext --filesystem install "$ext" || exit 1
fi
# Enable even if it was already installed, in case an earlier run stopped short
~/.local/bin/gext --filesystem enable "$ext"

Checking a machine

ls ~/.local/share/coredesktop/migrations/   # all migrations
ls ~/.local/state/coredesktop/migrations/   # the ones that have run
bash ~/.local/share/coredesktop/migrations/<name>.sh; echo "exit: $?"   # run one by hand to see the error