Git Deployment: Używanie Git do publikowania stron internetowych

Jednym z największych problemów występujących przy pracy nad stronami internetowymi jest aktualizacja strony, która jest aktywnie odwiedzana przez użytkowników. Od dłuższego czasu próbowałem różnych rozwiązań, ale zawsze występowały jakieś problemu, lub był element, który mi się nie podobał. Wydaje mi się, że udało mi się w końcu osiągnąć pożądany cel za pomocą systemu kontroli wersji Git.

Zacznę od końca, czyli jak obecnie wygląda proces aktualizowania strony. Posiadam dwie kopie bazy danych (produkcyjną i deweloperską), oraz dwie uruchomione kopie strony(produkcyjną i deweloperską, które korzystają z odpowiadających im baz danych). Testując nowe funkcjonalności, są one od razu widoczne na stronie deweloperskiej (dostępnej tylko dla mnie). Za każdym razem jak zapisuję plik, jest on wysyłany na serwer deweloperski przez FTP. Po przetestowaniu danej funkcjonalności, dodaję odpowiednie pliki do repozytorium, a następnie zmiany są wysyłane do strony produkcyjnej. Istotny jest fakt, że wysyłane są tylko zmiany. Zatem jeśli na serwerze produkcyjnym istnieją pliki (np. obrazki dodane przez użytkowników), które nie występują ani w repozytorium, ani na serwerze deweloperskim, nie zostaną one nadpisane/usunięte. Rozwiązanie niezwykle bezpieczne, a zarazem wygodne.

Do funkcjonowania takiego środowiska potrzebujemy Git zarówno na serwerze, jak i na komputerze lokalnym. Na Windowsa polecam Github, który zainstaluje nam msysGit, Windows PowerShell, oraz aplikację do obsługi repozytoria lokalnych i tych zamieszczonych na Github. Jeżeli używamy Git po raz pierwszy, polecam zapoznać się z biblią Git.

Ustawienia serwera

Na serwerze musimy utworzyć aż dwa repozytoria. Wynika to ze specyfiki działania Git, który nie pozwala na wysyłanie zmian do repozytorium w którym posiadamy „dirty working directory”, lub po polsku brudny katalog roboczy, tzn. zmiany nie dodane do repozytorium. Rozwiązaniem tego problemu jest utworzenie dwóch repozytoriów. Pierwsze repozytorium, nazwijmy je hub, jest repozytorium bare (tzn. bez katalogu roboczego) do którego wysyłamy zmiany z komputera lokalnego. Tworzymy je w lokalizacji niedostępnej dla serwera www, np. w katalogu domowym.

cd ~
mkdir projekt_x.git
cd projekt_x.git
git init --bare

Jeżeli używamy Git na serwerze po raz pierwszy, zostaniemy poproszeni o ustawienie nazwy i adresu email użytkownika, następnie możemy wykonać powyższe instrukcje. Drugie repozytorium (live) tworzymy w katalogu dostępnym dla serwera www, będzie to nasza wersja produkcyjna strony. Jest to już pełnoprawne repozytorium z katalogiem roboczym. Dodatkowo tworzymy pierwszy commit z pustym plikiem.

cd ~/domains/tomaszmazur.eu/public_html/
git init
touch empty
git add empty
git commit -m "Initial commit"

Musimy ustawić repozytorium hub jako zdalne repozytorium naszego nowo utworzonego repozytorium:

git remote add hub ~/projekt_x.git
git push hub +master:refs/heads/master

Już teraz każda zmiana dostępna w repozytorium hub, może zostać ściągnięta do repozytorium live. Chcemy jednak ten proces zautomatyzować, tak aby każda zmiana wysłana do hub była automatycznie pobierana przez live. W tym celu, w repozytorium hub tworzymy „hook” (skrypt) w pliku ~/projekt_x.git/hooks/post-update

#!/bin/sh
 
echo
echo "**** Pulling changes into Live [Hub's post-update hook]"
echo
 
cd ~/domains/tomaszmazur.eu/public_html || exit
unset GIT_DIR
git pull hub master
 
exec git-update-server-info

Skrypt ten będzie wykonany po każdej zmianie wysłanej do repozytorium hub. Skrypt przechodzi do repozytorium live, i pobiera zmiany z repozytorium hub. W sprytny sposób omijając niemożność wysłania zmian. 😉 Nie zapomnijmy nadać praw wykonywania:

chmod +x ~/projekt_x.git/hooks/post-update

Na serwerze wszystko jest już ustawione, pozostaje tylko skonfigurować Git na komputerze lokalnym, tak abyśmy mogli wysyłać zmiany do repozytorium hub.

Ustawienia lokalne

Przechodzimy do repozytorium na komputerze lokalnym za pomocą Windows PowerShell. Jeżeli nie mamy repozytorium to je tworzymy analogicznie jak wcześniej (dodajemy wszystkie niezbędne pliki do repozytorium i tworzymy pierwszy commit). Wystarczy skonfigurować repozytorium zdalne:

git remote add deploy ssh://login@serwer/sciezka/do/projekt_x.git
git push deploy +master:refs/heads/master

Całość naszego repozytorium lokalnego powinna zostać wysłana do naszego repozytorium hub, a stamtąd do repozytorium live. Żeby sprawdzić, czy wszystko przebiegło pomyślnie przechodzimy do repozytorium hub i sprawdzamy za pomocą komendy git log, historię commitów. Podobnie czynimy w repozytorium live, dodatkowo sprawdzamy czy pliki w tym repozytorium rzeczywiście istnieją.

Aktualizowanie strony live

Od tej chwili nanoszenie zmian (commitów) na wersję produkcyjną strony sprowadza się do wykonania komendy:

git push

Prawidłowo wykonana aktualizacja zwraca listę naniesionych zmian:git_push_success

Submodules – Sub moduły

Jeżeli nasz projekt posiada sub moduły, musimy pamiętać o tym, że nie zostaną one automatycznie zaktualizowane, ani zainicjowane w repozytorium live. Teoretycznie możemy odpowiednie komendy dodać do skryptu post-update, ale musimy się liczyć z konsekwencjami tego czynu (zawsze najbardziej aktualna wersja submodułów, niezależnie od wersji posiadanej na komputerze lokalnym). Z tego względu nie zdecydowałem się na automatyzację tej czynności. Przechodzimy do repozytorium live i uruchamiamy komendy:

git submodule init
git submodule update

Submoduły powinny zostać zaciągnięte z repozytoriów zdalnych.

Zabezpieczenie katalogu .git

Może się okazać, że nasz katalog .git w repozytorium live jest dostępny z poziomu przeglądarki internetowej. Blokujemy dostęp, tworząc lub modyfikując plik .htaccess:

RewriteEngine On
RewriteRule \.git - [F,L]

Uwagi końcowe

Należy pamiętać, że tak ustawiony system nie obsługuje aktualizacja/zmian bazy danych. Jeżeli wprowadzimy zmianę w strukturze bazy danych deweloperskiej, musimy pamiętać o naniesieniu tych zmian na bazę danych produkcyjną (z chwilą naniesienia odpowiednich zmian w kodzie). Mogą również wystąpić pewne problemy przy nanoszeniu zmian na repozytorium live, np. dodaliśmy do repozytorium nowy plik, który już istniał w katalogu roboczym repozytorium. Należy wtedy uruchomić Git w obrębie repozytorium live i ręcznie rozwiązać wszelkie konflikty.

Źródła:

  1. Using Git for Deployment – Dan Barber
  2. Using Git to manage a web site
  3. A web-focused Git workflow | Joe Maller

CKEditor: Sprawdzanie pisowni przez przeglądarkę

Sprawdzanie pisowni w CKEditor nie działa najlepiej, dodatkowo język polski nie jest domyślnie dostępny. Najprostszym rozwiązaniem tego problemu jest umożliwienie sprawdzania pisowni przez przeglądarkę. W pliku konfiguracyjnym CKEditor dodajemy ustawienia:

CKEDITOR.editorConfig = function( config )
{
    config.disableNativeSpellChecker = false;
    config.removePlugins = 'scayt,contextmenu';
};

W pierwszej linijce pozwalamy na sprawdzanie pisowni przez przeglądarkę. Kolejna linijka wyłącza scayt, czyli sprawdzanie pisowni wbudowane w CKEditor, oraz wyłącza własne menu kontekstowe w obrębie CKEditor. Ostatnią czynność wykonujemy po to, żeby po kliknięciu prawym przyciskiem myszy na podświetlony wyraz, można było zobaczyć podpowiedzi (przynajmniej tak to działa pod Firefox).

ckeditor_sprawdzanie_pisowni