Improve update and migration flow
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
# 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.
|
||||
|
||||
They are for both humans and agents:
|
||||
|
||||
- Users should know when migrations run, where state is stored, and how to retry
|
||||
or inspect pending work.
|
||||
- Agents should know which migration scope to use, how to write safe migration
|
||||
scripts, and what should **not** be a migration.
|
||||
|
||||
## The two migration scopes
|
||||
|
||||
Omarchy migrations are split by execution context:
|
||||
|
||||
```text
|
||||
migrations/system/*.sh
|
||||
migrations/user/*.sh
|
||||
```
|
||||
|
||||
### System migrations
|
||||
|
||||
System migrations run as root and must be noninteractive.
|
||||
|
||||
Use system migrations for machine-wide state, for example:
|
||||
|
||||
- `/etc` drop-ins or legacy config cleanup
|
||||
- `/boot` / bootloader cleanup
|
||||
- systemd system units or service state
|
||||
- hardware quirks
|
||||
- package-owned layout transitions
|
||||
|
||||
State lives in:
|
||||
|
||||
```text
|
||||
/var/lib/omarchy/migrations/system/<migration filename>
|
||||
```
|
||||
|
||||
### User migrations
|
||||
|
||||
User migrations run as the current graphical/login user and may be interactive.
|
||||
|
||||
Use user migrations for per-user or session-aware state, for example:
|
||||
|
||||
- `~/.config` changes
|
||||
- `~/.local` state
|
||||
- user systemd units
|
||||
- browser/editor preferences
|
||||
- DBus/session-dependent updates
|
||||
- prompts that need to happen in a visible terminal
|
||||
|
||||
State lives in:
|
||||
|
||||
```text
|
||||
~/.local/state/omarchy/migrations/user/<migration filename>
|
||||
```
|
||||
|
||||
A user migration is pending for a given user only when the script exists under
|
||||
`/usr/share/omarchy/migrations/user/` and that user's matching state file is
|
||||
missing.
|
||||
|
||||
There is no global root-owned “user migrations required” queue.
|
||||
|
||||
## 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`:
|
||||
|
||||
1. waits for any active pacman transaction to finish
|
||||
2. runs pending system migrations
|
||||
3. runs pending user migrations for the current user
|
||||
|
||||
System migrations usually already ran during the pacman transaction via the
|
||||
`omarchy` package `post_upgrade()`, but the second check is intentional and
|
||||
idempotent.
|
||||
|
||||
### During direct pacman updates
|
||||
|
||||
Raw `sudo pacman -Syu` is guarded. Users should normally run:
|
||||
|
||||
```bash
|
||||
omarchy update
|
||||
```
|
||||
|
||||
If a user explicitly bypasses the guard, the `omarchy` package still runs system
|
||||
migrations from `post_upgrade()`:
|
||||
|
||||
```bash
|
||||
omarchy-migrate-system
|
||||
```
|
||||
|
||||
User migrations are never run by pacman. Instead, the user session watches the
|
||||
packaged user migration directory and runs a notifier. The notifier checks:
|
||||
|
||||
```bash
|
||||
omarchy-migrate --pending user
|
||||
```
|
||||
|
||||
If that user has pending user migrations, it shows a notification that opens a
|
||||
terminal for:
|
||||
|
||||
```bash
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
The notifier never runs user migrations silently in the background.
|
||||
|
||||
### Manually
|
||||
|
||||
Users can safely run:
|
||||
|
||||
```bash
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
at any time. Already-completed migrations are skipped.
|
||||
|
||||
## Inspecting pending migrations
|
||||
|
||||
Use:
|
||||
|
||||
```bash
|
||||
omarchy-migrate --pending
|
||||
omarchy-migrate --pending system
|
||||
omarchy-migrate --pending user
|
||||
```
|
||||
|
||||
Exit behavior:
|
||||
|
||||
- `0` — one or more matching migrations are pending
|
||||
- non-zero — no matching migrations are pending
|
||||
|
||||
Output is scope-prefixed:
|
||||
|
||||
```text
|
||||
system/100-system.sh
|
||||
user/200-user.sh
|
||||
```
|
||||
|
||||
The lower-level runners also support `--pending` and print filenames without the
|
||||
scope prefix:
|
||||
|
||||
```bash
|
||||
omarchy-migrate-system --pending
|
||||
omarchy-migrate-user --pending
|
||||
```
|
||||
|
||||
Prefer `omarchy-migrate --pending ...` in user-facing tools and watchers.
|
||||
|
||||
## Writing migrations
|
||||
|
||||
Create a migration with:
|
||||
|
||||
```bash
|
||||
omarchy-dev-add-migration system --no-edit
|
||||
omarchy-dev-add-migration user --no-edit
|
||||
```
|
||||
|
||||
Choose the scope based on the state being changed, not on convenience.
|
||||
|
||||
### File format
|
||||
|
||||
Migrations are plain shell files:
|
||||
|
||||
- filename: unix timestamp, generated by `omarchy-dev-add-migration`
|
||||
- mode: `0644`
|
||||
- no shebang
|
||||
- start with an `echo` describing the migration
|
||||
- use `$OMARCHY_PATH` for Omarchy-owned files
|
||||
|
||||
Example system migration:
|
||||
|
||||
```bash
|
||||
echo "Remove legacy Limine config"
|
||||
|
||||
rm -f /boot/EFI/limine/limine.conf
|
||||
```
|
||||
|
||||
Example user migration:
|
||||
|
||||
```bash
|
||||
echo "Refresh user app launchers"
|
||||
|
||||
omarchy-refresh-applications
|
||||
```
|
||||
|
||||
### Execution model
|
||||
|
||||
Migration runners execute scripts with strict shell settings:
|
||||
|
||||
```bash
|
||||
bash -euo pipefail <migration>
|
||||
```
|
||||
|
||||
`$OMARCHY_PATH` is exported into the migration process.
|
||||
|
||||
A migration is marked complete only after the script exits successfully. If it
|
||||
fails, the marker is not written and the migration will be retried later.
|
||||
|
||||
Because failed migrations can be retried after doing partial work, migrations
|
||||
must be idempotent. Prefer operations that are safe to run more than once:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.config/example
|
||||
rm -f ~/.config/example/legacy.conf
|
||||
install -Dm644 "$OMARCHY_PATH/default/example.conf" ~/.config/example/example.conf
|
||||
systemctl --user enable --now some-unit.service || true
|
||||
```
|
||||
|
||||
Use `|| true` only when a failure is genuinely acceptable.
|
||||
|
||||
## What belongs in a migration?
|
||||
|
||||
Good migration uses:
|
||||
|
||||
- deleting or moving legacy files that block the packaged layout
|
||||
- marking or enabling new service state
|
||||
- migrating old config paths to new config paths
|
||||
- repairing known bad state from an earlier Omarchy release
|
||||
- one-time compatibility for existing installs
|
||||
|
||||
Bad migration uses:
|
||||
|
||||
- fresh-install setup that belongs in `install/` or `/etc/skel`
|
||||
- package installation that belongs in package dependencies or package lists
|
||||
- recurring maintenance
|
||||
- arbitrary cleanup that should be a user command
|
||||
- pre-4 upgrade work that belongs in `omarchy-upgrade-to-4`
|
||||
- hidden user/session work from pacman
|
||||
|
||||
## Fresh installs and new users
|
||||
|
||||
Fresh users created from the packaged layout should not have to run historical
|
||||
user migrations. The package seeds user migration markers into `/etc/skel` so
|
||||
new users start with shipped user migrations marked complete.
|
||||
|
||||
The ISO/finalization path also marks shipped user migrations complete for the
|
||||
freshly-created install user when running:
|
||||
|
||||
```bash
|
||||
omarchy-finalize-user --first-install
|
||||
```
|
||||
|
||||
Existing users keep their own migration state and run only migrations whose
|
||||
state files are missing.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### See what is pending
|
||||
|
||||
```bash
|
||||
omarchy-migrate --pending
|
||||
```
|
||||
|
||||
### Retry failed migrations
|
||||
|
||||
Fix the underlying problem, then run:
|
||||
|
||||
```bash
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
A failed migration is not marked complete, so it will retry.
|
||||
|
||||
### Re-run a completed migration manually
|
||||
|
||||
Remove its marker, then run the migration command again:
|
||||
|
||||
```bash
|
||||
rm ~/.local/state/omarchy/migrations/user/<migration>.sh
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
For system migrations:
|
||||
|
||||
```bash
|
||||
sudo rm /var/lib/omarchy/migrations/system/<migration>.sh
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
Be careful: migrations should be idempotent, but manually removing markers is an
|
||||
advanced troubleshooting step.
|
||||
|
||||
## Agent checklist
|
||||
|
||||
Before adding a migration:
|
||||
|
||||
1. Is this a one-time repair for existing installs?
|
||||
2. Is it system state or user/session state?
|
||||
3. Can it run safely more than once?
|
||||
4. Will it fail loudly if the important work fails?
|
||||
5. Does it avoid hidden interactive work from pacman?
|
||||
6. Does it belong in `omarchy-upgrade-to-4` instead?
|
||||
7. Did you add or update tests if behavior changed?
|
||||
|
||||
If the answer to any of these is unclear, stop and ask before adding the
|
||||
migration.
|
||||
Reference in New Issue
Block a user