Developer%27s environment setup - iiuni/projektzapisy GitHub Wiki
System Zapisów jest napisaną w Pythonie aplikacją serwerową. Na serwerze produkcyjnym (czyli w realu) uruchamiamy go za pomocą serwera Gunicorn ukrytego za Nginx'em. Stanem aplikacji zarządza serwer Postgresql.
Maszyna dla developera jest skonfigurowana tak, by nie różnić się zanadto od serwera produkcyjnego, ale jednocześnie być łatwą w użyciu i wygodną dla programisty. Nie wymaga od programisty żadnego konfigurowania ani wydawania wielu komend.
Na swoim komputerze musimy mieć zainstalowany Virtualbox, który pozwala nam uruchamiać maszyny wirtualne, oraz Vagrant, który potrafi tymi maszynami zarządzać i je łatwo konfigurować. W naszym projekcie mamy taką konfigurację, w pliku Vagrantfile
. Oba programy da się zainstalować na każdym sensownym systemie operacyjnym — w Ubuntu można skorzystać z wersji w repozytorium:
ja@mojkomputer:~$ sudo apt install virtualbox vagrant
Analogicznie polecenia na Windowsie:
PS C:\Users\user> winget install vagrant
PS C:\Users\user> winget install virtualbox
Klonujemy niniejsze repozytorium na swój komputer. Następnie otwieramy terminal w jego głównym katalogu (albo którymkolwiek podkatalogu) i wydajemy polecenie:
ja@mojkomputer:projektzapisy$ vagrant up
Vagrant ściągnie z internetu świeży obraz maszyny wirtualnej z systemem Ubuntu, a następnie uruchomi proces instalacji (prawie) wszystkiego, co jest potrzebne by System Zapisów działał. Ten proces nazywa się provisioning i został przez nas zaprogramowany w playbooku Ansible.
Gdy provisioning się zakończy i powyższe kroki zostaną wykonane, może konieczne być wykonanie polecenia:
ja@mojkomputer:projektzapisy$ vagrant reload
Gdy proces się zakończy, należy chwilkę odczekać, a następnie wejść (z komputera-hosta) na adres http://0.0.0.0:8000 (lub localhost:8000), gdzie nasłuchuje serwer testowy naszej aplikacji (uruchomiony w maszynie wirtualnej).
Przed uruchomieniem maszyny warto ściągnąć obraz bazy danych (link można znaleźć na Slacku, na kanale #db_backups
), rozpakować go i umieścić (plik ii_zapisy_dump_dev.sql
) w głównym katalogu projektzapisy/
. Provisioner instalujący oprogramowanie wychwyci ten plik i załaduje go do maszyny wirtualnej.
Obraz bazy jest zanonimizowany. Zamazane są w nim nazwiska, adresy email i inne „wrażliwe” dane. Hasła wszystkich użytkowników są zamienione na pass
. Użytkownikami z uprawnieniami administratora są np. mbiernacka
, asm
.
Maszynę wirtualną można wyłączyć poleceniem vagrant halt
lub nawet zniszczyć, poleceniem vagrant destroy
. Odpalenie polecenia vagrant provision
gdy maszyna jest uruchomiona spowoduje powtórzenie procesu instalacji — można to zrobić, gdy nasz playbook uległ zmianie, albo gdy chcemy załadować od nowa bazę danych.
W konfiguracji Vagranta katalog projektu (czyli projektzapisy/
) na naszym komputerze jest zmapowany do /vagrant/
w maszynie wirtualnej. W maszynie wirtualnej uruchomione są dwie istotne dla nas usługi systemowe:
- Serwer testowy naszej aplikacji zapisy, uruchomiony za pomocą polecenia
python manage.py runserver
z katalogu/vagrant/zapisy/
. Serwer ten jest zdecydowanie mniej wydajny niż ten produkcyjny, ale za to przeładowuje aplikację zawsze, gdy zmieni się jej kod. Dzięki temu możemy programować (na maszynie hosta) i na żywo widzieć efekty. - Kompilator assetów (Javascript/Typescript/Vue/style) obserwujący zmiany w plikach. Uruchomiony za pomocą polecenia
yarnpkg dev:watch
. Dzięki temu możemy programować we front-endzie i na żywo widzieć efekty (więcej informacji: Praca nad front-endem).
-
Live-kompilator assetów nie poradzi sobie, gdy dodajemy nowy bundle (w pliku
asset-defs.js
) lub jakieś zależności (do plikupackage.json
). Musimy wtedy zrestartować maszynę wirtualną (poleceniemvagrant reload
). -
Gdy dodajemy jakąś zależność Pythonową (do plików
requirements.*.txt
), musimy przeprowadzić jeszcze raz provisioning. -
Jeśli chcemy, by Django wygenerowało nam migracje po zmianach w strukturze bazy danych, musimy zalogować się do maszyny wirtualnej:
ja@mojkomputer:projektzapisy$ vagrant ssh
wewnątrz maszyny wirtualnej wchodzimy do katalogu
/vagrant/zapisy
i odpalamy polecenie:(env3) vagrant@ubuntu-focal:/vagrant/zapisy$ python manage.py makemigrations
-
Aby przetestować nasze zmiany na backendzie, należy skorzystać z unit testów. Aby je wywołać, należy wewnątrz maszyny wirtualnej wejść do katalogu
/vagrant/zapisy
i odpalić polecenie:(env3) vagrant@ubuntu-focal:/vagrant/zapisy$ python manage.py test
Komenda ta odpala wszystkie testy i informuje nas o ich wyniku. Jeżeli zmieniamy lub dodajemy nową logikę należy zmodyfikować/dodać nowe testy pokrywające wszystkie przypadki. Więcej o unit testach w Django i w Pythonie.
-
Jeśli maszyna wirtualna zacina się podczas provisioningu (na przykład na kroku Gathering facts), warto go przerwać (Ctrl+C) i uruchomić od nowa (
vagrant provision
). -
Łączenie się z deweloperską bazą danych zostało opisane na osobnej stronie wiki: Łączenie się z serwerem bazy danych środowiska deweloperskiego
-
Użytkownicy Windowsa napotykają często na bardzo trudne do zdiagnozowania kłopoty związane z kodowaniem końca linii. W Windowsie koniec linii koduje się za pomocą
\r\n
(CRLF — carriage return, line feeed), zaś w Uniksie/Linuksie tylko za pomocą\n
(LF). Nasz kod jest uruchamiany na Linuksie, więc w naszym projekcie trzymamy się standardu uniksowego. Git na Windowsie próbuje być jednak mądrzejszy i przy klonowaniu repozytorium zamienia\n
na\r\n
— co prowadzi do problemów z maszyną wirtualną. By upewnić się, że:- Klonujemy pliki bez konwertowania, oraz;
- Nie wrzucamy do repozytorium plików z windowsowymi końcami linii;
Należy ustawienie Git-a
core.autocrlf
ustawić nainput
. -
Użytkownicy Windows 11 mogą napotkać na problemy związane z wydajnością maszyn wirtualnych uruchamianych w VirtualBoxie, w szczególności naszej deweloperskiej wersji systemu zapisów. Jeśli maszyna uruchamia się podejrzanie długo, a w jej podglądzie w VB widzimy ikonkę żółwika w prawym dolnym rogu, to należy się upewnić, że wyłączona jest opcja "Integralność pamięci" pod "Ustawienia / Prywatność i zabezpieczenia / Zabezpieczenia Windows / Zabezpieczenia urządzenia / Izolacja rdzenia", która może uniemożliwić VirtualBoxowi korzystanie z odpowiedniej akceleracji. Ponadato w "Funkcjach systemu Windows" ("Panel Sterowania / Programy / Włącz lub wyłącz funkcje systemu Windows") należy wyłączyć trzy opcje: "Platforma maszyny wirtualnej", "Podsystem Windows dla systemu Linux" oraz "Hyper-V", a następnie zrestartować komputer. Wtedy zamiast ikonki żółwika powinna się pojawić biała literka "V" na niebieskim tle (czwarta ikonka od prawej w panelu VB).
-
Jeśli nie korzystamy z IDE (np. VS Code) z odpowiednio skonfigurowanymi wtyczkami lintera, warto osobno sprawdzić formatowanie kodu przed spushowaniem zmian (w przeciwnym wypadku ryzykujemy, że niezgodności zostaną wykryte dopiero przez GitHub Actions, dostaniemy o tym niepokojącego maila, i będziemy trzeba zrobić kolejny push). Najłatwiej zrobić to łącząc się z maszyną wirtualną (
vagrant ssh
) i wykonując w jej katalogu/vagrant/zapisy
polecenia$ python3 -m flake8 --statistics . $ yarnpkg prettier --check apps/
które skontrolują odpowiednio źródła Pythona oraz JS itp. (w tym drugim przypadku tylko w podkatalogu
apps/
; inne rzeczy, m.in. automatycznie wygenerowane, nas nie interesują). Ew. błędy w Pythonie należy skorygować ręcznie; dla JS trzeba (!) użyć polecenia$ yarnpkg prettier --write apps/
(i oczywiście scommitować zmiany). Analogiczne polecenia można wykonać na maszynie macierzystej, choć mogą wkraść się różnice m.in. w konfiguracji linterów czy nawet nazwach poleceń (w innych niż Ubuntu dystrybucjach
yarnpkg
może nazywać sięyarn
). -
Tam, gdzie "normalnie" użylibyśmy funkcji
print
do debugowania Pythonowych skryptów, warto zamiast tego użyć mechanizmu logów zapewnionego przez modułlogging
ze standardowej biblioteki (używanego już zresztą bezpośrednio przez Django i dodatkowo w kilku miejscach jawnie w kodzie SZ), na przykład tak:import logging logger = logging.getLogger(__name__) logger.info('Hello, world!')
Informacja trafi do pliku wskazanego w konfiguracji w
settings.py
(słownikLOGGING
), czyli, o ile nic tam się nie zmieni, dozapisy/logs/djangoproject.log
.To, co skrypty piszą na
stderr
(ale z jakiegoś powodu już nie nastdout
), dostępne jest przezjournalctl
zgodnie z działaniemsystemd
, jako którego usługa uruchamiany jest serwer Django. Możemy więc zamiast powyższego faktycznie użyć funkcjiprint
(z kwargumentemfile=sys.stderr
), a potem na maszynie wirtualnej (vagrant ssh
) wykonaćsudo journalctl -u runserver.service
.
Pierwszy set-up z użyciem Vagranta wprowadził do naszego projektu @florczakraf. Obecne rozwiązanie z użyciem Ansible (i nie wymagające logowania się do maszyny wirtualnej) stworzyli @barnij i @receek (#888).