Fix detection of "new migrations" in omarchy-update (#219)

Previously, `omarchy-update` used the timestamp of the most recent git
commit to determine which migrations are "new" and should be executed.

Unfortunately, that strategy can (and did) fail in certain scenarios. If
a migration was generated at time T1 but not merged until time T3, and
meanwhile omarchy's `master` branch was updated to a new release with
commit timestamp T2 (where T1 < T2 < T3), then anyone who runs
`omarchy-update` between T2 and T3 would end up with `last_updated_at`
equal to T2; thus, on their next `omarchy-update` it would fail to
detect the migration with timestamp T1 as a "new" migration that should
be executed.

This commit changes the strategy for detecting "new" migrations to avoid
that problem. Rather than recording the most recent commit's timestamp,
we record its SHA. Then, after pulling the new changes, we can leverage
`git diff --name-only --diff-filter=A $SHA.. migrations/*.sh`
to return precisely the list of migration files that were introduced by
our `git pull`. It doesn't matter if any of those migrations have a
timestamp that was earlier than the timestamp of the commit we started
on - we will always execute *every* migration that didn't exist before
our `git pull`!
This commit is contained in:
Richard Macklin
2025-07-20 15:55:22 -07:00
committed by GitHub
parent dca7e9a8e8
commit f81983ec50

View File

@ -3,11 +3,11 @@
cd ~/.local/share/omarchy
if [[ $1 == "all" ]]; then
# Run all migrations
last_updated_at=1
# Run all migrations since the root commit
migration_starting_point=$(git log --max-parents=0 --first-parent --format="%H")
else
# Remember the version we're at before upgrading
last_updated_at=$(git log -1 --format=%cd --date=unix)
# Remember the commit we're at before upgrading in order to only run new migrations
migration_starting_point=$(git log -1 --format=%H)
fi
# Get the latest while trying to preserve any modifications
@ -15,14 +15,12 @@ git pull --autostash
git diff --check || git reset --merge
# Run any pending migrations
for file in migrations/*.sh; do
for file in $(git diff --name-only --diff-filter=A $migration_starting_point.. migrations/*.sh); do
filename=$(basename "$file")
migrate_at="${filename%.sh}"
if [ $migrate_at -gt $last_updated_at ]; then
echo -e "\e[32m\nRunning migration ($migrate_at)\e[0m"
source $file
fi
echo -e "\e[32m\nRunning migration ($migrate_at)\e[0m"
source $file
done
# Back to where we came from