Panowie z Daylight Studio właśnie ogłosili, że światło dzienne ujrzała finalna wersja FUEL CMS – oznaczona numerem 1.0. Jeśli nie mieliście jeszcze okazji zetknąć się z tym projektem, to teraz jest ku temu okazja. W związku z wydaniem, odświeżona został cała strona projektu oraz dokumentacja, która zyskała nowe rozdziały.
renholder
Git Deployment i CodeIgniter
Dzisiaj chciałbym Wam przedstawić w jaki sposób możemy sobie skonfigurować projekt, tak aby łatwo nam się współpracowało z repozytorium Git. Czym jest Git? W skrócie ujmując, jest to system kontroli wersji. Jeśli nie mieliście jeszcze z nim do czynienia, to zapraszam np. na Wikibooks, gdzie możecie uzupełnić swoją wiedzę w tym zakresie. Nie oczekujcie więc, jakiegoś specjalnego wprowadzenia do Git, ponieważ będę zakładał, że macie o tym jakieś pojęcie – tak więc przedstawione zostaną raczej tylko „suche” komendy. Dodatkowo zakładam, że Git jest już zainstalowany na Waszym komputerze (oraz skonfigurowany). Jeśli chcielibyście poznać Gita, to swoją przygodę możecie rozpocząć w tym miejscu.
Zaczniemy od tego, że potrzebne nam będzie repozytorium. Ja skorzystam z usług firmy Atlassian i ich projektu Bitbucket. Czemu? Dlatego, że oferuje darmowe prywatne repozytoria (a oprócz tego jest bardzo dobrym produktem). Tak więc rejestrujemy się i tworzymy repozytorium (może być prywatne). Teraz musimy dodać nasz klucz publiczny (używany na lokalnej maszynie) do Bitbucket. W tym celu musimy wejść do zakładki „Manage account”, a później „SSH keys”.
Jeśli mamy to już za sobą, możemy pobrać repozytorium do utworzonego wcześniej folderu na naszym komputerze. Będąc w folderze, wykonujemy polecenie:
git clone git@bitbucket.org:nazwa_uzytkownika/nazwa_repozytorium.git .
Możemy to również zrobić z poziomu naszego IDE (o ile posiada taką opcję) lub za pośrednictwem zewnętrznego klienta np. SourceTree (również ze stajni Atlassian).
Skoro repozytorium jest już na naszym komputerze, możemy przejść na serwer zewnętrzny. Potrzebny nam będzie oczywiście dostęp do SSH i zainstalowany Git. Po zalogowaniu na serwer musimy skonfigurować Gita (wygenerować klucze). W tym celu wykonamy polecenie:
ssh-keygen
Kiedy zostaniemy zapytani o passphrase po prostu wciśnijmy klawisz Enter i nic więcej (innymi słowy zostawiamy wyjątkowo pustą wartość). Kolejnym krokiem będzie skopiowanie zawartości pliku publicznego, który został wygenerowany (powinien znajdować się w /.ssh/id_rsa.pub). Klucz ten musimy dodać do naszego repozytorium na Bitbucket. W tym celu wchodzimy do repozytorium i klikamy na „trybik” po prawej stronie, który przeniesie nas do ustawień administracyjnych. Następnie wybieramy zakładkę „Deployment keys” i dodajemy nasz klucz publiczny. Teraz możemy wrócić z powrotem na serwer i wykonać polecenie:
ssh -T git@bitbucket.org
które sprawdzi, czy klucz się zgadza oraz doda domenę do rozpoznawalnych hostów.
To tyle. Możemy przejść do folderu na serwerze, w którym ma się znajdować nasz projekt i wykonać znaną nam już komendę:
git clone git@bitbucket.org:nazwa_uzytkownika/nazwa_repozytorium.git .
No dobrze, jeśli już mamy to za sobą, to możemy przystąpić do przygotowania samego CI. Wracamy na nasz lokalny serwer developerski i do folderu gdzie ma się znajdować nasz projekt wgrywamy „czysty” framework CodeIgniter. Teraz czeka nas znowu kilka zmian. Najpierw edytujemy plik .gitignore w głównym katalogu i dodajemy na końcu:
application/config/development/*
Ten plik informuje Gita, które pliki mają zostać pominięte w procesie synchronizacji. Nie chcemy przecież aby pliki cache i logi były udostępniane dalej z naszej maszyny developerskiej. Dodana linijka mówi rownież o ignorowaniu wszystkich plików z katalogu application/config/development, który będzie przez nas wykorzystywany do przechowywania ustawień konfiguracyjnych wyłącznie na naszej lokalnej maszynie developerskiej. Będziemy mogli w ten sposób łatwo odseparować dane dostępowe do bazy danych oraz inne ustawienia. Tak więc od razu możemy stworzyć katalog development i przekopiować tam plik application/config/database.php (oraz inne jeśli będzie taka potrzeba), a następnie odpowiednio zmodyfikować ich zawartość, tak aby odpowiadała ustawieniom naszego lokalnego serwera.
Domyślnie CodeIgniter uruchamia się w trybie developerskim, dlatego podczas pracy na lokalnym serwerze, zostaną użyte pliki z utworzonego przez nas przed chwilą folderu development. Pojawia się jednak problem, ponieważ na naszym serwerze docelowym (produkcyjnym) będziemy chcieli uruchamiać aplikację w trybie „production”. Na szczęście jest na to prosty sposób. Edytujemy plik index.php i zamieniamy linijkę o numerze 21 na następującą (nazwa domeny, to oczywiście tylko przykład i należy ją zmodyfikować do własnych potrzeb):
define('ENVIRONMENT', $_SERVER['SERVER_NAME'] === 'naszprojekt.pl' ? 'production' : 'development');
Dzięki temu, kiedy CI będzie uruchamiany na naszym serwerze produkcyjnym, zostanie uruchomiony w odpowiednim trybie.
No dobrze, pora na gwóźdź programu, czyli plik, który pozwoli nam na pobieranie zmian z repozytorium na serwer produkcyjny. Możemy zrobić to na kilka sposobów: utworzyć specjalny kontroler, albo osobny plik. Tym razem zdecydujemy się na utworzenie osobnego pliku, ponieważ jest to rozwiązanie bardziej uniwersalne i do tego pozwala na rożne podejście – umieszczenie pliku bezpośrednio w projekcie lub pod inną domeną lub subdomeną. Właśnie z tego ostatniego rozwiązanie skorzystamy, ponieważ jest bardziej eleganckie. Pora więc utworzyć plik deploy.php o następującej treści:
<?php
class Deploy
{
/**
* Funkcja zwrotna, która zostanie wywołana po pobraniu zmian.
*/
public $post_deploy;
/**
* Ścieżka do deployu
*/
public $deploy_path;
/**
* Ścieżka do logów
*/
public $log_path;
/**
* Nazwa dla branch.
*/
private $_branch = 'master';
/**
* Nazwa dla remote.
*/
private $_remote = 'origin';
/**
* __construct
*/
public function __construct($deploy, $log)
{
$this->deploy_path = $deploy;
$this->log_path = $log;
$this->log('Deployment rozpoczęty.');
}
/**
* Wykonanie pobrania z repozytorium
*/
public function pull()
{
try
{
chdir($this->deploy_path);
exec('git pull '.$this->_remote.' '.$this->_branch);
$this->log('Pobieranie zmian... ');
if (is_callable($this->post_deploy))
{
call_user_func($this->post_deploy);
}
$this->log('Deployment zakończony.');
}
catch (Exception $e)
{
$this->log($e);
}
}
/**
* Logowanie wykonywanych czynności
*
* @param string $message Informacja tekstowa
*/
public function log($message)
{
file_put_contents($this->log_path.'deploy.log', '['.date('Y-m-d H:i:s').'] - '.$message.PHP_EOL, FILE_APPEND);
}
}
// Ustawiamy strefę czasową na potrzeby logów
date_default_timezone_set('Europe/Warsaw');
// Rozpoczynamy deployment
// Jako parametry konstruktora musimy podać bezwzględną ścieżkę
// do repozytorium na naszym serwerze oraz do miejsca gdzie będą zapisywane logi
// poniższe dane to tylko przykład i należy je zmodyfikować do własnych potrzeb
$deploy = new Deploy('/home/nazwa_uzytkownika/public_html/naszprojekt.pl/', '/home/nazwa_uzytkownika/public_html/deploy.naszprojekt.pl/');
$deploy->post_deploy = function() use ($deploy) {
exec('php '.$deploy->deploy_path.'index.php migrations/latest', $output);
$deploy->log('Migracja bazy danych... '.implode(' ', $output));
};
$deploy->pull();
To bardzo podstawowe rozwiązanie – z łatwością znajdziemy w sieci bardziej rozbudowane, ale do naszych skromnych potrzeb powinno wystarczyć. Powyższy plik umieścimy w subdomenie np: deploy.naszprojekt.pl. Pamiętajmy również o utworzeniu pliku deploy.log, w którym będą zapisywane rezultaty naszych działań. Do tego wszystkiego dołączymy specjalny plik .htaccess, który pozwoli na dostęp do naszego pliku tylko z określonych adresów IP (z których korzysta Bitbucket):
Deny from all # Bitbucket Posthook IP Allow from 131.103.20.165 Allow from 131.103.20.166
Wróćmy jeszcze na chwilę do opcji post_deploy z naszego skryptu. Jest to bardzo fajne rozwiązanie, ponieważ po pobraniu zmian z repozytorium mamy możliwość wykonania dodatkowych operacji (w całkiem elegancki sposób). Jak widać korzystamy z tego, aby wykonać metodę latest z kontrolera migrations. Oczywiście nadeszła pora, aby ten kontroler utworzyć – jest on bardzo podobny do tego, którego używaliśmy kiedyś w jednej z części blog tutorialu:
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Migrations extends CI_Controller
{
/**
* __construct
*/
public function __construct()
{
parent::__construct();
if ( ! $this->input->is_cli_request())
{
show_404();
}
$this->load->library('migration');
}
/**
* Migruje bazę danych do ostatniej dostępnej wersji
*/
public function latest()
{
if ( ! $this->migration->current())
{
echo $this->migration->error_string();
}
else
{
echo 'Poprawnie wykonano migracje bazy danych, do ostatniej dostepnej wersji.';
}
}
/**
* Migruje bazę do wersji podanej w parametrze
*
* @param int Numer wersji
*/
public function version($number)
{
if ( ! $this->migration->version($number))
{
echo $this->migration->error_string();
}
else
{
echo 'Poprawnie wykonano migracje bazy danych do wersji '. $number;
}
}
}
/* End of file migrations.php */
/* Location: ./application/controllers/migrations.php */
Oczywiście jeśli nie zamierzamy stosować migracji w swoim projekcie, to możemy tę opcję najzwyczajniej pominąć, chociaż osobiście uważam to za bardzo poręczne rozwiązanie, bez którego wręcz trudno się obyć podczas pracy w kilka osób. Na jakiej zasadzie to działa? Zakładamy, że wszystkie zmiany w strukturze bazy danych (ewentualnie również w przypadku domyślnych danych) odbywają się za pomocą migracji.
W pliku application/config/migration.php mamy zmienną $config['migration_version'], która odpowiada za numer aktualnej migracji. Po przesłaniu zmian do repozytorium, migracje na serwerze zostaną automatycznie zaktualizowane do tego właśnie numeru (za sprawą naszego skryptu). Po więcej informacji na temat migracji odsyłam do tego rozdziału z podręcznika.
W tym momencie pozwolę sobie założyć, że mamy utworzoną naszą przykładową subdomenę deploy.naszprojekt.pl oraz wgrane tam pliki: deploy.php, deploy.log oraz .htaccess. Teraz pozostało nam określenie czegoś co nazywa się Post Delpoyment Hook, czyli inaczej mówiąc, określenie adresu, który ma zostać wywołany w momencie kiedy prześlemy nasze zmiany do repozytorium – pozwoli to na odpalenie pliku deploy.php, którym zajmowaliśmy się powyżej. Aby tego dokonać, na stronie naszego repozytorium na Bitbucket, ponownie przechodzimy do ustawień („trybik” po prawej stronie) i tym razem wybieramy z menu opcję „Hooks”. Następnie w polu select zaznaczamy opcję „POST” i dodajemy adres URL, który ma zostać wywołany, czyli w naszym przypadku: http://deploy.naszprojekt.pl/deploy.php.
Co nam teraz pozostało? Jeśli korzystamy z migracji, to wypadałoby upewnić się, że dobrze skonfigurowaliśmy dane dostępowe do bazy danych na serwerze produkcyjnym (oraz utworzyliśmy bazę) i włączyliśmy obsługę migracji. Jeśli wszystko sprawdzone, to możemy zaczynać. Na naszej lokalnej maszynie, w głównym folderze naszej aplikacji wykonujemy kolejno komendy:
git add . git commit -m 'Pierwszy commit' git push origin master
W tym momencie dodaliśmy i wysłaliśmy zmiany do repozytorium na Bitbucket. Jeśli wszystko poszło po naszej myśli, to po tej czynności powinno nastąpić wywołanie adresu http://deploy.naszprojekt.pl/deploy.php. Plik deploy.php wykona następujące czynności: pobierze najnowsze zmiany z repozytorium oraz „odpali” kontroler z migracjami. Dzięki temu zarówno nasz kod jak i baza danych zostaną zsynchronizowane.
To tyle. Mam nadzieję, że tym wpisem udało mi się zachęcić Was do korzystania z Git w codziennej pracy lub chociażby zainteresować tym tematem.
Bonfire 0.7 wydane
Niedawno ukazała się nowa wersja Bonfire o numerze 0.7. Wedle zapowiedzi, to początek większych zmian jakie mają zachodzić w projekcie – jest też już nowa strona internetowa. Wygląda na to, że twórcy w końcu znaleźli na tylke wolnego czasu, aby pchnąć projekt na nowe tory. Ważnym elementem jest to, że główny developer projektu Lonnie Ezell, zdecydował się na dosyć ryzykowny krok i zapowiedział, że nie będzie się trzymał sztywno CI i jeśli będzie taka potrzeba, to nie zawaha się wprowadzić koniecznych zmiany do core.
Ta zapowiedź właściwie już się spełniła. Zmiany w core są naprawdę symboliczne i sprowadzają się do możliwości całkowitego odseparowania plików Bonfire od naszego projektu. Dalej, mamy zmiany w wyglądzie, przejście na bibliotekę phpass przy przechowywaniu haseł oraz wiele innych pomniejszych zmian. Niestety, tak jak zapowiadano, migracja do najnowszej wersji wcale nie będzie banalnie prosta (m.in. z racji reorganizacji struktury). Z innych zmian, które dopiero nadejdą, mamy całkiem nową bibliotekę routingu, która daje nam kilka naprawdę fajnych możliwości oraz rozszerzenie HMVC, które jest w pewnym sensie połączeniem rozwiązania, które stworzył Wiredesignz oraz Jens Segers.
Doczekaliśmy się również zapowiedzi tego, co ma się pojawić w najbliższych wydaniach:
- 0.7.1 – nowy, lżejszy system menu (który ma zastąpić konteksty) oraz biblioteka autoryzacji oparta o sterownik.
- 0.7.2 – lepsze wsparcie dla lokalizacji oraz stref czasowych
Co ważne, nowe biblioteki, o które wzbogacił sie ostatnio projekt (będzie) można bez większego problemu wykorzystać we własnych projektach, które niekoniecznie muszą być oparte o Bonfire.
Ze swojej strony mogę powiedzieć, że chociaż Bonfire nie używam, to kibicuję temu projektowi, bo kiedyś może być to naprawdę fajny system do tworzenia aplikacji. Aby poznać więcej szczegółów, zachęcam do zapoznania się z ostatnimi wpisami, które pojawiły się na blogu Bonfire.
Biblioteka Template
O bibliotece Template wspominałem już nieraz na forum. Tym razem jednak chciałbym przedstawić ją trochę dokładniej, tak abyście mieli możliwość łatwego rozpoczęcia pracy. Autorem tej biblioteki jest Phil Sturgeon, którego pewnie niektórzy z Was kojarzą m.in. jako pomysłodawcę projektu PyroCMS. Sama biblioteka ma już kilka lat, ale z powodzeniem można z niej korzystać w swoich projektach, kiedy potrzebujemy trochę bardziej złożonej funkcjonalności jeśli chodzi o widoki.
EllisLab żegna się z CodeIgniter
EllisLab ogłosił właśnie, że poszukuje nowego właściciela dla frameworka CodeIgniter, który miałby przejąć i poprowadzi dalszy rozwój tego projektu. Od dawna wiadomo, że EllisLab skupia się na swoim flagowym systemie CMS ExpressionEngine, co z biznesowego punku widzenia jest nawet zrozumiałe. Prowadzi to jednak do tego, że „moce przerobowe” nie pozwalają na dostateczne skupienie się na rozwoju samego frameworka. Właśnie to miało skłonić EllisLab do podjęcia takiej decyzji.
Warto zwrócić uwagę, że właściwie od dwóch lat wkład ekipy z EllisLab w rozwój frameworka jest raczej znikomy. Łatwo to potwierdzić spoglądając na branch: develop na github. Przysłowiową pałeczkę przejęła społeczność. Niemniej oznacza to koniec pewnych czasów… Co z tego wyniknie? Na razie trudno powiedzieć. Czas pokaże. Szkoda tylko, że nie podjęto tej decyzji wcześniej.
Link do wpisu na blogu EllisLab.