From 09d236ded5cb1facc0df8570dec7f42fc20b841f Mon Sep 17 00:00:00 2001 From: CroneKorkN Date: Sun, 10 May 2026 21:27:40 +0200 Subject: [PATCH] left4me: trigger alembic_upgrade from git_deploy (catch migrations on code updates) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pip_install's `unless` (import l4d2host, l4d2web) skips when both packages are already installed — so on a code-only apply, pip_install doesn't fire and alembic_upgrade (which it triggers) never runs. The new 0008 migration would silently get skipped, leaving the DB out of sync with the new schema. Wire git_deploy → alembic_upgrade directly. alembic upgrade head is idempotent (no-op when at head); seed_overlays + service:restart cascade off alembic, so editable-install code changes also get picked up by gunicorn. Edge case noted (deferred): a migration-only change with no code change has the same matching git rev, so this won't fire either. In practice migrations always come with the code change that uses them. --- bundles/left4me/items.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/bundles/left4me/items.py b/bundles/left4me/items.py index 0e8c880..37cdd2e 100644 --- a/bundles/left4me/items.py +++ b/bundles/left4me/items.py @@ -135,12 +135,23 @@ git_deploy = { '/opt/left4me/src': { 'repo': node.metadata.get('left4me/git_url'), 'rev': node.metadata.get('left4me/git_branch'), - # No triggers list — both downstream actions (chown_src and - # pip_install) run every apply gated by their own `unless` - # guards, which makes the chain self-healing after a partial - # failure. Chaining via triggers would have made them only - # fire when git_deploy itself fired, leaving stuck states - # unrecoverable. + 'triggers': [ + # On a code-update apply, refresh the DB schema. pip_install + # would have triggered alembic in the create_venv path, but on + # a normal apply pip_install's `unless` skips (packages still + # importable from the previous editable install), and that + # would leave alembic_upgrade dormant. Wiring git_deploy → + # alembic directly ensures new migrations land whenever new + # code lands. alembic upgrade head is idempotent (no-op when + # already at head), so this is safe to fire on every code + # update; the seed_overlays + service:restart cascade off + # alembic also covers picking up the new code in gunicorn. + 'action:left4me_alembic_upgrade', + ], + # chown_src and pip_install are NOT in triggers — they run every + # apply gated by their own `unless` guards, which makes the chain + # self-healing after a partial failure. (Items in a triggers list + # must be triggered:True, which would lose that property.) }, }