Azt szeretnénk elérni, hogy a helyi gépről pusholt változásaink után a távoli gép automatikusan generálja le Hugóval a statikus oldalt a webrootba. Tehát a git push művelet legyen egyben publikálás is. Az ilyen beállítás különösen jól jöhet akkor, ha git-használó szerkesztők dolgoznak a tartalmon (pl. technikai dokumentáción).

Távoli gép (VPS)

Hugo telepítése

A szerveren szükség van Hugóra, mert ott állítjuk elő majd a weboldalt. Ezúttal nem Debian-repóból és nem is forrásból telepítünk, hanem letöltjük GitHubról a kiválasztott verziót. Csak az áttekinthetőség kedvéért használok változókat:

$ DEB="hugo_extended_0.90.1_Linux-64bit.deb"
$ CS="hugo_0.90.1_checksums.txt"
$ wget https://github.com/gohugoio/hugo/releases/download/v0.90.1/$DEB
$ wget https://github.com/gohugoio/hugo/releases/download/v0.90.1/$CS
$ grep $DEB $CS | shasum --check --status && sudo dpkg -i $DEB

Git repó

Hozzunk létre egy üres git repót és benne egy hookot:1

$ mkdir /path/myproject.git
$ cd /path/myproject.git
$ git init --bare
$ nano hooks/post-receive
$ chmod +x hooks/post-receive

A post-receive szkript tartalma:

#!/bin/bash
TARGET=/srv/www/myproject
GIT_DIR=/path/myproject.git
GIT_BRANCH=master

symlink() {
    ln -s "$1" public.tmp && mv -Tf public.tmp public
}

while read oldrev newrev ref
do
    if [[ $ref = refs/heads/$GIT_BRANCH ]]
    then
        /usr/bin/git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $GIT_BRANCH
        pushd $TARGET
        mkdir -p releases/recent
        [[ -d releases/current ]] && /usr/bin/rsync -aq releases/current/ releases/recent
        symlink releases/recent
        /usr/bin/npm ci
        /usr/local/bin/hugo -d releases/current
        symlink releases/current
        popd
    fi
done

A $TARGET/public szimbolikus link a webroot. Nodejs legyen telepítve, a package-lock.json legyen komitolva.

Helyi gép (dev)

Itt már rendelkezünk a projektünk git repójával, amelyhez most felveszünk egy új push URL-t. Csinálhatunk új remote-ot, vagy a meglévő originhez adjuk hozzá,2 mint itt:

$ git remote -v
$ git remote set-url --add --push origin git@github.com:myuser/myproject.git
$ git remote set-url --add --push origin myuser@mydomain.hu:/path/myproject.git

A meglévő URL-t is hozzá kell adni, ezért írattuk ki (a fenti példában a githubos). Készen vagyunk, ugyanúgy pusholunk, mint eddig, de van automatikus zero downtime deploymentünk.

Hibaelhárítás

Amint látható, ez egy meglehetősen egyszerű szkenárió, ahol nem okoz nagy gondot, hogy közvetlenül az éles szerverre publikálunk, nincs se staging környezet, se development branch. Egyrészt ha szükségessé válik, ezek bármikor beiktathatók. Másrészt ha egy felhasználó elkövetne valami olyan hibát, amelynek a felmérése és javítása némi időbe kerülne, gyors intézkedésként elég lenne visszaállítani egy korábbi komitot, amire egy szkripttel is készülhetünk:

#!/bin/bash
TARGET=/srv/www/myproject
GIT_DIR=/path/myproject.git

/usr/bin/git --work-tree=$TARGET --git-dir=$GIT_DIR checkout HEAD~1
pushd $TARGET
/usr/bin/npm ci
/usr/local/bin/hugo -d releases/current
popd

Vagy:

$ ln -sf $TARGET/releases/recent $TARGET/public