ZpětDevOps

Testování migračních skriptů s Dockerem

Říjen 20255 min

SQL migrace jsou kód. Přesto v mnoha týmech zůstávají posledním artefaktem, který se nasazuje na dobré slovo — jednou se napíšou, v review se přelétnou očima a poprvé naostro běží až v produkci, nad reálnými daty. Nejspolehlivější test je přitom stejný jako u čehokoli jiného: proti skutečné databázi, která se chová jako produkce.

Migrace si zaslouží víc podezřívavosti než běžný kód, ne míň. Běží právě jednou, mění stav, který se špatně vrací zpět, a spouštějí se uprostřed deploye — přesně ve chvíli, kdy se všichni dívají a nikdo nestojí o překvapení. Takový rizikový profil volá po nudném, opakovatelném testovacím setupu — a přesně ten Docker nabízí.

Spusťte dočasnou databázi

Docker dělá z izolovaného testování migrací triviální záležitost. Jeden příkaz mi dá čistý Postgres, který žije přesně tak dlouho jako testovací běh:

# Spusťte dočasný Postgres
docker run --rm -e POSTGRES_PASSWORD=pass -p 5432:5432 postgres:16

Stejný příkaz běží u mě, u kolegy i v CI — jedno prostředí, nula výmluv. Celý vtip je ve flagu --rm. Kontejner po skončení testu zmizí a každý běh startuje ze známého, prázdného stavu — žádné tabulky z minulého experimentu, žádný drift schématu mezi mým strojem a strojem kolegy. Nad čistou instancí pak přehraju celý řetěz migrací od úplně prvního souboru. Tenhle jediný zvyk odhalí celou třídu chyb: chybějící defaulty sloupců, které se projeví jen na čerstvé instalaci, indexy, které zamknou tabulku na dlouhé minuty, a dotazy, které na deseti řádcích létaly a na deseti milionech se plazí.

Dvě pravidla drží kontejner poctivý. Zaprvé: zafixujte image na přesnou major verzi produkce — postgres:16 nic neznamená, když produkce jede na čtrnáctce, protože DDL, které jedna verze přijme, druhá klidně odmítne. Zadruhé: nahrajte realistická data — anonymizovaný dump nebo generované fixtury v produkčním měřítku. ALTER TABLE nad 200 řádky vám o ALTER TABLE nad 20 miliony neřekne vůbec nic.

Pouštějte stejné kontroly jako v produkci

Lokální test je jen polovina práce. Na mém stroji migrace projde vždycky; zajímá mě, jestli projde i v pátek odpoledne, když ji pouští někdo úplně jiný. Proto kontroly patří do CI, kde poběží na každém pull requestu — bez ohledu na to, jestli si na ně někdo vzpomene. Můj migrační job dělá pět věcí:

  • Migrace z nuly: aplikuje všechny migrace popořadě na prázdnou databázi — důkaz, že řetěz pořád funguje pro čerstvé prostředí.
  • Migrace z aktuálního stavu: obnoví snapshot produkčního schématu a aplikuje jen nové soubory — důkaz, že diff funguje nad stavem, na kterém skutečně záleží.
  • Smoke dotazy: spustí hrstku dotazů, na kterých aplikace stojí, a ověří, že pořád vracejí smysluplné výsledky.
  • Rollback: pustí down migraci a smoke dotazy zopakuje. Down migrace tiše hnijí, dokud je nic necvičí.
  • Měření času: zaloguje trvání každého příkazu a jeho zámků. Migrace, která na čtyřicet vteřin zablokuje zápisy, není migrace, ale výpadek s razítkem.

Nic z toho není exotika. Je to stejná disciplína, kterou dávno aplikujeme na aplikační kód — automatické testy, reálné závislosti, rychlá zpětná vazba — konečně namířená na jediný skript, který má root přístup k datům. Setup stojí jedno odpoledne; první špatný index, který chytí, ho zaplatí.

Cílem je jistota, ne štěstí. Než se deploy pipeline dostane k migračnímu kroku, ten samý skript už běžel proti stejnému enginu, nad daty produkčního tvaru, v kontejneru, který po sobě nikdo nemusel uklízet. Produkční běh tak přestává být událost a stává se reprízou — a nudné reprízy jsou přesně to, co od svých deployů chcete.

Další

Zpět na přehled