The retired omarchy-update-user-notify.path stays loaded in sessions that started before the update removing it, and pacman writes the migrations directory mid-transaction, so it fired a critical toast for migrations that omarchy-migrate was about to apply a step later. Migration 1785095882 stops that watcher, but migrations run after pacman, so it lands 11 seconds too late to prevent the toast it exists to retire. Check the lock omarchy-update holds for its whole pipeline instead of trusting that no trigger exists. That covers the stale watcher and anything added later: during an update every pending migration is by definition already being applied. The check repeats after waiting for the notification server, which is long enough for an update to start underneath it. Only this user's runtime directory is read, never the /tmp path the updater falls back to without XDG_RUNTIME_DIR. A shared lock file belongs to whoever created it first, so honouring it would let one user silence another user's notification; a redundant toast is the better failure. The sleep inhibitor now starts with the lock descriptor closed. It outlives the step that starts it, so an update killed before restore_update_inhibitors left it holding the flock indefinitely. That already blocked later updates, and now that the notifier reads the same lock it would have silenced migration notices at every login. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
161 lines
4.1 KiB
Markdown
161 lines
4.1 KiB
Markdown
# Omarchy migrations
|
|
|
|
Omarchy migrations are one-time repair scripts for existing installs. They are
|
|
used when a package update needs to change state that pacman cannot safely own by
|
|
itself.
|
|
|
|
## Migration model
|
|
|
|
Migrations live in:
|
|
|
|
```text
|
|
migrations/*.sh
|
|
```
|
|
|
|
They run as the current Omarchy user through `omarchy-migrate`, normally during
|
|
`omarchy update`. A migration may touch user/session state (`~/.config`,
|
|
`~/.local`, user systemd, browser/editor prefs, DBus/session state), and may also
|
|
perform machine-wide repairs when needed.
|
|
|
|
Completion state is per-user:
|
|
|
|
```text
|
|
~/.local/state/omarchy/migrations/<migration filename>
|
|
```
|
|
|
|
That means every user gets a chance to run every migration. Migrations run as the
|
|
user; privileged operations should invoke the appropriate helper or privilege
|
|
prompt themselves. Migrations must be idempotent: if one user already applied a
|
|
machine-wide repair, the same migration running for another user should detect
|
|
that and no-op.
|
|
|
|
## When migrations run
|
|
|
|
### During `omarchy update`
|
|
|
|
`omarchy update` is the normal update path. It runs package updates, then:
|
|
|
|
```bash
|
|
omarchy-migrate
|
|
omarchy-hook post-update
|
|
```
|
|
|
|
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
|
|
all pending migrations for the current user in the visible update terminal.
|
|
|
|
### At login
|
|
|
|
Every graphical login starts `omarchy-migrate-notify.service` after
|
|
`graphical-session.target`. The notifier checks:
|
|
|
|
```bash
|
|
omarchy-migrate --pending
|
|
```
|
|
|
|
It stays silent while `omarchy update` holds its lock, since that update applies
|
|
the pending migrations itself.
|
|
|
|
If that user has pending migrations, it shows a notification that opens a
|
|
terminal for:
|
|
|
|
```bash
|
|
omarchy-migrate
|
|
```
|
|
|
|
The notifier never runs migrations silently in the background.
|
|
|
|
This is what covers users who did not run the update themselves: someone who
|
|
bypassed the pacman guard with `sudo env OMARCHY_ALLOW_DIRECT_PACMAN=1 pacman
|
|
-Syu`, and any second user on the machine, whose migration markers are per-user
|
|
and therefore still missing after another user updated.
|
|
|
|
Login is the only trigger on purpose. Watching the packaged migration directory
|
|
also fires during a normal `omarchy update`, which prompts for migrations that
|
|
`omarchy-migrate` is about to run in the visible update terminal.
|
|
|
|
### Manually
|
|
|
|
Users can safely run:
|
|
|
|
```bash
|
|
omarchy-migrate
|
|
```
|
|
|
|
at any time. Already-completed migrations are skipped.
|
|
|
|
## Inspecting pending migrations
|
|
|
|
Use:
|
|
|
|
```bash
|
|
omarchy-migrate --pending
|
|
```
|
|
|
|
Exit behavior:
|
|
|
|
- `0` — one or more migrations are pending
|
|
- non-zero — no migrations are pending
|
|
|
|
Output is one pending migration per line:
|
|
|
|
```text
|
|
1781158082.sh
|
|
```
|
|
|
|
## Creating a migration
|
|
|
|
Use the helper:
|
|
|
|
```bash
|
|
omarchy-dev-add-migration --no-edit
|
|
```
|
|
|
|
This creates:
|
|
|
|
```text
|
|
migrations/<unix timestamp>.sh
|
|
```
|
|
|
|
New migration format:
|
|
|
|
- File permissions must be `0644` (`-rw-r--r--`). Migration runners execute them
|
|
with `bash -euo pipefail`, not through executable bits.
|
|
- No shebang line.
|
|
- Start with an `echo` describing what the migration does.
|
|
- Use `$OMARCHY_PATH` to reference the Omarchy directory.
|
|
- Be idempotent. Check existing state before changing it.
|
|
- Use helper commands such as `omarchy-cmd-present`, `omarchy-cmd-missing`,
|
|
`omarchy-pkg-add`, `omarchy-pkg-drop`, `omarchy-pkg-present`, and
|
|
`omarchy-pkg-missing` when appropriate.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
echo "Relink Neovim theme to Omarchy current state"
|
|
|
|
theme_link="$HOME/.config/nvim/lua/plugins/theme.lua"
|
|
current_relative_target="../../../../.local/state/omarchy/current/theme/neovim.lua"
|
|
|
|
[[ -L $theme_link ]] || exit 0
|
|
ln -sfn "$current_relative_target" "$theme_link"
|
|
```
|
|
|
|
## Testing migrations
|
|
|
|
Run a migration against a temporary home when possible:
|
|
|
|
```bash
|
|
HOME=$(mktemp -d) bash -euo pipefail migrations/<timestamp>.sh
|
|
```
|
|
|
|
To rerun a migration locally, remove its marker and run the migrator:
|
|
|
|
```bash
|
|
rm ~/.local/state/omarchy/migrations/<migration>.sh
|
|
omarchy-migrate
|
|
```
|
|
|
|
Omarchy 4.0 is upgraded through `bin/omarchy-upgrade-to-quattro`, not through the
|
|
normal migration runner. Do not add compatibility migrations for old installer
|
|
layouts; put pre-4 package-layout transition work in the upgrade command instead.
|