🤫 Psst! Článek vyšel v roce 2022 a protože řeší technikálie, nemusí už být aktuální. Berte ho s rezervou.
Přechod na statický generátor mi dost usnadnil život, web je teď kompletně v Gitu. Včetně Jekyllem vygenerovaného výstupu, aby se snáz hledal zdroj případné chyby a nebylo třeba komplikovaně řešit deploy.
Co vidíte jako ALES.NET je vlastně obsah složky www na větvi production. Krásně efektivní řešení Blueboardu, které jsem chtěl využít naplno. V první zkušební verzi jsem tedy prostě souběžně s ručními změnami commitoval i výsledné soubory. Strašně tím ale trpěla čitelnost jednotlivých commitů a vznikalo velké množství merge konfliktů.
Například každá změna CSS musela automaticky sáhnout na všechny HTML soubory a přepsat vygenerovaný cache-obcházející hash v <head>. Kvůli čemuž bylo zároveň potřeba při vývoji žonglovat mezi plným a přírůstkovým buildem. Ten je sice experimentální, ale funguje dobře a potřebný čas stáhne klidně na pětinu.
Jak z toho ven?
Řešením konfliktů bude commitovat složku www jen na větvi production a všude jinde ji ignorovat. Při vývoji se navíc naplno využije rychlost přírůstkového buildu s livereloadem a před nasazením změn se spustí ten plnohodnotný. To vše automaticky pomocí jednoduchého skriptu.
Pre-push hook krok za krokem (celý skript níže)
Jakmile teď tedy v hlavní vývojové větvi main nastřádám dost změn k nasazení, stačí se přepnout na production a pushnout. Pak se spustí to správný tóčo. Tedy po kontrole aktuální větve:
if [ "$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)" == "production" ]; then
Poté se změny z main začlení a Jekyll udělá čistý build:
git merge main
docker exec alesnet-jekyll-1 jekyll clean
docker exec alesnet-jekyll-1 jekyll build
Vynutí se commit adresáře www s buildem, který je jinak .gitignorován, aby při přepínání větví nevznikaly problémy. Commit díky podmínce neproběhne, pokud v adresáři není nic nového. A pokud ano, rovnou se pushne a tím i nasadí:
git add www -f
if ! git diff-index --quiet HEAD; then
git commit -m "Jekyll build"
git push --no-verify
fi
Pokud Jekyll změnil sitemapu, pingne se Googlu a zobrazí osekaná odpověď:
if ! git diff HEAD~1 HEAD --exit-code -s www/sitemap.xml; then
curl --silent "https://www.google.com/ping?sitemap=https://ales.net/sitemap.xml" | grep "<h2>"
fi
Pak se automaticky vrátíme na větev main. Tím však přijdeme o obsah složky www, který jsme nechali na předešlé větvi. Proto ještě Jekylla donutíme k novému buildu:
git checkout main
docker exec alesnet-jekyll-1 jekyll build
A jsme zpátky na vývojové verzi. Tentokrát ovšem se změnami procpanými na produkci a bez zaplevelené historie.
Celý soubor .githooks/pre-push
Když se všechno poslepuje, vznikne finální soubor:
#!/bin/sh
set -e
if [ "$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)" == "production" ]; then
git merge main
docker exec alesnet-jekyll-1 jekyll clean
docker exec alesnet-jekyll-1 jekyll build
git add www -f
if ! git diff-index --quiet HEAD; then
git commit -m "Jekyll build"
git push --no-verify
fi
if ! git diff HEAD~1 HEAD --exit-code -s www/sitemap.xml; then
curl --silent "https://www.google.com/ping?sitemap=https://ales.net/sitemap.xml" | grep "<h2>"
fi
git checkout main
docker exec alesnet-jekyll-1 jekyll build
fi
Git neverzuje svou složku .git/hooks, takže jsem hook hodil do vlastní, nastavil mu chmod +x a teprve pak commitnul. Aby se hook s následujícím pushem použil, stačí už jen upravit .git/config příkazem:
git config core.hooksPath .githooks
Tadá, od teď bude historie změn a jejich nasazení jako ze škatulky. ✨