Skip to content

Automatické nasazení dokumentace s git post-receive hookem

Jak už jsem psal dříve, tenhle web je vytvořený s Material for MkDocs a nasazení probíhá automaticky pomocí příslušné Github action. Je to velmi pohodlné, nemusím se o nic starat.

Zároveň už si nějakou dobu tvořím osobní znalostní bázi, také formou dokumentace pomocí Material for MkDocs (o tom třeba někdy v budoucnu). Pointa byla tvořit jí v textových souborech (v Markdownu) a mít jí dostupnou na všech zařízeních. Píšu si tam i dost soukromé věci, takže bázi nechci mít vystavenou veřejně na internetu jako tenhle web. Logickou volbou bylo tedy zkusit ji nasadit v rámci nového home labu.

Když jsem přemýšlel jak bázi nasadit a zpřístupnit, Claude mi navrh využít git post-receive hook. Návrh se mi zalíbil. Jedná se o jeden shellový script, který dokumentaci sestaví potom co udělám git push do daného repozitáře. Výsledný web je přístupný přes VPN pomocí tailscale serve.

Níže je příklad zmíněného git hooku v bare repozitáři na serveru.

hooks/post-receive
#!/bin/bash
#
# Build and deploy MkDocs documentation when main branch is pushed.
#

# The usual Bash safety net
set -o errexit
set -o nounset
set -o noglob
set -o pipefail

clone_dir="${HOME}/build/knowledge"
web_dir="${HOME}/web/knowledge"

unset GIT_DIR  # The envvar confuses git when cd into a different dir

while read -r oldsha newsha refname; do
    if [[ "${refname}" == "refs/heads/main" ]]; then
        echo "Push to main detected, building docs..."
        cd "${clone_dir}"

        # The repo is meant as pull-only, local changes are overridden.
        # Necessary for resolving force pushes.
        git fetch origin
        git reset --hard origin/main

        "${HOME}/.local/bin/uv" run mkdocs build --clean
        rm -rf "${web_dir}"
        cp -r site/ "${web_dir}"
        echo "Done. Docs deployed to ${web_dir}"
    fi
done

Zprovoznit daný skript byla trochu fuška, protože shellové prostředí git hooku je omezené (proto je tam např. ta úplná cesta k uv). Ale povedlo se. Zdá se, že to funguje dobře, a už jsem tenhle pattern použil i v jiném projektu.

Update: Lehce jsem poupravil text a explicitně uvedl, že git hook se nasazuje na serveru.